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