Home | History | Annotate | Download | only in utils
      1 /*
      2  *
      3  *  Copyright (C) 2013-2014 NXP Semiconductors
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 #include <errno.h>
     19 #include <pthread.h>
     20 
     21 #include <phNxpLog.h>
     22 #include <phNxpNciHal.h>
     23 #include <phNxpNciHal_utils.h>
     24 
     25 #if(NFC_NXP_CHIP_TYPE == PN548C2)
     26 extern uint8_t discovery_cmd[50];
     27 extern uint8_t discovery_cmd_len;
     28 extern uint8_t nfcdep_detected;
     29 #endif
     30 
     31 /*********************** Link list functions **********************************/
     32 
     33 /*******************************************************************************
     34 **
     35 ** Function         listInit
     36 **
     37 ** Description      List initialization
     38 **
     39 ** Returns          1, if list initialized, 0 otherwise
     40 **
     41 *******************************************************************************/
     42 int listInit(struct listHead* pList)
     43 {
     44     pList->pFirst = NULL;
     45     if (pthread_mutex_init(&pList->mutex, NULL) == -1)
     46     {
     47         NXPLOG_NCIHAL_E("Mutex creation failed (errno=0x%08x)", errno);
     48         return 0;
     49     }
     50 
     51     return 1;
     52 }
     53 
     54 /*******************************************************************************
     55 **
     56 ** Function         listDestroy
     57 **
     58 ** Description      List destruction
     59 **
     60 ** Returns          1, if list destroyed, 0 if failed
     61 **
     62 *******************************************************************************/
     63 int listDestroy(struct listHead* pList)
     64 {
     65     int bListNotEmpty = 1;
     66     while (bListNotEmpty)
     67     {
     68         bListNotEmpty = listGetAndRemoveNext(pList, NULL);
     69     }
     70 
     71     if (pthread_mutex_destroy(&pList->mutex) == -1)
     72     {
     73         NXPLOG_NCIHAL_E("Mutex destruction failed (errno=0x%08x)", errno);
     74         return 0;
     75     }
     76 
     77     return 1;
     78 }
     79 
     80 /*******************************************************************************
     81 **
     82 ** Function         listAdd
     83 **
     84 ** Description      Add a node to the list
     85 **
     86 ** Returns          1, if added, 0 if otherwise
     87 **
     88 *******************************************************************************/
     89 int listAdd(struct listHead* pList, void* pData)
     90 {
     91     struct listNode* pNode;
     92     struct listNode* pLastNode;
     93     int result;
     94 
     95     /* Create node */
     96     pNode = (struct listNode*) malloc(sizeof(struct listNode));
     97     if (pNode == NULL)
     98     {
     99         result = 0;
    100         NXPLOG_NCIHAL_E("Failed to malloc");
    101         goto clean_and_return;
    102     }
    103     pNode->pData = pData;
    104     pNode->pNext = NULL;
    105 
    106     pthread_mutex_lock(&pList->mutex);
    107 
    108     /* Add the node to the list */
    109     if (pList->pFirst == NULL)
    110     {
    111         /* Set the node as the head */
    112         pList->pFirst = pNode;
    113     }
    114     else
    115     {
    116         /* Seek to the end of the list */
    117         pLastNode = pList->pFirst;
    118         while (pLastNode->pNext != NULL)
    119         {
    120             pLastNode = pLastNode->pNext;
    121         }
    122 
    123         /* Add the node to the current list */
    124         pLastNode->pNext = pNode;
    125     }
    126 
    127     result = 1;
    128 
    129 clean_and_return:
    130     pthread_mutex_unlock(&pList->mutex);
    131     return result;
    132 }
    133 
    134 /*******************************************************************************
    135 **
    136 ** Function         listRemove
    137 **
    138 ** Description      Remove node from the list
    139 **
    140 ** Returns          1, if removed, 0 if otherwise
    141 **
    142 *******************************************************************************/
    143 int listRemove(struct listHead* pList, void* pData)
    144 {
    145     struct listNode* pNode;
    146     struct listNode* pRemovedNode;
    147     int result;
    148 
    149     pthread_mutex_lock(&pList->mutex);
    150 
    151     if (pList->pFirst == NULL)
    152     {
    153         /* Empty list */
    154         NXPLOG_NCIHAL_E("Failed to deallocate (list empty)");
    155         result = 0;
    156         goto clean_and_return;
    157     }
    158 
    159     pNode = pList->pFirst;
    160     if (pList->pFirst->pData == pData)
    161     {
    162         /* Get the removed node */
    163         pRemovedNode = pNode;
    164 
    165         /* Remove the first node */
    166         pList->pFirst = pList->pFirst->pNext;
    167     }
    168     else
    169     {
    170         while (pNode->pNext != NULL)
    171         {
    172             if (pNode->pNext->pData == pData)
    173             {
    174                 /* Node found ! */
    175                 break;
    176             }
    177             pNode = pNode->pNext;
    178         }
    179 
    180         if (pNode->pNext == NULL)
    181         {
    182             /* Node not found */
    183             result = 0;
    184             NXPLOG_NCIHAL_E("Failed to deallocate (not found %8p)", pData);
    185             goto clean_and_return;
    186         }
    187 
    188         /* Get the removed node */
    189         pRemovedNode = pNode->pNext;
    190 
    191         /* Remove the node from the list */
    192         pNode->pNext = pNode->pNext->pNext;
    193     }
    194 
    195     /* Deallocate the node */
    196     free(pRemovedNode);
    197 
    198     result = 1;
    199 
    200 clean_and_return:
    201     pthread_mutex_unlock(&pList->mutex);
    202     return result;
    203 }
    204 
    205 /*******************************************************************************
    206 **
    207 ** Function         listGetAndRemoveNext
    208 **
    209 ** Description      Get next node on the list and remove it
    210 **
    211 ** Returns          1, if successful, 0 if otherwise
    212 **
    213 *******************************************************************************/
    214 int listGetAndRemoveNext(struct listHead* pList, void** ppData)
    215 {
    216     struct listNode* pNode;
    217     int result;
    218 
    219     pthread_mutex_lock(&pList->mutex);
    220 
    221     if (pList->pFirst ==  NULL)
    222     {
    223         /* Empty list */
    224         NXPLOG_NCIHAL_D("Failed to deallocate (list empty)");
    225         result = 0;
    226         goto clean_and_return;
    227     }
    228 
    229     /* Work on the first node */
    230     pNode = pList->pFirst;
    231 
    232     /* Return the data */
    233     if (ppData != NULL)
    234     {
    235         *ppData = pNode->pData;
    236     }
    237 
    238     /* Remove and deallocate the node */
    239     pList->pFirst = pNode->pNext;
    240     free(pNode);
    241 
    242     result = 1;
    243 
    244 clean_and_return:
    245     listDump(pList);
    246     pthread_mutex_unlock(&pList->mutex);
    247     return result;
    248 }
    249 
    250 /*******************************************************************************
    251 **
    252 ** Function         listDump
    253 **
    254 ** Description      Dump list information
    255 **
    256 ** Returns          None
    257 **
    258 *******************************************************************************/
    259 void listDump(struct listHead* pList)
    260 {
    261     struct listNode* pNode = pList->pFirst;
    262 
    263     NXPLOG_NCIHAL_D("Node dump:");
    264     while (pNode != NULL)
    265     {
    266         NXPLOG_NCIHAL_D("- %8p (%8p)", pNode, pNode->pData);
    267         pNode = pNode->pNext;
    268     }
    269 
    270     return;
    271 }
    272 
    273 /* END Linked list source code */
    274 
    275 /****************** Semaphore and mutex helper functions **********************/
    276 
    277 static phNxpNciHal_Monitor_t *nxpncihal_monitor = NULL;
    278 
    279 /*******************************************************************************
    280 **
    281 ** Function         phNxpNciHal_init_monitor
    282 **
    283 ** Description      Initialize the semaphore monitor
    284 **
    285 ** Returns          Pointer to monitor, otherwise NULL if failed
    286 **
    287 *******************************************************************************/
    288 phNxpNciHal_Monitor_t*
    289 phNxpNciHal_init_monitor(void)
    290 {
    291     NXPLOG_NCIHAL_D("Entering phNxpNciHal_init_monitor");
    292 
    293     if (nxpncihal_monitor == NULL)
    294     {
    295         nxpncihal_monitor = (phNxpNciHal_Monitor_t *) malloc(
    296                 sizeof(phNxpNciHal_Monitor_t));
    297     }
    298 
    299     if (nxpncihal_monitor != NULL)
    300     {
    301         memset(nxpncihal_monitor, 0x00, sizeof(phNxpNciHal_Monitor_t));
    302 
    303         if (pthread_mutex_init(&nxpncihal_monitor->reentrance_mutex, NULL)
    304                 == -1)
    305         {
    306             NXPLOG_NCIHAL_E("reentrance_mutex creation returned 0x%08x", errno);
    307             goto clean_and_return;
    308         }
    309 
    310         if (pthread_mutex_init(&nxpncihal_monitor->concurrency_mutex, NULL)
    311                 == -1)
    312         {
    313             NXPLOG_NCIHAL_E("concurrency_mutex creation returned 0x%08x", errno);
    314             pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
    315             goto clean_and_return;
    316         }
    317 
    318         if (listInit(&nxpncihal_monitor->sem_list) != 1)
    319         {
    320             NXPLOG_NCIHAL_E("Semaphore List creation failed");
    321             pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
    322             pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
    323             goto clean_and_return;
    324         }
    325     }
    326     else
    327     {
    328         NXPLOG_NCIHAL_E("nxphal_monitor creation failed");
    329         goto clean_and_return;
    330     }
    331 
    332     NXPLOG_NCIHAL_D("Returning with SUCCESS");
    333 
    334     return nxpncihal_monitor;
    335 
    336 clean_and_return:
    337     NXPLOG_NCIHAL_D("Returning with FAILURE");
    338 
    339     if (nxpncihal_monitor != NULL)
    340     {
    341         free(nxpncihal_monitor);
    342         nxpncihal_monitor = NULL;
    343     }
    344 
    345     return NULL;
    346 }
    347 
    348 /*******************************************************************************
    349 **
    350 ** Function         phNxpNciHal_cleanup_monitor
    351 **
    352 ** Description      Clean up semaphore monitor
    353 **
    354 ** Returns          None
    355 **
    356 *******************************************************************************/
    357 void phNxpNciHal_cleanup_monitor(void)
    358 {
    359     if (nxpncihal_monitor != NULL)
    360     {
    361         pthread_mutex_destroy(&nxpncihal_monitor->concurrency_mutex);
    362         REENTRANCE_UNLOCK();
    363         pthread_mutex_destroy(&nxpncihal_monitor->reentrance_mutex);
    364         phNxpNciHal_releaseall_cb_data();
    365         listDestroy(&nxpncihal_monitor->sem_list);
    366     }
    367 
    368     free(nxpncihal_monitor);
    369     nxpncihal_monitor = NULL;
    370 
    371     return;
    372 }
    373 
    374 /*******************************************************************************
    375 **
    376 ** Function         phNxpNciHal_get_monitor
    377 **
    378 ** Description      Get monitor
    379 **
    380 ** Returns          Pointer to monitor
    381 **
    382 *******************************************************************************/
    383 phNxpNciHal_Monitor_t*
    384 phNxpNciHal_get_monitor(void)
    385 {
    386     return nxpncihal_monitor;
    387 }
    388 
    389 /* Initialize the callback data */
    390 NFCSTATUS phNxpNciHal_init_cb_data(phNxpNciHal_Sem_t *pCallbackData,
    391         void *pContext)
    392 {
    393     /* Create semaphore */
    394     if (sem_init(&pCallbackData->sem, 0, 0) == -1)
    395     {
    396         NXPLOG_NCIHAL_E("Semaphore creation failed (errno=0x%08x)", errno);
    397         return NFCSTATUS_FAILED;
    398     }
    399 
    400     /* Set default status value */
    401     pCallbackData->status = NFCSTATUS_FAILED;
    402 
    403     /* Copy the context */
    404     pCallbackData->pContext = pContext;
    405 
    406     /* Add to active semaphore list */
    407     if (listAdd(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1)
    408     {
    409         NXPLOG_NCIHAL_E("Failed to add the semaphore to the list");
    410     }
    411 
    412     return NFCSTATUS_SUCCESS;
    413 }
    414 
    415 /*******************************************************************************
    416 **
    417 ** Function         phNxpNciHal_cleanup_cb_data
    418 **
    419 ** Description      Clean up callback data
    420 **
    421 ** Returns          None
    422 **
    423 *******************************************************************************/
    424 void phNxpNciHal_cleanup_cb_data(phNxpNciHal_Sem_t* pCallbackData)
    425 {
    426     /* Destroy semaphore */
    427     if (sem_destroy(&pCallbackData->sem))
    428     {
    429         NXPLOG_NCIHAL_E("phNxpNciHal_cleanup_cb_data: Failed to destroy semaphore (errno=0x%08x)", errno);
    430     }
    431 
    432     /* Remove from active semaphore list */
    433     if (listRemove(&phNxpNciHal_get_monitor()->sem_list, pCallbackData) != 1)
    434     {
    435         NXPLOG_NCIHAL_E("phNxpNciHal_cleanup_cb_data: Failed to remove semaphore from the list");
    436     }
    437 
    438     return;
    439 }
    440 
    441 /*******************************************************************************
    442 **
    443 ** Function         phNxpNciHal_releaseall_cb_data
    444 **
    445 ** Description      Release all callback data
    446 **
    447 ** Returns          None
    448 **
    449 *******************************************************************************/
    450 void phNxpNciHal_releaseall_cb_data(void)
    451 {
    452     phNxpNciHal_Sem_t* pCallbackData;
    453 
    454     while (listGetAndRemoveNext(&phNxpNciHal_get_monitor()->sem_list,
    455             (void**) &pCallbackData))
    456     {
    457         pCallbackData->status = NFCSTATUS_FAILED;
    458         sem_post(&pCallbackData->sem);
    459     }
    460 
    461     return;
    462 }
    463 
    464 /* END Semaphore and mutex helper functions */
    465 
    466 /**************************** Other functions *********************************/
    467 
    468 /*******************************************************************************
    469 **
    470 ** Function         phNxpNciHal_print_packet
    471 **
    472 ** Description      Print packet
    473 **
    474 ** Returns          None
    475 **
    476 *******************************************************************************/
    477 void phNxpNciHal_print_packet(const char *pString, const uint8_t *p_data,
    478         uint16_t len)
    479 {
    480     uint32_t i, j;
    481     char print_buffer[len * 3 + 1];
    482 
    483     memset (print_buffer, 0, sizeof(print_buffer));
    484     for (i = 0; i < len; i++) {
    485         snprintf(&print_buffer[i * 2], 3, "%02X", p_data[i]);
    486     }
    487     if( 0 == memcmp(pString,"SEND",0x04))
    488     {
    489         NXPLOG_NCIX_D("len = %3d > %s", len, print_buffer);
    490     }
    491     else if( 0 == memcmp(pString,"RECV",0x04))
    492     {
    493         NXPLOG_NCIR_D("len = %3d > %s", len, print_buffer);
    494     }
    495 
    496     return;
    497 }
    498 
    499 
    500 /*******************************************************************************
    501 **
    502 ** Function         phNxpNciHal_emergency_recovery
    503 **
    504 ** Description      Emergency recovery in case of no other way out
    505 **
    506 ** Returns          None
    507 **
    508 *******************************************************************************/
    509 
    510 void phNxpNciHal_emergency_recovery (void)
    511 {
    512 #if(NFC_NXP_CHIP_TYPE == PN548C2)
    513     if (nfcdep_detected && discovery_cmd_len != 0)
    514     {
    515         pthread_t pthread;
    516         pthread_attr_t attr;
    517         pthread_attr_init (&attr);
    518         pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    519         if (pthread_create (&pthread, &attr, (void *)phNxpNciHal_core_reset_recovery, NULL) == 0)
    520         {
    521             return;
    522         }
    523     }
    524 #endif
    525     NXPLOG_NCIHAL_E ("%s: abort()", __FUNCTION__);
    526     abort ();
    527 }
    528