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 /* Local Function prototypes */ 45 static NFCSTATUS phTmlNfc_StartThread(void); 46 static void phTmlNfc_CleanUp(void); 47 static void phTmlNfc_ReadDeferredCb(void* pParams); 48 static void phTmlNfc_WriteDeferredCb(void* pParams); 49 static void * phTmlNfc_TmlThread(void* pParam); 50 static void * phTmlNfc_TmlWriterThread(void* pParam); 51 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext); 52 static NFCSTATUS phTmlNfc_InitiateTimer(void); 53 54 /* Function definitions */ 55 56 /******************************************************************************* 57 ** 58 ** Function phTmlNfc_Init 59 ** 60 ** Description Provides initialization of TML layer and hardware interface 61 ** Configures given hardware interface and sends handle to the 62 ** caller 63 ** 64 ** Parameters pConfig - TML configuration details as provided by the upper 65 ** layer 66 ** 67 ** Returns NFC status: 68 ** NFCSTATUS_SUCCESS - initialization successful 69 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 70 ** invalid 71 ** NFCSTATUS_FAILED - initialization failed (for example, 72 ** unable to open hardware interface) 73 ** NFCSTATUS_INVALID_DEVICE - device has not been opened or has 74 ** been disconnected 75 ** 76 *******************************************************************************/ 77 NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) { 78 NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS; 79 80 /* Check if TML layer is already Initialized */ 81 if (NULL != gpphTmlNfc_Context) { 82 /* TML initialization is already completed */ 83 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED); 84 } 85 /* Validate Input parameters */ 86 else if ((NULL == pConfig) || 87 (PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) { 88 /*Parameters passed to TML init are wrong */ 89 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 90 } else { 91 /* Allocate memory for TML context */ 92 gpphTmlNfc_Context = (phTmlNfc_Context_t *)malloc(sizeof(phTmlNfc_Context_t)); 93 94 if (NULL == gpphTmlNfc_Context) { 95 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 96 } else { 97 /* Initialise all the internal TML variables */ 98 memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE, 99 sizeof(phTmlNfc_Context_t)); 100 /* Make sure that the thread runs once it is created */ 101 gpphTmlNfc_Context->bThreadDone = 1; 102 103 /* Open the device file to which data is read/written */ 104 wInitStatus = phTmlNfc_i2c_open_and_configure( 105 pConfig, &(gpphTmlNfc_Context->pDevHandle)); 106 107 if (NFCSTATUS_SUCCESS != wInitStatus) { 108 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE); 109 gpphTmlNfc_Context->pDevHandle = NULL; 110 } else { 111 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 112 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 113 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 114 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 115 if (pthread_mutex_init(&gpphTmlNfc_Context->readInfoUpdateMutex, 116 NULL) == -1) { 117 wInitStatus = NFCSTATUS_FAILED; 118 } else if (0 != sem_init(&gpphTmlNfc_Context->rxSemaphore, 0, 0)) { 119 wInitStatus = NFCSTATUS_FAILED; 120 } else if (0 != sem_init(&gpphTmlNfc_Context->txSemaphore, 0, 0)) { 121 wInitStatus = NFCSTATUS_FAILED; 122 } else if (0 != sem_init(&gpphTmlNfc_Context->postMsgSemaphore, 0, 0)) { 123 wInitStatus = NFCSTATUS_FAILED; 124 } else { 125 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 126 /* Start TML thread (to handle write and read operations) */ 127 if (NFCSTATUS_SUCCESS != phTmlNfc_StartThread()) { 128 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 129 } else { 130 /* Create Timer used for Retransmission of NCI packets */ 131 gpphTmlNfc_Context->dwTimerId = phOsalNfc_Timer_Create(); 132 if (PH_OSALNFC_TIMER_ID_INVALID != gpphTmlNfc_Context->dwTimerId) { 133 /* Store the Thread Identifier to which Message is to be posted */ 134 gpphTmlNfc_Context->dwCallbackThreadId = 135 pConfig->dwGetMsgThreadId; 136 /* Enable retransmission of Nci packet & set retry count to 137 * default */ 138 gpphTmlNfc_Context->eConfig = phTmlNfc_e_DisableRetrans; 139 /* Retry Count = Standby Recovery time of NFCC / Retransmission 140 * time + 1 */ 141 gpphTmlNfc_Context->bRetryCount = 142 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; 143 gpphTmlNfc_Context->bWriteCbInvoked = false; 144 } else { 145 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 146 } 147 } 148 } 149 } 150 } 151 } 152 /* Clean up all the TML resources if any error */ 153 if (NFCSTATUS_SUCCESS != wInitStatus) { 154 /* Clear all handles and memory locations initialized during init */ 155 phTmlNfc_CleanUp(); 156 } 157 158 return wInitStatus; 159 } 160 161 /******************************************************************************* 162 ** 163 ** Function phTmlNfc_ConfigNciPktReTx 164 ** 165 ** Description Provides Enable/Disable Retransmission of NCI packets 166 ** Needed in case of Timeout between Transmission and Reception 167 ** of NCI packets. Retransmission can be enabled only if 168 ** standby mode is enabled 169 ** 170 ** Parameters eConfig - values from phTmlNfc_ConfigRetrans_t 171 ** bRetryCount - Number of times Nci packets shall be 172 ** retransmitted (default = 3) 173 ** 174 ** Returns None 175 ** 176 *******************************************************************************/ 177 void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration, 178 uint8_t bRetryCounter) { 179 /* Enable/Disable Retransmission */ 180 181 gpphTmlNfc_Context->eConfig = eConfiguration; 182 if (phTmlNfc_e_EnableRetrans == eConfiguration) { 183 /* Check whether Retry counter passed is valid */ 184 if (0 != bRetryCounter) { 185 gpphTmlNfc_Context->bRetryCount = bRetryCounter; 186 } 187 /* Set retry counter to its default value */ 188 else { 189 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 190 */ 191 gpphTmlNfc_Context->bRetryCount = 192 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1; 193 } 194 } 195 196 return; 197 } 198 199 /******************************************************************************* 200 ** 201 ** Function phTmlNfc_StartThread 202 ** 203 ** Description Initializes comport, reader and writer threads 204 ** 205 ** Parameters None 206 ** 207 ** Returns NFC status: 208 ** NFCSTATUS_SUCCESS - threads initialized successfully 209 ** NFCSTATUS_FAILED - initialization failed due to system error 210 ** 211 *******************************************************************************/ 212 static NFCSTATUS phTmlNfc_StartThread(void) { 213 NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS; 214 void* h_threadsEvent = 0x00; 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 &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 &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 pthread_mutex_lock(&gpphTmlNfc_Context->readInfoUpdateMutex); 343 memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd); 344 345 NXPLOG_TML_D("PN54X - I2C Read successful.....\n"); 346 /* This has to be reset only after a successful read */ 347 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 348 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 349 (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) { 350 NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n"); 351 /* Stop Timer to prevent Retransmission */ 352 uint32_t timerStatus = 353 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId); 354 if (NFCSTATUS_SUCCESS != timerStatus) { 355 NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n"); 356 } else { 357 gpphTmlNfc_Context->bWriteCbInvoked = false; 358 } 359 } 360 if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { 361 NXPLOG_TML_D("Delay Read if write thread is busy"); 362 usleep(2000); /*2ms delay to give prio to write complete */ 363 } 364 /* Update the actual number of bytes read including header */ 365 gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd); 366 phNxpNciHal_print_packet("RECV", 367 gpphTmlNfc_Context->tReadInfo.pBuffer, 368 gpphTmlNfc_Context->tReadInfo.wLength); 369 370 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 371 372 /* Fill the Transaction info structure to be passed to Callback 373 * Function */ 374 tTransactionInfo.wStatus = wStatus; 375 tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer; 376 /* Actual number of bytes read is filled in the structure */ 377 tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength; 378 379 /* Read operation completed successfully. Post a Message onto Callback 380 * Thread*/ 381 /* Prepare the message to be posted on User thread */ 382 tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb; 383 tDeferredInfo.pParameter = &tTransactionInfo; 384 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 385 tMsg.pMsgData = &tDeferredInfo; 386 tMsg.Size = sizeof(tDeferredInfo); 387 pthread_mutex_unlock(&gpphTmlNfc_Context->readInfoUpdateMutex); 388 NXPLOG_TML_D("PN54X - Posting read message.....\n"); 389 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 390 } 391 } else { 392 NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL"); 393 } 394 } else { 395 NXPLOG_TML_D("PN54X - read request NOT enabled"); 396 usleep(10 * 1000); 397 } 398 } /* End of While loop */ 399 400 return NULL; 401 } 402 403 /******************************************************************************* 404 ** 405 ** Function phTmlNfc_TmlWriterThread 406 ** 407 ** Description Writes the requested data onto the lower layer driver 408 ** 409 ** Parameters pParam - context provided by upper layer 410 ** 411 ** Returns None 412 ** 413 *******************************************************************************/ 414 static void * phTmlNfc_TmlWriterThread(void* pParam) { 415 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 416 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 417 /* Transaction info buffer to be passed to Callback Thread */ 418 static phTmlNfc_TransactInfo_t tTransactionInfo; 419 /* Structure containing Tml callback function and parameters to be invoked 420 by the callback thread */ 421 static phLibNfc_DeferredCall_t tDeferredInfo; 422 /* Initialize Message structure to post message onto Callback Thread */ 423 static phLibNfc_Message_t tMsg; 424 /* In case of I2C Write Retry */ 425 static uint16_t retry_cnt; 426 UNUSED(pParam); 427 NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n"); 428 429 /* Writer thread loop shall be running till shutdown is invoked */ 430 while (gpphTmlNfc_Context->bThreadDone) { 431 NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n"); 432 sem_wait(&gpphTmlNfc_Context->txSemaphore); 433 /* If Tml write is requested */ 434 if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) { 435 NXPLOG_TML_D("PN54X - Write requested.....\n"); 436 /* Set the variable to success initially */ 437 wStatus = NFCSTATUS_SUCCESS; 438 if (NULL != gpphTmlNfc_Context->pDevHandle) { 439 retry: 440 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 441 /* Variable to fetch the actual number of bytes written */ 442 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 443 /* Write the data in the buffer onto the file */ 444 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n"); 445 dwNoBytesWrRd = 446 phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle, 447 gpphTmlNfc_Context->tWriteInfo.pBuffer, 448 gpphTmlNfc_Context->tWriteInfo.wLength); 449 450 /* Try I2C Write Five Times, if it fails : Raju */ 451 if (-1 == dwNoBytesWrRd) { 452 if (getDownloadFlag() == true) { 453 if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) { 454 NXPLOG_NCIHAL_E("PN54X - Error in I2C Write - Retry 0x%x", 455 retry_cnt); 456 // Add a 10 ms delay to ensure NFCC is not still in stand by mode. 457 usleep(10 * 1000); 458 goto retry; 459 } 460 } 461 NXPLOG_TML_E("PN54X - Error in I2C Write.....\n"); 462 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 463 } else { 464 phNxpNciHal_print_packet("SEND", 465 gpphTmlNfc_Context->tWriteInfo.pBuffer, 466 gpphTmlNfc_Context->tWriteInfo.wLength); 467 } 468 retry_cnt = 0; 469 if (NFCSTATUS_SUCCESS == wStatus) { 470 NXPLOG_TML_D("PN54X - I2C Write successful.....\n"); 471 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE; 472 } 473 /* Fill the Transaction info structure to be passed to Callback Function 474 */ 475 tTransactionInfo.wStatus = wStatus; 476 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer; 477 /* Actual number of bytes written is filled in the structure */ 478 tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd; 479 480 /* Prepare the message to be posted on the User thread */ 481 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb; 482 tDeferredInfo.pParameter = &tTransactionInfo; 483 /* Write operation completed successfully. Post a Message onto Callback 484 * Thread*/ 485 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 486 tMsg.pMsgData = &tDeferredInfo; 487 tMsg.Size = sizeof(tDeferredInfo); 488 489 /* Check whether Retransmission needs to be started, 490 * If yes, Post message only if 491 * case 1. Message is not posted && 492 * case 11. Write status is success || 493 * case 12. Last retry of write is also failure 494 */ 495 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 496 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 497 if (gpphTmlNfc_Context->bWriteCbInvoked == false) { 498 if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) { 499 NXPLOG_TML_D("PN54X - Posting Write message.....\n"); 500 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, 501 &tMsg); 502 gpphTmlNfc_Context->bWriteCbInvoked = true; 503 } 504 } 505 } else { 506 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n"); 507 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 508 } 509 } else { 510 NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL"); 511 } 512 513 /* If Data packet is sent, then NO retransmission */ 514 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 515 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) { 516 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case"); 517 wStatus = phTmlNfc_InitiateTimer(); 518 if (NFCSTATUS_SUCCESS != wStatus) { 519 /* Reset Variables used for Retransmission */ 520 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed"); 521 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 522 bCurrentRetryCount = 0; 523 } 524 } 525 } else { 526 NXPLOG_TML_D("PN54X - Write request NOT enabled"); 527 usleep(10000); 528 } 529 530 } /* End of While loop */ 531 532 return NULL; 533 } 534 535 /******************************************************************************* 536 ** 537 ** Function phTmlNfc_CleanUp 538 ** 539 ** Description Clears all handles opened during TML initialization 540 ** 541 ** Parameters None 542 ** 543 ** Returns None 544 ** 545 *******************************************************************************/ 546 static void phTmlNfc_CleanUp(void) { 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 pthread_mutex_destroy(&gpphTmlNfc_Context->readInfoUpdateMutex); 601 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) { 602 NXPLOG_TML_E("Fail to kill reader thread!"); 603 } 604 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) { 605 NXPLOG_TML_E("Fail to kill writer thread!"); 606 } 607 NXPLOG_TML_D("bThreadDone == 0"); 608 609 phTmlNfc_CleanUp(); 610 } else { 611 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 612 } 613 614 return wShutdownStatus; 615 } 616 617 /******************************************************************************* 618 ** 619 ** Function phTmlNfc_Write 620 ** 621 ** Description Asynchronously writes given data block to hardware 622 ** interface/driver. Enables writer thread if there are no 623 ** write requests pending. Returns successfully once writer 624 ** thread completes write operation. Notifies upper layer using 625 ** callback mechanism. 626 ** 627 ** NOTE: 628 ** * it is important to post a message with id 629 ** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data 630 ** has been written to PN54X 631 ** * if CRC needs to be computed, then input buffer should be 632 ** capable to store two more bytes apart from length of 633 ** packet 634 ** 635 ** Parameters pBuffer - data to be sent 636 ** wLength - length of data buffer 637 ** pTmlWriteComplete - pointer to the function to be invoked 638 ** upon completion 639 ** pContext - context provided by upper layer 640 ** 641 ** Returns NFC status: 642 ** NFCSTATUS_PENDING - command is yet to be processed 643 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 644 ** invalid 645 ** NFCSTATUS_BUSY - write request is already in progress 646 ** 647 *******************************************************************************/ 648 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength, 649 pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, 650 void* pContext) { 651 NFCSTATUS wWriteStatus; 652 653 /* Check whether TML is Initialized */ 654 655 if (NULL != gpphTmlNfc_Context) { 656 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) && 657 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) { 658 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) { 659 /* Setting the flag marks beginning of a Write Operation */ 660 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true; 661 /* Copy the buffer, length and Callback function, 662 This shall be utilized while invoking the Callback function in thread 663 */ 664 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer; 665 gpphTmlNfc_Context->tWriteInfo.wLength = wLength; 666 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete; 667 gpphTmlNfc_Context->tWriteInfo.pContext = pContext; 668 669 wWriteStatus = NFCSTATUS_PENDING; 670 // FIXME: If retry is going on. Stop the retry thread/timer 671 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) { 672 /* Set retry count to default value */ 673 // FIXME: If the timer expired there, and meanwhile we have created 674 // a new request. The expired timer will think that retry is still 675 // ongoing. 676 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount; 677 gpphTmlNfc_Context->bWriteCbInvoked = false; 678 } 679 /* Set event to invoke Writer Thread */ 680 gpphTmlNfc_Context->tWriteInfo.bEnable = 1; 681 sem_post(&gpphTmlNfc_Context->txSemaphore); 682 } else { 683 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 684 } 685 } else { 686 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 687 } 688 } else { 689 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 690 } 691 692 return wWriteStatus; 693 } 694 695 /******************************************************************************* 696 ** 697 ** Function phTmlNfc_UpdateReadCompleteCallback 698 ** 699 ** Description Updates the callback to be invoked after read completed 700 ** 701 ** Parameters pTmlReadComplete - pointer to the function to be invoked 702 ** upon completion of read operation 703 ** 704 ** Returns NFC status: 705 ** NFCSTATUS_SUCCESS - if TmlNfc context available 706 ** NFCSTATUS_FAILED - otherwise 707 ** 708 *******************************************************************************/ 709 NFCSTATUS phTmlNfc_UpdateReadCompleteCallback ( 710 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete) { 711 NFCSTATUS wStatus = NFCSTATUS_FAILED; 712 if ((NULL != gpphTmlNfc_Context) && (NULL != pTmlReadComplete)) { 713 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; 714 wStatus = NFCSTATUS_SUCCESS; 715 } 716 return wStatus; 717 } 718 719 /******************************************************************************* 720 ** 721 ** Function phTmlNfc_Read 722 ** 723 ** Description Asynchronously reads data from the driver 724 ** Number of bytes to be read and buffer are passed by upper 725 ** layer. 726 ** Enables reader thread if there are no read requests pending 727 ** Returns successfully once read operation is completed 728 ** Notifies upper layer using callback mechanism 729 ** 730 ** Parameters pBuffer - location to send read data to the upper layer via 731 ** callback 732 ** wLength - length of read data buffer passed by upper layer 733 ** pTmlReadComplete - pointer to the function to be invoked 734 ** upon completion of read operation 735 ** pContext - context provided by upper layer 736 ** 737 ** Returns NFC status: 738 ** NFCSTATUS_PENDING - command is yet to be processed 739 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 740 ** invalid 741 ** NFCSTATUS_BUSY - read request is already in progress 742 ** 743 *******************************************************************************/ 744 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength, 745 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, 746 void* pContext) { 747 NFCSTATUS wReadStatus; 748 749 /* Check whether TML is Initialized */ 750 if (NULL != gpphTmlNfc_Context) { 751 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) && 752 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) { 753 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) { 754 pthread_mutex_lock(&gpphTmlNfc_Context->readInfoUpdateMutex); 755 /* Setting the flag marks beginning of a Read Operation */ 756 gpphTmlNfc_Context->tReadInfo.bThreadBusy = true; 757 /* Copy the buffer, length and Callback function, 758 This shall be utilized while invoking the Callback function in thread 759 */ 760 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer; 761 gpphTmlNfc_Context->tReadInfo.wLength = wLength; 762 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; 763 gpphTmlNfc_Context->tReadInfo.pContext = pContext; 764 wReadStatus = NFCSTATUS_PENDING; 765 766 /* Set event to invoke Reader Thread */ 767 gpphTmlNfc_Context->tReadInfo.bEnable = 1; 768 pthread_mutex_unlock(&gpphTmlNfc_Context->readInfoUpdateMutex); 769 770 sem_post(&gpphTmlNfc_Context->rxSemaphore); 771 } else { 772 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 773 } 774 } else { 775 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 776 } 777 } else { 778 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 779 } 780 781 return wReadStatus; 782 } 783 784 /******************************************************************************* 785 ** 786 ** Function phTmlNfc_ReadAbort 787 ** 788 ** Description Aborts pending read request (if any) 789 ** 790 ** Parameters None 791 ** 792 ** Returns NFC status: 793 ** NFCSTATUS_SUCCESS - ongoing read 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 read 798 ** operation 799 ** 800 *******************************************************************************/ 801 NFCSTATUS phTmlNfc_ReadAbort(void) { 802 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 803 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 804 805 /*Reset the flag to accept another Read Request */ 806 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 807 wStatus = NFCSTATUS_SUCCESS; 808 809 return wStatus; 810 } 811 812 /******************************************************************************* 813 ** 814 ** Function phTmlNfc_WriteAbort 815 ** 816 ** Description Aborts pending write request (if any) 817 ** 818 ** Parameters None 819 ** 820 ** Returns NFC status: 821 ** NFCSTATUS_SUCCESS - ongoing write operation aborted 822 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is 823 ** invalid 824 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 825 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write 826 ** operation 827 ** 828 *******************************************************************************/ 829 NFCSTATUS phTmlNfc_WriteAbort(void) { 830 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 831 832 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 833 /* Stop if any retransmission is in progress */ 834 bCurrentRetryCount = 0; 835 836 /* Reset the flag to accept another Write Request */ 837 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 838 wStatus = NFCSTATUS_SUCCESS; 839 840 return wStatus; 841 } 842 843 /******************************************************************************* 844 ** 845 ** Function phTmlNfc_IoCtl 846 ** 847 ** Description Resets device when insisted by upper layer 848 ** Number of bytes to be read and buffer are passed by upper 849 ** layer 850 ** Enables reader thread if there are no read requests pending 851 ** Returns successfully once read operation is completed 852 ** Notifies upper layer using callback mechanism 853 ** 854 ** Parameters eControlCode - control code for a specific operation 855 ** 856 ** Returns NFC status: 857 ** NFCSTATUS_SUCCESS - ioctl command completed successfully 858 ** NFCSTATUS_FAILED - ioctl command request failed 859 ** 860 *******************************************************************************/ 861 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) { 862 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 863 864 if (NULL == gpphTmlNfc_Context) { 865 wStatus = NFCSTATUS_FAILED; 866 } else { 867 switch (eControlCode) { 868 case phTmlNfc_e_ResetDevice: { 869 /*Reset PN54X*/ 870 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 871 usleep(100 * 1000); 872 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 873 usleep(100 * 1000); 874 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 875 break; 876 } 877 case phTmlNfc_e_EnableNormalMode: { 878 /*Reset PN54X*/ 879 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 880 usleep(10 * 1000); 881 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 882 usleep(100 * 1000); 883 break; 884 } 885 case phTmlNfc_e_EnableDownloadMode: { 886 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0); 887 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 2); 888 usleep(100 * 1000); 889 break; 890 } 891 default: { 892 wStatus = NFCSTATUS_INVALID_PARAMETER; 893 break; 894 } 895 } 896 } 897 898 return wStatus; 899 } 900 901 /******************************************************************************* 902 ** 903 ** Function phTmlNfc_DeferredCall 904 ** 905 ** Description Posts message on upper layer thread 906 ** upon successful read or write operation 907 ** 908 ** Parameters dwThreadId - id of the thread posting message 909 ** ptWorkerMsg - message to be posted 910 ** 911 ** Returns None 912 ** 913 *******************************************************************************/ 914 void phTmlNfc_DeferredCall(uintptr_t dwThreadId, 915 phLibNfc_Message_t* ptWorkerMsg) { 916 intptr_t bPostStatus; 917 UNUSED(dwThreadId); 918 /* Post message on the user thread to invoke the callback function */ 919 sem_wait(&gpphTmlNfc_Context->postMsgSemaphore); 920 bPostStatus = 921 phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0); 922 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 923 } 924 925 /******************************************************************************* 926 ** 927 ** Function phTmlNfc_ReadDeferredCb 928 ** 929 ** Description Read thread call back function 930 ** 931 ** Parameters pParams - context provided by upper layer 932 ** 933 ** Returns None 934 ** 935 *******************************************************************************/ 936 static void phTmlNfc_ReadDeferredCb(void* pParams) { 937 /* Transaction info buffer to be passed to Callback Function */ 938 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 939 940 /* Reset the flag to accept another Read Request */ 941 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false; 942 gpphTmlNfc_Context->tReadInfo.pThread_Callback( 943 gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo); 944 945 return; 946 } 947 948 /******************************************************************************* 949 ** 950 ** Function phTmlNfc_WriteDeferredCb 951 ** 952 ** Description Write thread call back function 953 ** 954 ** Parameters pParams - context provided by upper layer 955 ** 956 ** Returns None 957 ** 958 *******************************************************************************/ 959 static void phTmlNfc_WriteDeferredCb(void* pParams) { 960 /* Transaction info buffer to be passed to Callback Function */ 961 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams; 962 963 /* Reset the flag to accept another Write Request */ 964 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false; 965 gpphTmlNfc_Context->tWriteInfo.pThread_Callback( 966 gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo); 967 968 return; 969 } 970 971 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) { 972 fragmentation_enabled = result; 973 } 974 975 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() { 976 return fragmentation_enabled; 977 } 978