1 /* 2 * Copyright (C) 2010-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 /* 18 * TML Implementation. 19 */ 20 21 #include <phDal4Nfc_messageQueueLib.h> 22 #include <phNxpLog.h> 23 #include <phNxpNciHal_utils.h> 24 #include <phOsalNfc_Timer.h> 25 #include <phTmlNfc.h> 26 #include <phTmlNfc_i2c.h> 27 28 /* 29 * Duration of Timer to wait after sending an Nci packet 30 */ 31 #define PHTMLNFC_MAXTIME_RETRANSMIT (200U) 32 #define MAX_WRITE_RETRY_COUNT 0x03 33 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 */ 34 static uint8_t bCurrentRetryCount = (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; 35 36 /* Value to reset variables of TML */ 37 #define PH_TMLNFC_RESET_VALUE (0x00) 38 39 /* Indicates a Initial or offset value */ 40 #define PH_TMLNFC_VALUE_ONE (0x01) 41 42 /* Initialize Context structure pointer used to access context structure */ 43 phTmlNfc_Context_t* gpphTmlNfc_Context = NULL; 44 phTmlNfc_i2cfragmentation_t fragmentation_enabled = I2C_FRAGMENATATION_DISABLED; 45 /* Local Function prototypes */ 46 static NFCSTATUS phTmlNfc_StartThread(void); 47 static void phTmlNfc_CleanUp(void); 48 static void phTmlNfc_ReadDeferredCb(void* pParams); 49 static void phTmlNfc_WriteDeferredCb(void* pParams); 50 static void phTmlNfc_TmlThread(void* pParam); 51 static void phTmlNfc_TmlWriterThread(void* pParam); 52 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext); 53 static NFCSTATUS phTmlNfc_InitiateTimer(void); 54 55 /* Function definitions */ 56 57 /******************************************************************************* 58 ** 59 ** Function phTmlNfc_Init 60 ** 61 ** Description Provides initialization of TML layer and hardware interface 62 ** Configures given hardware interface and sends handle to the 63 ** caller 64 ** 65 ** Parameters pConfig - TML configuration details as provided by the upper 66 ** layer 67 ** 68 ** Returns NFC status: 69 ** NFCSTATUS_SUCCESS - initialization successful 70 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 71 ** invalid 72 ** NFCSTATUS_FAILED - initialization failed (for example, 73 ** unable to open hardware interface) 74 ** NFCSTATUS_INVALID_DEVICE - device has not been opened or has 75 ** been disconnected 76 ** 77 *******************************************************************************/ 78 NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) { 79 NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS; 80 81 /* Check if TML layer is already Initialized */ 82 if (NULL != gpphTmlNfc_Context) { 83 /* TML initialization is already completed */ 84 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED); 85 } 86 /* Validate Input parameters */ 87 else if ((NULL == pConfig) || 88 (PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) { 89 /*Parameters passed to TML init are wrong */ 90 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 91 } else { 92 /* Allocate memory for TML context */ 93 gpphTmlNfc_Context = malloc(sizeof(phTmlNfc_Context_t)); 94 95 if (NULL == gpphTmlNfc_Context) { 96 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 97 } else { 98 /* Initialise all the internal TML variables */ 99 memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE, 100 sizeof(phTmlNfc_Context_t)); 101 /* Make sure that the thread runs once it is created */ 102 gpphTmlNfc_Context->bThreadDone = 1; 103 104 /* Open the device file to which data is read/written */ 105 wInitStatus = phTmlNfc_i2c_open_and_configure( 106 pConfig, &(gpphTmlNfc_Context->pDevHandle)); 107 108 if (NFCSTATUS_SUCCESS != wInitStatus) { 109 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE); 110 gpphTmlNfc_Context->pDevHandle = NULL; 111 } else { 112 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 113 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 114 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 115 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 116 117 if (0 != sem_init(&gpphTmlNfc_Context->rxSemaphore, 0, 0)) { 118 wInitStatus = NFCSTATUS_FAILED; 119 } else if (0 != sem_init(&gpphTmlNfc_Context->txSemaphore, 0, 0)) { 120 wInitStatus = NFCSTATUS_FAILED; 121 } else if (0 != sem_init(&gpphTmlNfc_Context->postMsgSemaphore, 0, 0)) { 122 wInitStatus = NFCSTATUS_FAILED; 123 } else { 124 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 125 /* Start TML thread (to handle write and read operations) */ 126 if (NFCSTATUS_SUCCESS != phTmlNfc_StartThread()) { 127 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 128 } else { 129 /* Create Timer used for Retransmission of NCI packets */ 130 gpphTmlNfc_Context->dwTimerId = phOsalNfc_Timer_Create(); 131 if (PH_OSALNFC_TIMER_ID_INVALID != gpphTmlNfc_Context->dwTimerId) { 132 /* Store the Thread Identifier to which Message is to be posted */ 133 gpphTmlNfc_Context->dwCallbackThreadId = 134 pConfig->dwGetMsgThreadId; 135 /* Enable retransmission of Nci packet & set retry count to 136 * default */ 137 gpphTmlNfc_Context->eConfig = phTmlNfc_e_DisableRetrans; 138 /* Retry Count = Standby Recovery time of NFCC / Retransmission 139 * time + 1 */ 140 gpphTmlNfc_Context->bRetryCount = 141 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; 142 gpphTmlNfc_Context->bWriteCbInvoked = false; 143 } else { 144 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 145 } 146 } 147 } 148 } 149 } 150 } 151 /* Clean up all the TML resources if any error */ 152 if (NFCSTATUS_SUCCESS != wInitStatus) { 153 /* Clear all handles and memory locations initialized during init */ 154 phTmlNfc_CleanUp(); 155 } 156 157 return wInitStatus; 158 } 159 160 /******************************************************************************* 161 ** 162 ** Function phTmlNfc_ConfigNciPktReTx 163 ** 164 ** Description Provides Enable/Disable Retransmission of NCI packets 165 ** Needed in case of Timeout between Transmission and Reception 166 ** of NCI packets. Retransmission can be enabled only if 167 ** standby mode is enabled 168 ** 169 ** Parameters eConfig - values from phTmlNfc_ConfigRetrans_t 170 ** bRetryCount - Number of times Nci packets shall be 171 ** retransmitted (default = 3) 172 ** 173 ** Returns None 174 ** 175 *******************************************************************************/ 176 void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration, 177 uint8_t bRetryCounter) { 178 /* Enable/Disable Retransmission */ 179 180 gpphTmlNfc_Context->eConfig = eConfiguration; 181 if (phTmlNfc_e_EnableRetrans == eConfiguration) { 182 /* Check whether Retry counter passed is valid */ 183 if (0 != bRetryCounter) { 184 gpphTmlNfc_Context->bRetryCount = bRetryCounter; 185 } 186 /* Set retry counter to its default value */ 187 else { 188 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 189 */ 190 gpphTmlNfc_Context->bRetryCount = 191 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; 192 } 193 } 194 195 return; 196 } 197 198 /******************************************************************************* 199 ** 200 ** Function phTmlNfc_StartThread 201 ** 202 ** Description Initializes comport, reader and writer threads 203 ** 204 ** Parameters None 205 ** 206 ** Returns NFC status: 207 ** NFCSTATUS_SUCCESS - threads initialized successfully 208 ** NFCSTATUS_FAILED - initialization failed due to system error 209 ** 210 *******************************************************************************/ 211 static NFCSTATUS phTmlNfc_StartThread(void) { 212 NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS; 213 void* h_threadsEvent = 0x00; 214 uint32_t dwEvent; 215 int pthread_create_status = 0; 216 217 /* Create Reader and Writer threads */ 218 pthread_create_status = 219 pthread_create(&gpphTmlNfc_Context->readerThread, NULL, 220 (void*)&phTmlNfc_TmlThread, (void*)h_threadsEvent); 221 if (0 != pthread_create_status) { 222 wStartStatus = NFCSTATUS_FAILED; 223 } else { 224 /*Start Writer Thread*/ 225 pthread_create_status = 226 pthread_create(&gpphTmlNfc_Context->writerThread, NULL, 227 (void*)&phTmlNfc_TmlWriterThread, (void*)h_threadsEvent); 228 if (0 != pthread_create_status) { 229 wStartStatus = NFCSTATUS_FAILED; 230 } 231 } 232 233 return wStartStatus; 234 } 235 236 /******************************************************************************* 237 ** 238 ** Function phTmlNfc_ReTxTimerCb 239 ** 240 ** Description This is the timer callback function after timer expiration. 241 ** 242 ** Parameters dwThreadId - id of the thread posting message 243 ** pContext - context provided by upper layer 244 ** 245 ** Returns None 246 ** 247 *******************************************************************************/ 248 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext) { 249 if ((gpphTmlNfc_Context->dwTimerId == dwTimerId) && (NULL == pContext)) { 250 /* If Retry Count has reached its limit,Retransmit Nci 251 packet */ 252 if (0 == bCurrentRetryCount) { 253 /* Since the count has reached its limit,return from timer callback 254 Upper layer Timeout would have happened */ 255 } else { 256 bCurrentRetryCount--; 257 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; 258 gpphTmlNfc_Context->tWriteInfo.bEnable = 1; 259 } 260 sem_post(&gpphTmlNfc_Context->txSemaphore); 261 } 262 263 return; 264 } 265 266 /******************************************************************************* 267 ** 268 ** Function phTmlNfc_InitiateTimer 269 ** 270 ** Description Start a timer for Tx and Rx thread. 271 ** 272 ** Parameters void 273 ** 274 ** Returns NFC status 275 ** 276 *******************************************************************************/ 277 static NFCSTATUS phTmlNfc_InitiateTimer(void) { 278 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 279 280 /* Start Timer once Nci packet is sent */ 281 wStatus = phOsalNfc_Timer_Start(gpphTmlNfc_Context->dwTimerId, 282 (uint32_t)PHTMLNFC_MAXTIME_RETRANSMIT, 283 phTmlNfc_ReTxTimerCb, NULL); 284 285 return wStatus; 286 } 287 288 /******************************************************************************* 289 ** 290 ** Function phTmlNfc_TmlThread 291 ** 292 ** Description Read the data from the lower layer driver 293 ** 294 ** Parameters pParam - parameters for Writer thread function 295 ** 296 ** Returns None 297 ** 298 *******************************************************************************/ 299 static void phTmlNfc_TmlThread(void* pParam) { 300 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 301 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 302 uint8_t temp[260]; 303 /* Transaction info buffer to be passed to Callback Thread */ 304 static phTmlNfc_TransactInfo_t tTransactionInfo; 305 /* Structure containing Tml callback function and parameters to be invoked 306 by the callback thread */ 307 static phLibNfc_DeferredCall_t tDeferredInfo; 308 /* Initialize Message structure to post message onto Callback Thread */ 309 static phLibNfc_Message_t tMsg; 310 UNUSED(pParam); 311 NXPLOG_TML_D("PN54X - Tml Reader Thread Started................\n"); 312 313 /* Writer thread loop shall be running till shutdown is invoked */ 314 while (gpphTmlNfc_Context->bThreadDone) { 315 /* If Tml write is requested */ 316 /* Set the variable to success initially */ 317 wStatus = NFCSTATUS_SUCCESS; 318 sem_wait(&gpphTmlNfc_Context->rxSemaphore); 319 320 /* If Tml read is requested */ 321 if (1 == gpphTmlNfc_Context->tReadInfo.bEnable) { 322 NXPLOG_TML_D("PN54X - Read requested.....\n"); 323 /* Set the variable to success initially */ 324 wStatus = NFCSTATUS_SUCCESS; 325 326 /* Variable to fetch the actual number of bytes read */ 327 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 328 329 /* Read the data from the file onto the buffer */ 330 if (NULL != gpphTmlNfc_Context->pDevHandle) { 331 NXPLOG_TML_D("PN54X - Invoking I2C Read.....\n"); 332 dwNoBytesWrRd = 333 phTmlNfc_i2c_read(gpphTmlNfc_Context->pDevHandle, temp, 260); 334 335 if (-1 == dwNoBytesWrRd) { 336 NXPLOG_TML_E("PN54X - Error in I2C Read.....\n"); 337 sem_post(&gpphTmlNfc_Context->rxSemaphore); 338 } else if (dwNoBytesWrRd > 260) { 339 NXPLOG_TML_E("Numer of bytes read exceeds the limit 260.....\n"); 340 sem_post(&gpphTmlNfc_Context->rxSemaphore); 341 } else { 342 memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd); 343 344 NXPLOG_TML_D("PN54X - I2C Read successful.....\n"); 345 /* This has to be reset only after a successful read */ 346 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 347 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 348 (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) { 349 NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n"); 350 /* Stop Timer to prevent Retransmission */ 351 uint32_t timerStatus = 352 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId); 353 if (NFCSTATUS_SUCCESS != timerStatus) { 354 NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n"); 355 } else { 356 gpphTmlNfc_Context->bWriteCbInvoked = false; 357 } 358 } 359 if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { 360 NXPLOG_TML_D("Delay Read if write thread is busy"); 361 usleep(2000); /*2ms delay to give prio to write complete */ 362 } 363 /* Update the actual number of bytes read including header */ 364 gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd); 365 phNxpNciHal_print_packet("RECV", 366 gpphTmlNfc_Context->tReadInfo.pBuffer, 367 gpphTmlNfc_Context->tReadInfo.wLength); 368 369 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 370 371 /* Fill the Transaction info structure to be passed to Callback 372 * Function */ 373 tTransactionInfo.wStatus = wStatus; 374 tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer; 375 /* Actual number of bytes read is filled in the structure */ 376 tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength; 377 378 /* Read operation completed successfully. Post a Message onto Callback 379 * Thread*/ 380 /* Prepare the message to be posted on User thread */ 381 tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb; 382 tDeferredInfo.pParameter = &tTransactionInfo; 383 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 384 tMsg.pMsgData = &tDeferredInfo; 385 tMsg.Size = sizeof(tDeferredInfo); 386 NXPLOG_TML_D("PN54X - Posting read message.....\n"); 387 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 388 } 389 } else { 390 NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL"); 391 } 392 } else { 393 NXPLOG_TML_D("PN54X - read request NOT enabled"); 394 usleep(10 * 1000); 395 } 396 } /* End of While loop */ 397 398 return; 399 } 400 401 /******************************************************************************* 402 ** 403 ** Function phTmlNfc_TmlWriterThread 404 ** 405 ** Description Writes the requested data onto the lower layer driver 406 ** 407 ** Parameters pParam - context provided by upper layer 408 ** 409 ** Returns None 410 ** 411 *******************************************************************************/ 412 static void phTmlNfc_TmlWriterThread(void* pParam) { 413 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 414 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 415 /* Transaction info buffer to be passed to Callback Thread */ 416 static phTmlNfc_TransactInfo_t tTransactionInfo; 417 /* Structure containing Tml callback function and parameters to be invoked 418 by the callback thread */ 419 static phLibNfc_DeferredCall_t tDeferredInfo; 420 /* Initialize Message structure to post message onto Callback Thread */ 421 static phLibNfc_Message_t tMsg; 422 /* In case of I2C Write Retry */ 423 static uint16_t retry_cnt; 424 UNUSED(pParam); 425 NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n"); 426 427 /* Writer thread loop shall be running till shutdown is invoked */ 428 while (gpphTmlNfc_Context->bThreadDone) { 429 NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n"); 430 sem_wait(&gpphTmlNfc_Context->txSemaphore); 431 /* If Tml write is requested */ 432 if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) { 433 NXPLOG_TML_D("PN54X - Write requested.....\n"); 434 /* Set the variable to success initially */ 435 wStatus = NFCSTATUS_SUCCESS; 436 if (NULL != gpphTmlNfc_Context->pDevHandle) { 437 retry: 438 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 439 /* Variable to fetch the actual number of bytes written */ 440 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 441 /* Write the data in the buffer onto the file */ 442 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n"); 443 dwNoBytesWrRd = 444 phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle, 445 gpphTmlNfc_Context->tWriteInfo.pBuffer, 446 gpphTmlNfc_Context->tWriteInfo.wLength); 447 448 /* Try I2C Write Five Times, if it fails : Raju */ 449 if (-1 == dwNoBytesWrRd) { 450 if (getDownloadFlag() == true) { 451 if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) { 452 NXPLOG_NCIHAL_E("PN54X - Error in I2C Write - Retry 0x%x", 453 retry_cnt); 454 goto retry; 455 } 456 } 457 NXPLOG_TML_E("PN54X - Error in I2C Write.....\n"); 458 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 459 } else { 460 phNxpNciHal_print_packet("SEND", 461 gpphTmlNfc_Context->tWriteInfo.pBuffer, 462 gpphTmlNfc_Context->tWriteInfo.wLength); 463 } 464 retry_cnt = 0; 465 if (NFCSTATUS_SUCCESS == wStatus) { 466 NXPLOG_TML_D("PN54X - I2C Write successful.....\n"); 467 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE; 468 } 469 /* Fill the Transaction info structure to be passed to Callback Function 470 */ 471 tTransactionInfo.wStatus = wStatus; 472 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer; 473 /* Actual number of bytes written is filled in the structure */ 474 tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd; 475 476 /* Prepare the message to be posted on the User thread */ 477 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb; 478 tDeferredInfo.pParameter = &tTransactionInfo; 479 /* Write operation completed successfully. Post a Message onto Callback 480 * Thread*/ 481 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 482 tMsg.pMsgData = &tDeferredInfo; 483 tMsg.Size = sizeof(tDeferredInfo); 484 485 /* Check whether Retransmission needs to be started, 486 * If yes, Post message only if 487 * case 1. Message is not posted && 488 * case 11. Write status is success || 489 * case 12. Last retry of write is also failure 490 */ 491 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 492 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 493 if (gpphTmlNfc_Context->bWriteCbInvoked == false) { 494 if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) { 495 NXPLOG_TML_D("PN54X - Posting Write message.....\n"); 496 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, 497 &tMsg); 498 gpphTmlNfc_Context->bWriteCbInvoked = true; 499 } 500 } 501 } else { 502 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n"); 503 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 504 } 505 } else { 506 NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL"); 507 } 508 509 /* If Data packet is sent, then NO retransmission */ 510 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 511 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 512 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case"); 513 wStatus = phTmlNfc_InitiateTimer(); 514 if (NFCSTATUS_SUCCESS != wStatus) { 515 /* Reset Variables used for Retransmission */ 516 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed"); 517 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 518 bCurrentRetryCount = 0; 519 } 520 } 521 } else { 522 NXPLOG_TML_D("PN54X - Write request NOT enabled"); 523 usleep(10000); 524 } 525 526 } /* End of While loop */ 527 528 return; 529 } 530 531 /******************************************************************************* 532 ** 533 ** Function phTmlNfc_CleanUp 534 ** 535 ** Description Clears all handles opened during TML initialization 536 ** 537 ** Parameters None 538 ** 539 ** Returns None 540 ** 541 *******************************************************************************/ 542 static void phTmlNfc_CleanUp(void) { 543 NFCSTATUS wRetval = NFCSTATUS_SUCCESS; 544 545 if (NULL == gpphTmlNfc_Context) { 546 return; 547 } 548 if (NULL != gpphTmlNfc_Context->pDevHandle) { 549 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 550 gpphTmlNfc_Context->bThreadDone = 0; 551 } 552 sem_destroy(&gpphTmlNfc_Context->rxSemaphore); 553 sem_destroy(&gpphTmlNfc_Context->txSemaphore); 554 sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore); 555 phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle); 556 gpphTmlNfc_Context->pDevHandle = NULL; 557 /* Clear memory allocated for storing Context variables */ 558 free((void*)gpphTmlNfc_Context); 559 /* Set the pointer to NULL to indicate De-Initialization */ 560 gpphTmlNfc_Context = NULL; 561 562 return; 563 } 564 565 /******************************************************************************* 566 ** 567 ** Function phTmlNfc_Shutdown 568 ** 569 ** Description Uninitializes TML layer and hardware interface 570 ** 571 ** Parameters None 572 ** 573 ** Returns NFC status: 574 ** NFCSTATUS_SUCCESS - TML configuration released successfully 575 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 576 ** invalid 577 ** NFCSTATUS_FAILED - un-initialization failed (example: unable 578 ** to close interface) 579 ** 580 *******************************************************************************/ 581 NFCSTATUS phTmlNfc_Shutdown(void) { 582 NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS; 583 584 /* Check whether TML is Initialized */ 585 if (NULL != gpphTmlNfc_Context) { 586 /* Reset thread variable to terminate the thread */ 587 gpphTmlNfc_Context->bThreadDone = 0; 588 usleep(1000); 589 /* Clear All the resources allocated during initialization */ 590 sem_post(&gpphTmlNfc_Context->rxSemaphore); 591 usleep(1000); 592 sem_post(&gpphTmlNfc_Context->txSemaphore); 593 usleep(1000); 594 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 595 usleep(1000); 596 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 597 usleep(1000); 598 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) { 599 NXPLOG_TML_E("Fail to kill reader thread!"); 600 } 601 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) { 602 NXPLOG_TML_E("Fail to kill writer thread!"); 603 } 604 NXPLOG_TML_D("bThreadDone == 0"); 605 606 phTmlNfc_CleanUp(); 607 } else { 608 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 609 } 610 611 return wShutdownStatus; 612 } 613 614 /******************************************************************************* 615 ** 616 ** Function phTmlNfc_Write 617 ** 618 ** Description Asynchronously writes given data block to hardware 619 ** interface/driver. Enables writer thread if there are no 620 ** write requests pending. Returns successfully once writer 621 ** thread completes write operation. Notifies upper layer using 622 ** callback mechanism. 623 ** 624 ** NOTE: 625 ** * it is important to post a message with id 626 ** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data 627 ** has been written to PN54X 628 ** * if CRC needs to be computed, then input buffer should be 629 ** capable to store two more bytes apart from length of 630 ** packet 631 ** 632 ** Parameters pBuffer - data to be sent 633 ** wLength - length of data buffer 634 ** pTmlWriteComplete - pointer to the function to be invoked 635 ** upon completion 636 ** pContext - context provided by upper layer 637 ** 638 ** Returns NFC status: 639 ** NFCSTATUS_PENDING - command is yet to be processed 640 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 641 ** invalid 642 ** NFCSTATUS_BUSY - write request is already in progress 643 ** 644 *******************************************************************************/ 645 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength, 646 pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, 647 void* pContext) { 648 NFCSTATUS wWriteStatus; 649 650 /* Check whether TML is Initialized */ 651 652 if (NULL != gpphTmlNfc_Context) { 653 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) && 654 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) { 655 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { 656 /* Setting the flag marks beginning of a Write Operation */ 657 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; 658 /* Copy the buffer, length and Callback function, 659 This shall be utilized while invoking the Callback function in thread 660 */ 661 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer; 662 gpphTmlNfc_Context->tWriteInfo.wLength = wLength; 663 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete; 664 gpphTmlNfc_Context->tWriteInfo.pContext = pContext; 665 666 wWriteStatus = NFCSTATUS_PENDING; 667 // FIXME: If retry is going on. Stop the retry thread/timer 668 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) { 669 /* Set retry count to default value */ 670 // FIXME: If the timer expired there, and meanwhile we have created 671 // a new request. The expired timer will think that retry is still 672 // ongoing. 673 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount; 674 gpphTmlNfc_Context->bWriteCbInvoked = false; 675 } 676 /* Set event to invoke Writer Thread */ 677 gpphTmlNfc_Context->tWriteInfo.bEnable = 1; 678 sem_post(&gpphTmlNfc_Context->txSemaphore); 679 } else { 680 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 681 } 682 } else { 683 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 684 } 685 } else { 686 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 687 } 688 689 return wWriteStatus; 690 } 691 692 /******************************************************************************* 693 ** 694 ** Function phTmlNfc_Read 695 ** 696 ** Description Asynchronously reads data from the driver 697 ** Number of bytes to be read and buffer are passed by upper 698 ** layer. 699 ** Enables reader thread if there are no read requests pending 700 ** Returns successfully once read operation is completed 701 ** Notifies upper layer using callback mechanism 702 ** 703 ** Parameters pBuffer - location to send read data to the upper layer via 704 ** callback 705 ** wLength - length of read data buffer passed by upper layer 706 ** pTmlReadComplete - pointer to the function to be invoked 707 ** upon completion of read operation 708 ** pContext - context provided by upper layer 709 ** 710 ** Returns NFC status: 711 ** NFCSTATUS_PENDING - command is yet to be processed 712 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 713 ** invalid 714 ** NFCSTATUS_BUSY - read request is already in progress 715 ** 716 *******************************************************************************/ 717 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength, 718 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, 719 void* pContext) { 720 NFCSTATUS wReadStatus; 721 722 /* Check whether TML is Initialized */ 723 if (NULL != gpphTmlNfc_Context) { 724 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) && 725 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) { 726 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) { 727 /* Setting the flag marks beginning of a Read Operation */ 728 gpphTmlNfc_Context->tReadInfo.bThreadBusy = true; 729 /* Copy the buffer, length and Callback function, 730 This shall be utilized while invoking the Callback function in thread 731 */ 732 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer; 733 gpphTmlNfc_Context->tReadInfo.wLength = wLength; 734 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; 735 gpphTmlNfc_Context->tReadInfo.pContext = pContext; 736 wReadStatus = NFCSTATUS_PENDING; 737 738 /* Set event to invoke Reader Thread */ 739 gpphTmlNfc_Context->tReadInfo.bEnable = 1; 740 sem_post(&gpphTmlNfc_Context->rxSemaphore); 741 } else { 742 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 743 } 744 } else { 745 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 746 } 747 } else { 748 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 749 } 750 751 return wReadStatus; 752 } 753 754 /******************************************************************************* 755 ** 756 ** Function phTmlNfc_ReadAbort 757 ** 758 ** Description Aborts pending read request (if any) 759 ** 760 ** Parameters None 761 ** 762 ** Returns NFC status: 763 ** NFCSTATUS_SUCCESS - ongoing read operation aborted 764 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 765 ** invalid 766 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 767 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read 768 ** operation 769 ** 770 *******************************************************************************/ 771 NFCSTATUS phTmlNfc_ReadAbort(void) { 772 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 773 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 774 775 /*Reset the flag to accept another Read Request */ 776 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 777 wStatus = NFCSTATUS_SUCCESS; 778 779 return wStatus; 780 } 781 782 /******************************************************************************* 783 ** 784 ** Function phTmlNfc_WriteAbort 785 ** 786 ** Description Aborts pending write request (if any) 787 ** 788 ** Parameters None 789 ** 790 ** Returns NFC status: 791 ** NFCSTATUS_SUCCESS - ongoing write operation aborted 792 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 793 ** invalid 794 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 795 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write 796 ** operation 797 ** 798 *******************************************************************************/ 799 NFCSTATUS phTmlNfc_WriteAbort(void) { 800 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 801 802 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 803 /* Stop if any retransmission is in progress */ 804 bCurrentRetryCount = 0; 805 806 /* Reset the flag to accept another Write Request */ 807 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 808 wStatus = NFCSTATUS_SUCCESS; 809 810 return wStatus; 811 } 812 813 /******************************************************************************* 814 ** 815 ** Function phTmlNfc_IoCtl 816 ** 817 ** Description Resets device when insisted by upper layer 818 ** Number of bytes to be read and buffer are passed by upper 819 ** layer 820 ** Enables reader thread if there are no read requests pending 821 ** Returns successfully once read operation is completed 822 ** Notifies upper layer using callback mechanism 823 ** 824 ** Parameters eControlCode - control code for a specific operation 825 ** 826 ** Returns NFC status: 827 ** NFCSTATUS_SUCCESS - ioctl command completed successfully 828 ** NFCSTATUS_FAILED - ioctl command request failed 829 ** 830 *******************************************************************************/ 831 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) { 832 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 833 834 if (NULL == gpphTmlNfc_Context) { 835 wStatus = NFCSTATUS_FAILED; 836 } else { 837 switch (eControlCode) { 838 case phTmlNfc_e_ResetDevice: { 839 /*Reset PN54X*/ 840 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 841 usleep(100 * 1000); 842 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 843 usleep(100 * 1000); 844 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 845 break; 846 } 847 case phTmlNfc_e_EnableNormalMode: { 848 /*Reset PN54X*/ 849 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 850 usleep(10 * 1000); 851 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 852 usleep(100 * 1000); 853 break; 854 } 855 case phTmlNfc_e_EnableDownloadMode: { 856 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0); 857 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 2); 858 usleep(100 * 1000); 859 break; 860 } 861 default: { 862 wStatus = NFCSTATUS_INVALID_PARAMETER; 863 break; 864 } 865 } 866 } 867 868 return wStatus; 869 } 870 871 /******************************************************************************* 872 ** 873 ** Function phTmlNfc_DeferredCall 874 ** 875 ** Description Posts message on upper layer thread 876 ** upon successful read or write operation 877 ** 878 ** Parameters dwThreadId - id of the thread posting message 879 ** ptWorkerMsg - message to be posted 880 ** 881 ** Returns None 882 ** 883 *******************************************************************************/ 884 void phTmlNfc_DeferredCall(uintptr_t dwThreadId, 885 phLibNfc_Message_t* ptWorkerMsg) { 886 intptr_t bPostStatus; 887 UNUSED(dwThreadId); 888 /* Post message on the user thread to invoke the callback function */ 889 sem_wait(&gpphTmlNfc_Context->postMsgSemaphore); 890 bPostStatus = 891 phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0); 892 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 893 } 894 895 /******************************************************************************* 896 ** 897 ** Function phTmlNfc_ReadDeferredCb 898 ** 899 ** Description Read thread call back function 900 ** 901 ** Parameters pParams - context provided by upper layer 902 ** 903 ** Returns None 904 ** 905 *******************************************************************************/ 906 static void phTmlNfc_ReadDeferredCb(void* pParams) { 907 /* Transaction info buffer to be passed to Callback Function */ 908 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 909 910 /* Reset the flag to accept another Read Request */ 911 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 912 gpphTmlNfc_Context->tReadInfo.pThread_Callback( 913 gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo); 914 915 return; 916 } 917 918 /******************************************************************************* 919 ** 920 ** Function phTmlNfc_WriteDeferredCb 921 ** 922 ** Description Write thread call back function 923 ** 924 ** Parameters pParams - context provided by upper layer 925 ** 926 ** Returns None 927 ** 928 *******************************************************************************/ 929 static void phTmlNfc_WriteDeferredCb(void* pParams) { 930 /* Transaction info buffer to be passed to Callback Function */ 931 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 932 933 /* Reset the flag to accept another Write Request */ 934 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 935 gpphTmlNfc_Context->tWriteInfo.pThread_Callback( 936 gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo); 937 938 return; 939 } 940 941 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) { 942 fragmentation_enabled = result; 943 } 944 945 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() { 946 return fragmentation_enabled; 947 } 948