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