Home | History | Annotate | Download | only in hal
      1 /*
      2  * Copyright (C) 2012-2014 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <phNxpNciHal_NfcDepSWPrio.h>
     18 #include <phNxpLog.h>
     19 #include <phNxpNciHal.h>
     20 
     21 #define CUSTOM_POLL_TIMEOUT 160    /* Timeout value to wait for NFC-DEP detection.*/
     22 #define CLEAN_UP_TIMEOUT 250
     23 #define MAX_WRITE_RETRY 5
     24 
     25 /******************* Global variables *****************************************/
     26 extern phNxpNciHal_Control_t nxpncihal_ctrl;
     27 extern NFCSTATUS phNxpNciHal_send_ext_cmd(uint16_t cmd_len, uint8_t *p_cmd);
     28 static uint8_t cmd_stop_rf_discovery[] = { 0x21, 0x06, 0x01, 0x00 }; /* IDLE */
     29 static uint8_t cmd_resume_rf_discovery[] = { 0x21, 0x06, 0x01, 0x03 }; /* RF_DISCOVER */
     30 
     31 /*RF_DISCOVER_SELECT_CMD*/
     32 static uint8_t cmd_select_rf_discovery[] = {0x21,0x04,0x03,0x01,0x04,0x02 };
     33 
     34 static uint8_t cmd_poll[64];
     35 static uint8_t cmd_poll_len = 0;
     36 int discover_type = 0xFF;
     37 uint32_t cleanup_timer;
     38 
     39 /*PRIO LOGIC related dead functions undefined*/
     40 #ifdef P2P_PRIO_LOGIC_HAL_IMP
     41 
     42 static int iso_dep_detected = 0x00;
     43 static int poll_timer_fired = 0x00;
     44 static uint8_t bIgnorep2plogic = 0;
     45 static uint8_t *p_iso_ntf_buff = NULL; /* buffer to store second notification */
     46 static uint8_t bIgnoreIsoDep = 0;
     47 static uint32_t custom_poll_timer;
     48 
     49 /************** NFC-DEP SW PRIO functions ***************************************/
     50 
     51 static NFCSTATUS phNxpNciHal_start_polling_loop(void);
     52 static NFCSTATUS phNxpNciHal_stop_polling_loop(void);
     53 static NFCSTATUS phNxpNciHal_resume_polling_loop(void);
     54 static void phNxpNciHal_NfcDep_store_ntf(uint8_t *p_cmd_data, uint16_t cmd_len);
     55 
     56 
     57 /*******************************************************************************
     58 **
     59 ** Function         cleanup_timer_handler
     60 **
     61 ** Description      Callback function for cleanup timer.
     62 **
     63 ** Returns          None
     64 **
     65 *******************************************************************************/
     66 static void cleanup_timer_handler(uint32_t timerId, void *pContext)
     67 {
     68     NXPLOG_NCIHAL_D(">> cleanup_timer_handler.");
     69 
     70     NXPLOG_NCIHAL_D(">> cleanup_timer_handler. ISO_DEP not detected second time.");
     71 
     72     phOsalNfc_Timer_Delete(cleanup_timer);
     73     cleanup_timer=0;
     74     iso_dep_detected = 0x00;
     75     EnableP2P_PrioLogic = FALSE;
     76     return;
     77 }
     78 
     79 /*******************************************************************************
     80 **
     81 ** Function         custom_poll_timer_handler
     82 **
     83 ** Description      Callback function for custom poll timer.
     84 **
     85 ** Returns          None
     86 **
     87 *******************************************************************************/
     88 static void custom_poll_timer_handler(uint32_t timerId, void *pContext)
     89 {
     90     NXPLOG_NCIHAL_D(">> custom_poll_timer_handler.");
     91 
     92     NXPLOG_NCIHAL_D(">> custom_poll_timer_handler. NFC_DEP not detected. so giving early chance to ISO_DEP.");
     93 
     94     phOsalNfc_Timer_Delete(custom_poll_timer);
     95 
     96     if (iso_dep_detected == 0x01)
     97     {
     98         poll_timer_fired = 0x01;
     99 
    100         /*
    101          * Restart polling loop.
    102          * When the polling loop is stopped, polling will be restarted.
    103          */
    104         NXPLOG_NCIHAL_D(">> custom_poll_timer_handler - restart polling loop.");
    105 
    106         phNxpNciHal_stop_polling_loop();
    107     }
    108     else
    109     {
    110         NXPLOG_NCIHAL_E(">> custom_poll_timer_handler - invalid flag state (iso_dep_detected)");
    111     }
    112 
    113     return;
    114 }
    115 /*******************************************************************************
    116 **
    117 ** Function         phNxpNciHal_stop_polling_loop
    118 **
    119 ** Description      Sends stop polling cmd to NFCC
    120 **
    121 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
    122 **
    123 *******************************************************************************/
    124 static NFCSTATUS phNxpNciHal_stop_polling_loop()
    125 {
    126     NFCSTATUS status = NFCSTATUS_SUCCESS;
    127     phNxpNciHal_Sem_t cb_data;
    128     pthread_t pthread;
    129     discover_type = STOP_POLLING;
    130 
    131     pthread_attr_t attr;
    132     pthread_attr_init (&attr);
    133     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    134     if (pthread_create (&pthread, &attr, tmp_thread, (void*) &discover_type) != 0)
    135     {
    136         NXPLOG_NCIHAL_E("fail to create pthread");
    137     }
    138     pthread_attr_destroy (&attr);
    139     return status;
    140 }
    141 
    142 /*******************************************************************************
    143 **
    144 ** Function         phNxpNciHal_resume_polling_loop
    145 **
    146 ** Description      Sends resume polling cmd to NFCC
    147 **
    148 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
    149 **
    150 *******************************************************************************/
    151 static NFCSTATUS phNxpNciHal_resume_polling_loop()
    152 {
    153     NFCSTATUS status = NFCSTATUS_SUCCESS;
    154     phNxpNciHal_Sem_t cb_data;
    155     pthread_t pthread;
    156     discover_type = RESUME_POLLING;
    157 
    158     pthread_attr_t attr;
    159     pthread_attr_init (&attr);
    160     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    161     if (pthread_create (&pthread, &attr, tmp_thread, (void*) &discover_type) != 0)
    162     {
    163         NXPLOG_NCIHAL_E("fail to create pthread");
    164     }
    165     pthread_attr_destroy (&attr);
    166     return status;
    167 }
    168 
    169 /*******************************************************************************
    170 **
    171 ** Function         phNxpNciHal_start_polling_loop
    172 **
    173 ** Description      Sends start polling cmd to NFCC
    174 **
    175 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
    176 **
    177 *******************************************************************************/
    178 NFCSTATUS phNxpNciHal_start_polling_loop()
    179 {
    180     NFCSTATUS status = NFCSTATUS_FAILED;
    181     phNxpNciHal_Sem_t cb_data;
    182     pthread_t pthread;
    183     discover_type = START_POLLING;
    184 
    185     pthread_attr_t attr;
    186     pthread_attr_init (&attr);
    187     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    188     if (pthread_create (&pthread, &attr, tmp_thread, (void*) &discover_type) != 0)
    189     {
    190         NXPLOG_NCIHAL_E("fail to create pthread");
    191     }
    192     pthread_attr_destroy (&attr);
    193     return status;
    194 }
    195 
    196 /*******************************************************************************
    197 **
    198 ** Function         phNxpNciHal_NfcDep_rsp_ext
    199 **
    200 ** Description      Implements algorithm for NFC-DEP protocol priority over
    201 **                  ISO-DEP protocol.
    202 **                  Following the algorithm:
    203 **                  IF ISO-DEP detected first time,set the ISO-DEP detected flag
    204 **                  and resume polling loop with 60ms timeout value.
    205 **                      a) if than NFC-DEP detected than send the response to
    206 **                       libnfc-nci stack and stop the timer.
    207 **                      b) if NFC-DEP not detected with in 60ms, than restart the
    208 **                          polling loop to give early chance to ISO-DEP with a
    209 **                          cleanup timer.
    210 **                      c) if ISO-DEP detected second time send the response to
    211 **                          libnfc-nci stack and stop the cleanup timer.
    212 **                      d) if ISO-DEP not detected with in cleanup timeout, than
    213 **                          clear the ISO-DEP detection flag.
    214 **
    215 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
    216 **
    217 *******************************************************************************/
    218 NFCSTATUS phNxpNciHal_NfcDep_rsp_ext(uint8_t *p_ntf, uint16_t *p_len)
    219 {
    220     NFCSTATUS status = NFCSTATUS_INVALID_PARAMETER;
    221 
    222     NXPLOG_NCIHAL_D(">> p_ntf[0]=%02x , p_ntf[1]=%02x",p_ntf[0],p_ntf[1]);
    223 
    224     if(p_ntf[0] == 0x41 && p_ntf[1] == 0x04)
    225     {
    226         //Tag selected, Disable P2P Prio logic.
    227         bIgnoreIsoDep = 1;
    228         NXPLOG_NCIHAL_D(">> Tag selected, Disable P2P Prio logic.");
    229 
    230     }
    231     else if( ((p_ntf[0] == 0x61 && p_ntf[1] == 0x06) ||
    232             (p_ntf[0] == 0x41 && p_ntf[1] == 0x06) ) && bIgnoreIsoDep == 1
    233             )
    234     {
    235         //Tag deselected, enable P2P Prio logic.
    236         bIgnoreIsoDep = 0x00;
    237         NXPLOG_NCIHAL_D(">> Tag deselected, enable P2P Prio logic.");
    238 
    239     }
    240     if (bIgnoreIsoDep == 0x00 &&
    241             p_ntf[0] == 0x61 &&
    242             p_ntf[1] == 0x05 && *p_len > 5)
    243     {
    244         if (p_ntf[5] == 0x04 && p_ntf[6] < 0x80)
    245         {
    246             NXPLOG_NCIHAL_D(">> ISO DEP detected.");
    247 
    248             if (iso_dep_detected == 0x00)
    249             {
    250                 NXPLOG_NCIHAL_D(
    251                         ">> ISO DEP detected first time. Resume polling loop");
    252 
    253                 iso_dep_detected = 0x01;
    254                 status = phNxpNciHal_resume_polling_loop();
    255 
    256                 custom_poll_timer = phOsalNfc_Timer_Create();
    257                 NXPLOG_NCIHAL_D("custom poll timer started - %d", custom_poll_timer);
    258 
    259                 status = phOsalNfc_Timer_Start(custom_poll_timer,
    260                         CUSTOM_POLL_TIMEOUT,
    261                         &custom_poll_timer_handler,
    262                         NULL);
    263 
    264                 if (NFCSTATUS_SUCCESS == status)
    265                 {
    266                     NXPLOG_NCIHAL_D("custom poll timer started");
    267                 }
    268                 else
    269                 {
    270                     NXPLOG_NCIHAL_E("custom poll timer not started!!!");
    271                     status  = NFCSTATUS_FAILED;
    272                 }
    273 
    274                 status = NFCSTATUS_FAILED;
    275             }
    276             else
    277             {
    278                 NXPLOG_NCIHAL_D(">> ISO DEP detected second time.");
    279                 /* Store notification */
    280                 phNxpNciHal_NfcDep_store_ntf(p_ntf, *p_len);
    281 
    282                 /* Stop Cleanup_timer */
    283                 phOsalNfc_Timer_Stop(cleanup_timer);
    284                 phOsalNfc_Timer_Delete(cleanup_timer);
    285                 cleanup_timer=0;
    286                 EnableP2P_PrioLogic = FALSE;
    287                 iso_dep_detected = 0;
    288                 status = NFCSTATUS_SUCCESS;
    289             }
    290         }
    291         else if (p_ntf[5] == 0x05)
    292         {
    293             NXPLOG_NCIHAL_D(">> NFC-DEP Detected - stopping the custom poll timer");
    294 
    295             phOsalNfc_Timer_Stop(custom_poll_timer);
    296             phOsalNfc_Timer_Delete(custom_poll_timer);
    297             EnableP2P_PrioLogic = FALSE;
    298             iso_dep_detected = 0;
    299             status = NFCSTATUS_SUCCESS;
    300         }
    301         else
    302         {
    303             NXPLOG_NCIHAL_D(">>  detected other technology- stopping the custom poll timer");
    304             phOsalNfc_Timer_Stop(custom_poll_timer);
    305             phOsalNfc_Timer_Delete(custom_poll_timer);
    306             EnableP2P_PrioLogic = FALSE;
    307             iso_dep_detected = 0;
    308             status = NFCSTATUS_INVALID_PARAMETER;
    309         }
    310     }
    311     else if( bIgnoreIsoDep == 0x00 &&
    312             ((p_ntf[0] == 0x41 && p_ntf[1] == 0x06) || (p_ntf[0] == 0x61
    313             && p_ntf[1] == 0x06))
    314             )
    315     {
    316         NXPLOG_NCIHAL_D(">> RF disabled");
    317         if (poll_timer_fired == 0x01)
    318         {
    319             poll_timer_fired = 0x00;
    320 
    321             NXPLOG_NCIHAL_D(">>restarting polling loop.");
    322 
    323             /* start polling loop */
    324             phNxpNciHal_start_polling_loop();
    325             EnableP2P_PrioLogic = FALSE;
    326             NXPLOG_NCIHAL_D (">> NFC DEP NOT  detected - custom poll timer expired - RF disabled");
    327 
    328             cleanup_timer = phOsalNfc_Timer_Create();
    329 
    330             /* Start cleanup_timer */
    331             NFCSTATUS status = phOsalNfc_Timer_Start(cleanup_timer,
    332                     CLEAN_UP_TIMEOUT,
    333                     &cleanup_timer_handler,
    334                     NULL);
    335 
    336             if (NFCSTATUS_SUCCESS == status)
    337             {
    338                 NXPLOG_NCIHAL_D("cleanup timer started");
    339             }
    340             else
    341             {
    342                 NXPLOG_NCIHAL_E("cleanup timer not started!!!");
    343                 status  = NFCSTATUS_FAILED;
    344             }
    345 
    346             status = NFCSTATUS_FAILED;
    347         }
    348         else
    349         {
    350             status = NFCSTATUS_SUCCESS;
    351         }
    352     }
    353     if (bIgnoreIsoDep == 0x00 &&
    354             iso_dep_detected == 1)
    355     {
    356         if ((p_ntf[0] == 0x41 && p_ntf[1] == 0x06) || (p_ntf[0] == 0x61
    357                 && p_ntf[1] == 0x06))
    358         {
    359             NXPLOG_NCIHAL_D(">>iso_dep_detected Disconnect related notification");
    360             status = NFCSTATUS_FAILED;
    361         }
    362         else
    363         {
    364             NXPLOG_NCIHAL_W("Never come here");
    365         }
    366     }
    367 
    368     return status;
    369 }
    370 /*******************************************************************************
    371 **
    372 ** Function         phNxpNciHal_NfcDep_store_ntf
    373 **
    374 ** Description      Stores the iso dep notification locally.
    375 **
    376 ** Returns          None
    377 **
    378 *******************************************************************************/
    379 static void phNxpNciHal_NfcDep_store_ntf(uint8_t *p_cmd_data, uint16_t cmd_len)
    380 {
    381     p_iso_ntf_buff = NULL;
    382 
    383     p_iso_ntf_buff = malloc(sizeof (uint8_t) * cmd_len);
    384     if (p_iso_ntf_buff == NULL)
    385     {
    386         NXPLOG_NCIHAL_E("Error allocating memory (p_iso_ntf_buff)");
    387         return;
    388     }
    389     memcpy(p_iso_ntf_buff, p_cmd_data, cmd_len);
    390     bIgnorep2plogic = 1;
    391 }
    392 
    393 /*******************************************************************************
    394 **
    395 ** Function         phNxpNciHal_NfcDep_comapre_ntf
    396 **
    397 ** Description      Compare the notification with previous iso dep notification.
    398 **
    399 ** Returns          NFCSTATUS_SUCCESS if successful,otherwise NFCSTATUS_FAILED
    400 **
    401 *******************************************************************************/
    402 NFCSTATUS phNxpNciHal_NfcDep_comapre_ntf(uint8_t *p_cmd_data, uint16_t cmd_len)
    403 {
    404    NFCSTATUS status = NFCSTATUS_FAILED;
    405    int32_t ret_val = -1;
    406 
    407    if (bIgnorep2plogic == 1)
    408    {
    409         ret_val = memcmp(p_cmd_data,p_iso_ntf_buff, cmd_len);
    410         if(ret_val != 0)
    411         {
    412             NXPLOG_NCIHAL_E("Third notification is not equal to last");
    413         }
    414         else
    415         {
    416             NXPLOG_NCIHAL_E("Third notification is equal to last (disable p2p logic)");
    417             status = NFCSTATUS_SUCCESS;
    418         }
    419         bIgnorep2plogic = 0;
    420     }
    421     if (p_iso_ntf_buff != NULL)
    422     {
    423         free(p_iso_ntf_buff);
    424         p_iso_ntf_buff = NULL;
    425     }
    426 
    427     return status;
    428 }
    429 
    430 
    431 extern NFCSTATUS phNxpNciHal_clean_P2P_Prio()
    432 {
    433     NFCSTATUS status = NFCSTATUS_SUCCESS;
    434 
    435     iso_dep_detected = 0x00;
    436     EnableP2P_PrioLogic = FALSE;
    437     poll_timer_fired = 0x00;
    438     bIgnorep2plogic = 0x00;
    439     bIgnoreIsoDep = 0x00;
    440 
    441     status = phOsalNfc_Timer_Stop(cleanup_timer);
    442     status |= phOsalNfc_Timer_Delete(cleanup_timer);
    443 
    444     status |= phOsalNfc_Timer_Stop(custom_poll_timer);
    445     status |= phOsalNfc_Timer_Delete(custom_poll_timer);
    446     cleanup_timer=0;
    447     return status;
    448 }
    449 
    450 #endif
    451 /*******************************************************************************
    452 **
    453 ** Function         hal_write_cb
    454 **
    455 ** Description      Callback function for hal write.
    456 **
    457 ** Returns          None
    458 **
    459 *******************************************************************************/
    460 static void hal_write_cb(void *pContext, phTmlNfc_TransactInfo_t *pInfo)
    461 {
    462     phNxpNciHal_Sem_t *p_cb_data = (phNxpNciHal_Sem_t*) pContext;
    463 
    464     if (pInfo->wStatus == NFCSTATUS_SUCCESS)
    465     {
    466         NXPLOG_NCIHAL_D("hal_write_cb: write successful status = 0x%x", pInfo->wStatus);
    467     }
    468     else
    469     {
    470         NXPLOG_NCIHAL_E("hal_write_cb: write error status = 0x%x", pInfo->wStatus);
    471     }
    472 
    473     p_cb_data->status = pInfo->wStatus;
    474 
    475     SEM_POST(p_cb_data);
    476     return;
    477 }
    478 
    479 /*******************************************************************************
    480  **
    481  ** Function         tmp_thread
    482  **
    483  ** Description      Thread to execute custom poll commands .
    484  **
    485  ** Returns          None
    486  **
    487  *******************************************************************************/
    488 void *tmp_thread(void *tmp)
    489 {
    490     NFCSTATUS status = NFCSTATUS_SUCCESS;
    491     uint16_t data_len;
    492     NXPLOG_NCIHAL_E("tmp_thread: enter type=0x0%x",  *((int*)tmp));
    493     usleep(10*1000);
    494 
    495     switch( *((int*)tmp) )
    496     {
    497     case START_POLLING:
    498     {
    499         CONCURRENCY_LOCK();
    500         data_len = phNxpNciHal_write_unlocked(cmd_poll_len, cmd_poll);
    501         CONCURRENCY_UNLOCK();
    502 
    503         if(data_len != cmd_poll_len)
    504         {
    505             NXPLOG_NCIHAL_E("phNxpNciHal_start_polling_loop: data len mismatch");
    506             status = NFCSTATUS_FAILED;
    507         }
    508     }
    509     break;
    510 
    511     case RESUME_POLLING:
    512     {
    513         CONCURRENCY_LOCK();
    514         data_len = phNxpNciHal_write_unlocked(sizeof(cmd_resume_rf_discovery),
    515                 cmd_resume_rf_discovery);
    516         CONCURRENCY_UNLOCK();
    517 
    518         if(data_len != sizeof(cmd_resume_rf_discovery))
    519         {
    520             NXPLOG_NCIHAL_E("phNxpNciHal_resume_polling_loop: data len mismatch");
    521             status = NFCSTATUS_FAILED;
    522         }
    523     }
    524     break;
    525 
    526     case STOP_POLLING:
    527     {
    528         CONCURRENCY_LOCK();
    529         data_len = phNxpNciHal_write_unlocked(sizeof(cmd_stop_rf_discovery),
    530                 cmd_stop_rf_discovery);
    531         CONCURRENCY_UNLOCK();
    532 
    533         if(data_len != sizeof(cmd_stop_rf_discovery))
    534         {
    535             NXPLOG_NCIHAL_E("phNxpNciHal_stop_polling_loop: data len mismatch");
    536             status = NFCSTATUS_FAILED;
    537         }
    538     }
    539     break;
    540 
    541     case DISCOVER_SELECT:
    542     {
    543         CONCURRENCY_LOCK();
    544         data_len = phNxpNciHal_write_unlocked(sizeof(cmd_select_rf_discovery),
    545                 cmd_select_rf_discovery);
    546         CONCURRENCY_UNLOCK();
    547 
    548         if(data_len != sizeof(cmd_resume_rf_discovery))
    549         {
    550             NXPLOG_NCIHAL_E("phNxpNciHal_resume_polling_loop: data len mismatch");
    551             status = NFCSTATUS_FAILED;
    552         }
    553     }
    554     break;
    555 
    556     default:
    557         NXPLOG_NCIHAL_E("No Matching case");
    558         status = NFCSTATUS_FAILED;
    559         break;
    560     }
    561 
    562     NXPLOG_NCIHAL_E("tmp_thread: exit");
    563     return NULL;
    564 }
    565 /*******************************************************************************
    566  **
    567  ** Function         phNxpNciHal_select_RF_Discovery
    568  **
    569  ** Description     Sends RF_DISCOVER_SELECT_CMD
    570  ** Parameters    RfID ,  RfProtocolType
    571  ** Returns          NFCSTATUS_PENDING if success
    572  **
    573  *******************************************************************************/
    574 NFCSTATUS phNxpNciHal_select_RF_Discovery(unsigned int RfID,unsigned int RfProtocolType)
    575 {
    576     NFCSTATUS status = NFCSTATUS_SUCCESS;
    577     phNxpNciHal_Sem_t cb_data;
    578     pthread_t pthread;
    579     discover_type = DISCOVER_SELECT;
    580     cmd_select_rf_discovery[3]=RfID;
    581     cmd_select_rf_discovery[4]=RfProtocolType;
    582 
    583     pthread_attr_t attr;
    584     pthread_attr_init (&attr);
    585     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    586     if (pthread_create (&pthread, &attr, tmp_thread, (void*) &discover_type) != 0)
    587     {
    588         NXPLOG_NCIHAL_E("fail to create pthread");
    589     }
    590     pthread_attr_destroy (&attr);
    591     return status;
    592 }
    593 /*******************************************************************************
    594 **
    595 ** Function         phNxpNciHal_NfcDep_cmd_ext
    596 **
    597 ** Description      Stores the polling loop configuration locally.
    598 **
    599 ** Returns          None
    600 **
    601 *******************************************************************************/
    602 void phNxpNciHal_NfcDep_cmd_ext(uint8_t *p_cmd_data, uint16_t *cmd_len)
    603 {
    604     if (p_cmd_data[0] == 0x21 && p_cmd_data[1] == 0x03)
    605     {
    606         if (*cmd_len == 6 && p_cmd_data[3] == 0x01 && p_cmd_data[4] == 0x02
    607                 && p_cmd_data[5] == 0x01)
    608         {
    609             /* DO NOTHING */
    610         }
    611         else
    612         {
    613             /* Store the polling loop configuration */
    614             cmd_poll_len = *cmd_len;
    615             memset(&cmd_poll, 0, cmd_poll_len);
    616             memcpy(&cmd_poll, p_cmd_data, cmd_poll_len);
    617         }
    618     }
    619 
    620     return;
    621 }
    622