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 // Add a 10 ms delay to ensure NFCC is not still in stand by mode. 455 usleep(10 * 1000); 456 goto retry; 457 } 458 } 459 NXPLOG_TML_E("PN54X - Error in I2C Write.....\n"); 460 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 461 } else { 462 phNxpNciHal_print_packet("SEND", 463 gpphTmlNfc_Context->tWriteInfo.pBuffer, 464 gpphTmlNfc_Context->tWriteInfo.wLength); 465 } 466 retry_cnt = 0; 467 if (NFCSTATUS_SUCCESS == wStatus) { 468 NXPLOG_TML_D("PN54X - I2C Write successful.....\n"); 469 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE; 470 } 471 /* Fill the Transaction info structure to be passed to Callback Function 472 */ 473 tTransactionInfo.wStatus = wStatus; 474 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer; 475 /* Actual number of bytes written is filled in the structure */ 476 tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd; 477 478 /* Prepare the message to be posted on the User thread */ 479 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb; 480 tDeferredInfo.pParameter = &tTransactionInfo; 481 /* Write operation completed successfully. Post a Message onto Callback 482 * Thread*/ 483 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 484 tMsg.pMsgData = &tDeferredInfo; 485 tMsg.Size = sizeof(tDeferredInfo); 486 487 /* Check whether Retransmission needs to be started, 488 * If yes, Post message only if 489 * case 1. Message is not posted && 490 * case 11. Write status is success || 491 * case 12. Last retry of write is also failure 492 */ 493 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 494 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 495 if (gpphTmlNfc_Context->bWriteCbInvoked == false) { 496 if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) { 497 NXPLOG_TML_D("PN54X - Posting Write message.....\n"); 498 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, 499 &tMsg); 500 gpphTmlNfc_Context->bWriteCbInvoked = true; 501 } 502 } 503 } else { 504 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n"); 505 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 506 } 507 } else { 508 NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL"); 509 } 510 511 /* If Data packet is sent, then NO retransmission */ 512 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 513 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 514 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case"); 515 wStatus = phTmlNfc_InitiateTimer(); 516 if (NFCSTATUS_SUCCESS != wStatus) { 517 /* Reset Variables used for Retransmission */ 518 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed"); 519 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 520 bCurrentRetryCount = 0; 521 } 522 } 523 } else { 524 NXPLOG_TML_D("PN54X - Write request NOT enabled"); 525 usleep(10000); 526 } 527 528 } /* End of While loop */ 529 530 return; 531 } 532 533 /******************************************************************************* 534 ** 535 ** Function phTmlNfc_CleanUp 536 ** 537 ** Description Clears all handles opened during TML initialization 538 ** 539 ** Parameters None 540 ** 541 ** Returns None 542 ** 543 *******************************************************************************/ 544 static void phTmlNfc_CleanUp(void) { 545 NFCSTATUS wRetval = NFCSTATUS_SUCCESS; 546 547 if (NULL == gpphTmlNfc_Context) { 548 return; 549 } 550 if (NULL != gpphTmlNfc_Context->pDevHandle) { 551 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 552 gpphTmlNfc_Context->bThreadDone = 0; 553 } 554 sem_destroy(&gpphTmlNfc_Context->rxSemaphore); 555 sem_destroy(&gpphTmlNfc_Context->txSemaphore); 556 sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore); 557 phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle); 558 gpphTmlNfc_Context->pDevHandle = NULL; 559 /* Clear memory allocated for storing Context variables */ 560 free((void*)gpphTmlNfc_Context); 561 /* Set the pointer to NULL to indicate De-Initialization */ 562 gpphTmlNfc_Context = NULL; 563 564 return; 565 } 566 567 /******************************************************************************* 568 ** 569 ** Function phTmlNfc_Shutdown 570 ** 571 ** Description Uninitializes TML layer and hardware interface 572 ** 573 ** Parameters None 574 ** 575 ** Returns NFC status: 576 ** NFCSTATUS_SUCCESS - TML configuration released successfully 577 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 578 ** invalid 579 ** NFCSTATUS_FAILED - un-initialization failed (example: unable 580 ** to close interface) 581 ** 582 *******************************************************************************/ 583 NFCSTATUS phTmlNfc_Shutdown(void) { 584 NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS; 585 586 /* Check whether TML is Initialized */ 587 if (NULL != gpphTmlNfc_Context) { 588 /* Reset thread variable to terminate the thread */ 589 gpphTmlNfc_Context->bThreadDone = 0; 590 usleep(1000); 591 /* Clear All the resources allocated during initialization */ 592 sem_post(&gpphTmlNfc_Context->rxSemaphore); 593 usleep(1000); 594 sem_post(&gpphTmlNfc_Context->txSemaphore); 595 usleep(1000); 596 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 597 usleep(1000); 598 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 599 usleep(1000); 600 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) { 601 NXPLOG_TML_E("Fail to kill reader thread!"); 602 } 603 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) { 604 NXPLOG_TML_E("Fail to kill writer thread!"); 605 } 606 NXPLOG_TML_D("bThreadDone == 0"); 607 608 phTmlNfc_CleanUp(); 609 } else { 610 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 611 } 612 613 return wShutdownStatus; 614 } 615 616 /******************************************************************************* 617 ** 618 ** Function phTmlNfc_Write 619 ** 620 ** Description Asynchronously writes given data block to hardware 621 ** interface/driver. Enables writer thread if there are no 622 ** write requests pending. Returns successfully once writer 623 ** thread completes write operation. Notifies upper layer using 624 ** callback mechanism. 625 ** 626 ** NOTE: 627 ** * it is important to post a message with id 628 ** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data 629 ** has been written to PN54X 630 ** * if CRC needs to be computed, then input buffer should be 631 ** capable to store two more bytes apart from length of 632 ** packet 633 ** 634 ** Parameters pBuffer - data to be sent 635 ** wLength - length of data buffer 636 ** pTmlWriteComplete - pointer to the function to be invoked 637 ** upon completion 638 ** pContext - context provided by upper layer 639 ** 640 ** Returns NFC status: 641 ** NFCSTATUS_PENDING - command is yet to be processed 642 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 643 ** invalid 644 ** NFCSTATUS_BUSY - write request is already in progress 645 ** 646 *******************************************************************************/ 647 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength, 648 pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, 649 void* pContext) { 650 NFCSTATUS wWriteStatus; 651 652 /* Check whether TML is Initialized */ 653 654 if (NULL != gpphTmlNfc_Context) { 655 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) && 656 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) { 657 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { 658 /* Setting the flag marks beginning of a Write Operation */ 659 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; 660 /* Copy the buffer, length and Callback function, 661 This shall be utilized while invoking the Callback function in thread 662 */ 663 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer; 664 gpphTmlNfc_Context->tWriteInfo.wLength = wLength; 665 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete; 666 gpphTmlNfc_Context->tWriteInfo.pContext = pContext; 667 668 wWriteStatus = NFCSTATUS_PENDING; 669 // FIXME: If retry is going on. Stop the retry thread/timer 670 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) { 671 /* Set retry count to default value */ 672 // FIXME: If the timer expired there, and meanwhile we have created 673 // a new request. The expired timer will think that retry is still 674 // ongoing. 675 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount; 676 gpphTmlNfc_Context->bWriteCbInvoked = false; 677 } 678 /* Set event to invoke Writer Thread */ 679 gpphTmlNfc_Context->tWriteInfo.bEnable = 1; 680 sem_post(&gpphTmlNfc_Context->txSemaphore); 681 } else { 682 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 683 } 684 } else { 685 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 686 } 687 } else { 688 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 689 } 690 691 return wWriteStatus; 692 } 693 694 /******************************************************************************* 695 ** 696 ** Function phTmlNfc_Read 697 ** 698 ** Description Asynchronously reads data from the driver 699 ** Number of bytes to be read and buffer are passed by upper 700 ** layer. 701 ** Enables reader thread if there are no read requests pending 702 ** Returns successfully once read operation is completed 703 ** Notifies upper layer using callback mechanism 704 ** 705 ** Parameters pBuffer - location to send read data to the upper layer via 706 ** callback 707 ** wLength - length of read data buffer passed by upper layer 708 ** pTmlReadComplete - pointer to the function to be invoked 709 ** upon completion of read operation 710 ** pContext - context provided by upper layer 711 ** 712 ** Returns NFC status: 713 ** NFCSTATUS_PENDING - command is yet to be processed 714 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 715 ** invalid 716 ** NFCSTATUS_BUSY - read request is already in progress 717 ** 718 *******************************************************************************/ 719 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength, 720 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, 721 void* pContext) { 722 NFCSTATUS wReadStatus; 723 724 /* Check whether TML is Initialized */ 725 if (NULL != gpphTmlNfc_Context) { 726 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) && 727 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) { 728 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) { 729 /* Setting the flag marks beginning of a Read Operation */ 730 gpphTmlNfc_Context->tReadInfo.bThreadBusy = true; 731 /* Copy the buffer, length and Callback function, 732 This shall be utilized while invoking the Callback function in thread 733 */ 734 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer; 735 gpphTmlNfc_Context->tReadInfo.wLength = wLength; 736 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; 737 gpphTmlNfc_Context->tReadInfo.pContext = pContext; 738 wReadStatus = NFCSTATUS_PENDING; 739 740 /* Set event to invoke Reader Thread */ 741 gpphTmlNfc_Context->tReadInfo.bEnable = 1; 742 sem_post(&gpphTmlNfc_Context->rxSemaphore); 743 } else { 744 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 745 } 746 } else { 747 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 748 } 749 } else { 750 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 751 } 752 753 return wReadStatus; 754 } 755 756 /******************************************************************************* 757 ** 758 ** Function phTmlNfc_ReadAbort 759 ** 760 ** Description Aborts pending read request (if any) 761 ** 762 ** Parameters None 763 ** 764 ** Returns NFC status: 765 ** NFCSTATUS_SUCCESS - ongoing read operation aborted 766 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 767 ** invalid 768 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 769 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read 770 ** operation 771 ** 772 *******************************************************************************/ 773 NFCSTATUS phTmlNfc_ReadAbort(void) { 774 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 775 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 776 777 /*Reset the flag to accept another Read Request */ 778 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 779 wStatus = NFCSTATUS_SUCCESS; 780 781 return wStatus; 782 } 783 784 /******************************************************************************* 785 ** 786 ** Function phTmlNfc_WriteAbort 787 ** 788 ** Description Aborts pending write request (if any) 789 ** 790 ** Parameters None 791 ** 792 ** Returns NFC status: 793 ** NFCSTATUS_SUCCESS - ongoing write operation aborted 794 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 795 ** invalid 796 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 797 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write 798 ** operation 799 ** 800 *******************************************************************************/ 801 NFCSTATUS phTmlNfc_WriteAbort(void) { 802 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 803 804 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 805 /* Stop if any retransmission is in progress */ 806 bCurrentRetryCount = 0; 807 808 /* Reset the flag to accept another Write Request */ 809 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 810 wStatus = NFCSTATUS_SUCCESS; 811 812 return wStatus; 813 } 814 815 /******************************************************************************* 816 ** 817 ** Function phTmlNfc_IoCtl 818 ** 819 ** Description Resets device when insisted by upper layer 820 ** Number of bytes to be read and buffer are passed by upper 821 ** layer 822 ** Enables reader thread if there are no read requests pending 823 ** Returns successfully once read operation is completed 824 ** Notifies upper layer using callback mechanism 825 ** 826 ** Parameters eControlCode - control code for a specific operation 827 ** 828 ** Returns NFC status: 829 ** NFCSTATUS_SUCCESS - ioctl command completed successfully 830 ** NFCSTATUS_FAILED - ioctl command request failed 831 ** 832 *******************************************************************************/ 833 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) { 834 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 835 836 if (NULL == gpphTmlNfc_Context) { 837 wStatus = NFCSTATUS_FAILED; 838 } else { 839 switch (eControlCode) { 840 case phTmlNfc_e_ResetDevice: { 841 /*Reset PN54X*/ 842 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 843 usleep(100 * 1000); 844 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 845 usleep(100 * 1000); 846 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 847 break; 848 } 849 case phTmlNfc_e_EnableNormalMode: { 850 /*Reset PN54X*/ 851 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 852 usleep(10 * 1000); 853 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 854 usleep(100 * 1000); 855 break; 856 } 857 case phTmlNfc_e_EnableDownloadMode: { 858 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0); 859 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 2); 860 usleep(100 * 1000); 861 break; 862 } 863 default: { 864 wStatus = NFCSTATUS_INVALID_PARAMETER; 865 break; 866 } 867 } 868 } 869 870 return wStatus; 871 } 872 873 /******************************************************************************* 874 ** 875 ** Function phTmlNfc_DeferredCall 876 ** 877 ** Description Posts message on upper layer thread 878 ** upon successful read or write operation 879 ** 880 ** Parameters dwThreadId - id of the thread posting message 881 ** ptWorkerMsg - message to be posted 882 ** 883 ** Returns None 884 ** 885 *******************************************************************************/ 886 void phTmlNfc_DeferredCall(uintptr_t dwThreadId, 887 phLibNfc_Message_t* ptWorkerMsg) { 888 intptr_t bPostStatus; 889 UNUSED(dwThreadId); 890 /* Post message on the user thread to invoke the callback function */ 891 sem_wait(&gpphTmlNfc_Context->postMsgSemaphore); 892 bPostStatus = 893 phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0); 894 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 895 } 896 897 /******************************************************************************* 898 ** 899 ** Function phTmlNfc_ReadDeferredCb 900 ** 901 ** Description Read thread call back function 902 ** 903 ** Parameters pParams - context provided by upper layer 904 ** 905 ** Returns None 906 ** 907 *******************************************************************************/ 908 static void phTmlNfc_ReadDeferredCb(void* pParams) { 909 /* Transaction info buffer to be passed to Callback Function */ 910 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 911 912 /* Reset the flag to accept another Read Request */ 913 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 914 gpphTmlNfc_Context->tReadInfo.pThread_Callback( 915 gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo); 916 917 return; 918 } 919 920 /******************************************************************************* 921 ** 922 ** Function phTmlNfc_WriteDeferredCb 923 ** 924 ** Description Write thread call back function 925 ** 926 ** Parameters pParams - context provided by upper layer 927 ** 928 ** Returns None 929 ** 930 *******************************************************************************/ 931 static void phTmlNfc_WriteDeferredCb(void* pParams) { 932 /* Transaction info buffer to be passed to Callback Function */ 933 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 934 935 /* Reset the flag to accept another Write Request */ 936 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 937 gpphTmlNfc_Context->tWriteInfo.pThread_Callback( 938 gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo); 939 940 return; 941 } 942 943 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) { 944 fragmentation_enabled = result; 945 } 946 947 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() { 948 return fragmentation_enabled; 949 } 950