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 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 = NULL; 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 (NULL != 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 if (dwNoBytesWrRd > 260) 370 { 371 NXPLOG_TML_E ("Numer of bytes read exceeds the limit 260.....\n"); 372 sem_post (&gpphTmlNfc_Context->rxSemaphore); 373 } 374 else 375 { 376 memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd); 377 378 NXPLOG_TML_D("PN54X - I2C Read successful.....\n"); 379 /* This has to be reset only after a successful read */ 380 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 381 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 382 (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) 383 { 384 385 NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n"); 386 /* Stop Timer to prevent Retransmission */ 387 uint32_t timerStatus = phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId); 388 if (NFCSTATUS_SUCCESS != timerStatus) 389 { 390 NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n"); 391 } 392 else 393 { 394 gpphTmlNfc_Context->bWriteCbInvoked = FALSE; 395 } 396 } 397 if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) 398 { 399 NXPLOG_TML_D ("Delay Read if write thread is busy"); 400 usleep (2000); /*2ms delay to give prio to write complete */ 401 } 402 /* Update the actual number of bytes read including header */ 403 gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t) (dwNoBytesWrRd); 404 phNxpNciHal_print_packet("RECV", gpphTmlNfc_Context->tReadInfo.pBuffer, 405 gpphTmlNfc_Context->tReadInfo.wLength); 406 407 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 408 409 /* Fill the Transaction info structure to be passed to Callback Function */ 410 tTransactionInfo.wStatus = wStatus; 411 tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer; 412 /* Actual number of bytes read is filled in the structure */ 413 tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength; 414 415 /* Read operation completed successfully. Post a Message onto Callback Thread*/ 416 /* Prepare the message to be posted on User thread */ 417 tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb; 418 tDeferredInfo.pParameter = &tTransactionInfo; 419 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 420 tMsg.pMsgData = &tDeferredInfo; 421 tMsg.Size = sizeof(tDeferredInfo); 422 NXPLOG_TML_D("PN54X - Posting read message.....\n"); 423 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 424 425 } 426 } 427 else 428 { 429 NXPLOG_TML_D ("PN54X -gpphTmlNfc_Context->pDevHandle is NULL"); 430 } 431 } 432 else 433 { 434 NXPLOG_TML_D("PN54X - read request NOT enabled"); 435 usleep(10*1000); 436 } 437 }/* End of While loop */ 438 439 return; 440 } 441 442 /******************************************************************************* 443 ** 444 ** Function phTmlNfc_TmlWriterThread 445 ** 446 ** Description Writes the requested data onto the lower layer driver 447 ** 448 ** Parameters pParam - context provided by upper layer 449 ** 450 ** Returns None 451 ** 452 *******************************************************************************/ 453 static void phTmlNfc_TmlWriterThread(void *pParam) 454 { 455 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 456 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 457 /* Transaction info buffer to be passed to Callback Thread */ 458 static phTmlNfc_TransactInfo_t tTransactionInfo; 459 /* Structure containing Tml callback function and parameters to be invoked 460 by the callback thread */ 461 static phLibNfc_DeferredCall_t tDeferredInfo; 462 /* Initialize Message structure to post message onto Callback Thread */ 463 static phLibNfc_Message_t tMsg; 464 /* In case of I2C Write Retry */ 465 static uint16_t retry_cnt; 466 UNUSED(pParam); 467 NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n"); 468 469 /* Writer thread loop shall be running till shutdown is invoked */ 470 while (gpphTmlNfc_Context->bThreadDone) 471 { 472 NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n"); 473 sem_wait(&gpphTmlNfc_Context->txSemaphore); 474 /* If Tml write is requested */ 475 if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) 476 { 477 NXPLOG_TML_D("PN54X - Write requested.....\n"); 478 /* Set the variable to success initially */ 479 wStatus = NFCSTATUS_SUCCESS; 480 if (NULL != gpphTmlNfc_Context->pDevHandle) 481 { 482 retry: 483 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 484 /* Variable to fetch the actual number of bytes written */ 485 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE; 486 /* Write the data in the buffer onto the file */ 487 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n"); 488 dwNoBytesWrRd = phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle, 489 gpphTmlNfc_Context->tWriteInfo.pBuffer, 490 gpphTmlNfc_Context->tWriteInfo.wLength 491 ); 492 493 /* Try I2C Write Five Times, if it fails : Raju */ 494 if (-1 == dwNoBytesWrRd) 495 { 496 if (getDownloadFlag() == TRUE) 497 { 498 if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) 499 { 500 NXPLOG_NCIHAL_E( 501 "PN54X - Error in I2C Write - Retry 0x%x", retry_cnt); 502 goto retry; 503 } 504 } 505 NXPLOG_TML_E("PN54X - Error in I2C Write.....\n"); 506 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED); 507 } 508 else 509 { 510 phNxpNciHal_print_packet("SEND", gpphTmlNfc_Context->tWriteInfo.pBuffer, 511 gpphTmlNfc_Context->tWriteInfo.wLength); 512 } 513 retry_cnt = 0; 514 if (NFCSTATUS_SUCCESS == wStatus) 515 { 516 NXPLOG_TML_D("PN54X - I2C Write successful.....\n"); 517 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE; 518 } 519 /* Fill the Transaction info structure to be passed to Callback Function */ 520 tTransactionInfo.wStatus = wStatus; 521 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer; 522 /* Actual number of bytes written is filled in the structure */ 523 tTransactionInfo.wLength = (uint16_t) dwNoBytesWrRd; 524 525 /* Prepare the message to be posted on the User thread */ 526 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb; 527 tDeferredInfo.pParameter = &tTransactionInfo; 528 /* Write operation completed successfully. Post a Message onto Callback Thread*/ 529 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG; 530 tMsg.pMsgData = &tDeferredInfo; 531 tMsg.Size = sizeof(tDeferredInfo); 532 533 /* Check whether Retransmission needs to be started, 534 * If yes, Post message only if 535 * case 1. Message is not posted && 536 * case 11. Write status is success || 537 * case 12. Last retry of write is also failure 538 */ 539 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 540 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) 541 { 542 if (FALSE == gpphTmlNfc_Context->bWriteCbInvoked) 543 { 544 if ((NFCSTATUS_SUCCESS == wStatus) || 545 (bCurrentRetryCount == 0)) 546 { 547 NXPLOG_TML_D("PN54X - Posting Write message.....\n"); 548 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, 549 &tMsg); 550 gpphTmlNfc_Context->bWriteCbInvoked = TRUE; 551 } 552 } 553 } 554 else 555 { 556 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n"); 557 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg); 558 } 559 } 560 else 561 { 562 NXPLOG_TML_D ("PN54X - gpphTmlNfc_Context->pDevHandle is NULL"); 563 } 564 565 /* If Data packet is sent, then NO retransmission */ 566 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) && 567 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) 568 { 569 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case"); 570 wStatus = phTmlNfc_InitiateTimer(); 571 if (NFCSTATUS_SUCCESS != wStatus) 572 { 573 /* Reset Variables used for Retransmission */ 574 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed"); 575 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 576 bCurrentRetryCount = 0; 577 } 578 } 579 } 580 else 581 { 582 NXPLOG_TML_D("PN54X - Write request NOT enabled"); 583 usleep(10000); 584 } 585 586 }/* End of While loop */ 587 588 return; 589 } 590 591 /******************************************************************************* 592 ** 593 ** Function phTmlNfc_CleanUp 594 ** 595 ** Description Clears all handles opened during TML initialization 596 ** 597 ** Parameters None 598 ** 599 ** Returns None 600 ** 601 *******************************************************************************/ 602 static void phTmlNfc_CleanUp(void) 603 { 604 NFCSTATUS wRetval = NFCSTATUS_SUCCESS; 605 606 if (NULL != gpphTmlNfc_Context->pDevHandle) 607 { 608 (void) phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 609 gpphTmlNfc_Context->bThreadDone = 0; 610 } 611 sem_destroy(&gpphTmlNfc_Context->rxSemaphore); 612 sem_destroy(&gpphTmlNfc_Context->txSemaphore); 613 sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore); 614 phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle); 615 gpphTmlNfc_Context->pDevHandle = NULL; 616 /* Clear memory allocated for storing Context variables */ 617 free((void *) gpphTmlNfc_Context); 618 /* Set the pointer to NULL to indicate De-Initialization */ 619 gpphTmlNfc_Context = NULL; 620 621 return; 622 } 623 624 /******************************************************************************* 625 ** 626 ** Function phTmlNfc_Shutdown 627 ** 628 ** Description Uninitializes TML layer and hardware interface 629 ** 630 ** Parameters None 631 ** 632 ** Returns NFC status: 633 ** NFCSTATUS_SUCCESS - TML configuration released successfully 634 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is invalid 635 ** NFCSTATUS_FAILED - un-initialization failed (example: unable to close interface) 636 ** 637 *******************************************************************************/ 638 NFCSTATUS phTmlNfc_Shutdown(void) 639 { 640 NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS; 641 642 /* Check whether TML is Initialized */ 643 if (NULL != gpphTmlNfc_Context) 644 { 645 /* Reset thread variable to terminate the thread */ 646 gpphTmlNfc_Context->bThreadDone = 0; 647 usleep(1000); 648 /* Clear All the resources allocated during initialization */ 649 sem_post(&gpphTmlNfc_Context->rxSemaphore); 650 usleep(1000); 651 sem_post(&gpphTmlNfc_Context->txSemaphore); 652 usleep(1000); 653 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 654 usleep(1000); 655 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 656 usleep(1000); 657 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) 658 { 659 NXPLOG_TML_E ("Fail to kill reader thread!"); 660 } 661 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) 662 { 663 NXPLOG_TML_E ("Fail to kill writer thread!"); 664 } 665 NXPLOG_TML_D ("bThreadDone == 0"); 666 667 phTmlNfc_CleanUp(); 668 } 669 else 670 { 671 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 672 } 673 674 return wShutdownStatus; 675 } 676 677 /******************************************************************************* 678 ** 679 ** Function phTmlNfc_Write 680 ** 681 ** Description Asynchronously writes given data block to hardware interface/driver 682 ** Enables writer thread if there are no write requests pending 683 ** Returns successfully once writer thread completes write operation 684 ** Notifies upper layer using callback mechanism 685 ** NOTE: 686 ** * it is important to post a message with id PH_TMLNFC_WRITE_MESSAGE 687 ** to IntegrationThread after data has been written to PN54X 688 ** * if CRC needs to be computed, then input buffer should be capable to store 689 ** two more bytes apart from length of packet 690 ** 691 ** Parameters pBuffer - data to be sent 692 ** wLength - length of data buffer 693 ** pTmlWriteComplete - pointer to the function to be invoked upon completion 694 ** pContext - context provided by upper layer 695 ** 696 ** Returns NFC status: 697 ** NFCSTATUS_PENDING - command is yet to be processed 698 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is invalid 699 ** NFCSTATUS_BUSY - write request is already in progress 700 ** 701 *******************************************************************************/ 702 NFCSTATUS phTmlNfc_Write(uint8_t *pBuffer, uint16_t wLength, pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, void *pContext) 703 { 704 NFCSTATUS wWriteStatus; 705 706 /* Check whether TML is Initialized */ 707 708 if (NULL != gpphTmlNfc_Context) 709 { 710 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) && 711 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) 712 { 713 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) 714 { 715 /* Setting the flag marks beginning of a Write Operation */ 716 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = TRUE; 717 /* Copy the buffer, length and Callback function, 718 This shall be utilized while invoking the Callback function in thread */ 719 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer; 720 gpphTmlNfc_Context->tWriteInfo.wLength = wLength; 721 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete; 722 gpphTmlNfc_Context->tWriteInfo.pContext = pContext; 723 724 wWriteStatus = NFCSTATUS_PENDING; 725 //FIXME: If retry is going on. Stop the retry thread/timer 726 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) 727 { 728 /* Set retry count to default value */ 729 //FIXME: If the timer expired there, and meanwhile we have created 730 // a new request. The expired timer will think that retry is still 731 // ongoing. 732 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount; 733 gpphTmlNfc_Context->bWriteCbInvoked = FALSE; 734 } 735 /* Set event to invoke Writer Thread */ 736 gpphTmlNfc_Context->tWriteInfo.bEnable = 1; 737 sem_post(&gpphTmlNfc_Context->txSemaphore); 738 } 739 else 740 { 741 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 742 } 743 } 744 else 745 { 746 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 747 } 748 } 749 else 750 { 751 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 752 } 753 754 return wWriteStatus; 755 } 756 757 /******************************************************************************* 758 ** 759 ** Function phTmlNfc_Read 760 ** 761 ** Description Asynchronously reads data from the driver 762 ** Number of bytes to be read and buffer are passed by upper layer 763 ** Enables reader thread if there are no read requests pending 764 ** Returns successfully once read operation is completed 765 ** Notifies upper layer using callback mechanism 766 ** 767 ** Parameters pBuffer - location to send read data to the upper layer via callback 768 ** wLength - length of read data buffer passed by upper layer 769 ** pTmlReadComplete - pointer to the function to be invoked upon completion of read operation 770 ** pContext - context provided by upper layer 771 ** 772 ** Returns NFC status: 773 ** NFCSTATUS_PENDING - command is yet to be processed 774 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is invalid 775 ** NFCSTATUS_BUSY - read request is already in progress 776 ** 777 *******************************************************************************/ 778 NFCSTATUS phTmlNfc_Read(uint8_t *pBuffer, uint16_t wLength, pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, void *pContext) 779 { 780 NFCSTATUS wReadStatus; 781 782 /* Check whether TML is Initialized */ 783 if (NULL != gpphTmlNfc_Context) 784 { 785 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) && 786 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) 787 { 788 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) 789 { 790 /* Setting the flag marks beginning of a Read Operation */ 791 gpphTmlNfc_Context->tReadInfo.bThreadBusy = TRUE; 792 /* Copy the buffer, length and Callback function, 793 This shall be utilized while invoking the Callback function in thread */ 794 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer; 795 gpphTmlNfc_Context->tReadInfo.wLength = wLength; 796 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete; 797 gpphTmlNfc_Context->tReadInfo.pContext = pContext; 798 wReadStatus = NFCSTATUS_PENDING; 799 800 /* Set event to invoke Reader Thread */ 801 gpphTmlNfc_Context->tReadInfo.bEnable = 1; 802 sem_post(&gpphTmlNfc_Context->rxSemaphore); 803 } 804 else 805 { 806 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY); 807 } 808 } 809 else 810 { 811 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER); 812 } 813 } 814 else 815 { 816 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED); 817 } 818 819 return wReadStatus; 820 } 821 822 /******************************************************************************* 823 ** 824 ** Function phTmlNfc_ReadAbort 825 ** 826 ** Description Aborts pending read request (if any) 827 ** 828 ** Parameters None 829 ** 830 ** Returns NFC status: 831 ** NFCSTATUS_SUCCESS - ongoing read operation aborted 832 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is invalid 833 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 834 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read operation 835 ** 836 *******************************************************************************/ 837 NFCSTATUS phTmlNfc_ReadAbort(void) 838 { 839 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 840 gpphTmlNfc_Context->tReadInfo.bEnable = 0; 841 842 /*Reset the flag to accept another Read Request */ 843 gpphTmlNfc_Context->tReadInfo.bThreadBusy=FALSE; 844 wStatus = NFCSTATUS_SUCCESS; 845 846 return wStatus; 847 } 848 849 /******************************************************************************* 850 ** 851 ** Function phTmlNfc_WriteAbort 852 ** 853 ** Description Aborts pending write request (if any) 854 ** 855 ** Parameters None 856 ** 857 ** Returns NFC status: 858 ** NFCSTATUS_SUCCESS - ongoing write operation aborted 859 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is invalid 860 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized 861 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write operation 862 ** 863 *******************************************************************************/ 864 NFCSTATUS phTmlNfc_WriteAbort(void) 865 { 866 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER; 867 868 gpphTmlNfc_Context->tWriteInfo.bEnable = 0; 869 /* Stop if any retransmission is in progress */ 870 bCurrentRetryCount = 0; 871 872 /* Reset the flag to accept another Write Request */ 873 gpphTmlNfc_Context->tWriteInfo.bThreadBusy=FALSE; 874 wStatus = NFCSTATUS_SUCCESS; 875 876 return wStatus; 877 } 878 879 /******************************************************************************* 880 ** 881 ** Function phTmlNfc_IoCtl 882 ** 883 ** Description Resets device when insisted by upper layer 884 ** Number of bytes to be read and buffer are passed by upper layer 885 ** Enables reader thread if there are no read requests pending 886 ** Returns successfully once read operation is completed 887 ** Notifies upper layer using callback mechanism 888 ** 889 ** Parameters eControlCode - control code for a specific operation 890 ** 891 ** Returns NFC status: 892 ** NFCSTATUS_SUCCESS - ioctl command completed successfully 893 ** NFCSTATUS_FAILED - ioctl command request failed 894 ** 895 *******************************************************************************/ 896 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) 897 { 898 NFCSTATUS wStatus = NFCSTATUS_SUCCESS; 899 900 if (NULL == gpphTmlNfc_Context) 901 { 902 wStatus = NFCSTATUS_FAILED; 903 } 904 else 905 { 906 switch (eControlCode) 907 { 908 case phTmlNfc_e_ResetDevice: 909 { 910 /*Reset PN54X*/ 911 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 912 usleep(100 * 1000); 913 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 914 usleep(100 * 1000); 915 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 916 break; 917 } 918 case phTmlNfc_e_EnableNormalMode: 919 { 920 /*Reset PN54X*/ 921 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0); 922 usleep(10 * 1000); 923 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1); 924 usleep(100 * 1000); 925 break; 926 } 927 case phTmlNfc_e_EnableDownloadMode: 928 { 929 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0); 930 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle,2); 931 usleep(100 * 1000); 932 break; 933 } 934 default: 935 { 936 wStatus = NFCSTATUS_INVALID_PARAMETER; 937 break; 938 } 939 } 940 } 941 942 return wStatus; 943 } 944 945 /******************************************************************************* 946 ** 947 ** Function phTmlNfc_DeferredCall 948 ** 949 ** Description Posts message on upper layer thread 950 ** upon successful read or write operation 951 ** 952 ** Parameters dwThreadId - id of the thread posting message 953 ** ptWorkerMsg - message to be posted 954 ** 955 ** Returns None 956 ** 957 *******************************************************************************/ 958 void phTmlNfc_DeferredCall(uintptr_t dwThreadId, phLibNfc_Message_t *ptWorkerMsg) 959 { 960 intptr_t bPostStatus; 961 UNUSED(dwThreadId); 962 /* Post message on the user thread to invoke the callback function */ 963 sem_wait(&gpphTmlNfc_Context->postMsgSemaphore); 964 bPostStatus = phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, 965 ptWorkerMsg, 966 0 967 ); 968 sem_post(&gpphTmlNfc_Context->postMsgSemaphore); 969 } 970 971 /******************************************************************************* 972 ** 973 ** Function phTmlNfc_ReadDeferredCb 974 ** 975 ** Description Read thread call back function 976 ** 977 ** Parameters pParams - context provided by upper layer 978 ** 979 ** Returns None 980 ** 981 *******************************************************************************/ 982 static void phTmlNfc_ReadDeferredCb(void *pParams) 983 { 984 /* Transaction info buffer to be passed to Callback Function */ 985 phTmlNfc_TransactInfo_t *pTransactionInfo = (phTmlNfc_TransactInfo_t *) pParams; 986 987 /* Reset the flag to accept another Read Request */ 988 gpphTmlNfc_Context->tReadInfo.bThreadBusy = FALSE; 989 gpphTmlNfc_Context->tReadInfo.pThread_Callback(gpphTmlNfc_Context->tReadInfo.pContext, 990 pTransactionInfo); 991 992 return; 993 } 994 995 /******************************************************************************* 996 ** 997 ** Function phTmlNfc_WriteDeferredCb 998 ** 999 ** Description Write thread call back function 1000 ** 1001 ** Parameters pParams - context provided by upper layer 1002 ** 1003 ** Returns None 1004 ** 1005 *******************************************************************************/ 1006 static void phTmlNfc_WriteDeferredCb(void *pParams) 1007 { 1008 /* Transaction info buffer to be passed to Callback Function */ 1009 phTmlNfc_TransactInfo_t *pTransactionInfo = (phTmlNfc_TransactInfo_t *) pParams; 1010 1011 /* Reset the flag to accept another Write Request */ 1012 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = FALSE; 1013 gpphTmlNfc_Context->tWriteInfo.pThread_Callback(gpphTmlNfc_Context->tWriteInfo.pContext, 1014 pTransactionInfo); 1015 1016 return; 1017 } 1018 1019 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) 1020 { 1021 fragmentation_enabled = result; 1022 } 1023 1024 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() 1025 { 1026 return fragmentation_enabled; 1027 } 1028