Home | History | Annotate | Download | only in tml
      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