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 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