• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010-2021 NXP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * TML Implementation.
19  */
20 
21 #include <phDal4Nfc_messageQueueLib.h>
22 #include <phNxpConfig.h>
23 #include <phNxpLog.h>
24 #include <phNxpNciHal_utils.h>
25 #include <phOsalNfc_Timer.h>
26 #include <phTmlNfc.h>
27 #include "NfccTransportFactory.h"
28 
29 /*
30  * Duration of Timer to wait after sending an Nci packet
31  */
32 #define PHTMLNFC_MAXTIME_RETRANSMIT (200U)
33 #define MAX_WRITE_RETRY_COUNT 0x03
34 #define MAX_READ_RETRY_DELAY_IN_MILLISEC (150U)
35 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 */
36 static uint8_t bCurrentRetryCount = (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
37 
38 /* Value to reset variables of TML  */
39 #define PH_TMLNFC_RESET_VALUE (0x00)
40 
41 /* Indicates a Initial or offset value */
42 #define PH_TMLNFC_VALUE_ONE (0x01)
43 
44 spTransport gpTransportObj;
45 extern bool_t gsIsFirstHalMinOpen;
46 
47 /* Initialize Context structure pointer used to access context structure */
48 phTmlNfc_Context_t* gpphTmlNfc_Context = NULL;
49 /* Local Function prototypes */
50 static NFCSTATUS phTmlNfc_StartThread(void);
51 static void phTmlNfc_ReadDeferredCb(void* pParams);
52 static void phTmlNfc_WriteDeferredCb(void* pParams);
53 static void* phTmlNfc_TmlThread(void* pParam);
54 static void* phTmlNfc_TmlWriterThread(void* pParam);
55 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext);
56 static NFCSTATUS phTmlNfc_InitiateTimer(void);
57 static void phTmlNfc_SignalWriteComplete(void);
58 static int phTmlNfc_WaitReadInit(void);
59 
60 /* Function definitions */
61 
62 /*******************************************************************************
63 **
64 ** Function         phTmlNfc_Init
65 **
66 ** Description      Provides initialization of TML layer and hardware interface
67 **                  Configures given hardware interface and sends handle to the
68 **                  caller
69 **
70 ** Parameters       pConfig - TML configuration details as provided by the upper
71 **                            layer
72 **
73 ** Returns          NFC status:
74 **                  NFCSTATUS_SUCCESS - initialization successful
75 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
76 **                                                invalid
77 **                  NFCSTATUS_FAILED - initialization failed (for example,
78 **                                     unable to open hardware interface)
79 **                  NFCSTATUS_INVALID_DEVICE - device has not been opened or has
80 **                                             been disconnected
81 **
82 *******************************************************************************/
phTmlNfc_Init(pphTmlNfc_Config_t pConfig)83 NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) {
84   NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS;
85 
86   /* Check if TML layer is already Initialized */
87   if (NULL != gpphTmlNfc_Context) {
88     /* TML initialization is already completed */
89     wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED);
90   }
91   /* Validate Input parameters */
92   else if ((NULL == pConfig) ||
93            (PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) {
94     /*Parameters passed to TML init are wrong */
95     wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
96   } else {
97     /* Allocate memory for TML context */
98     gpphTmlNfc_Context =
99         (phTmlNfc_Context_t*)malloc(sizeof(phTmlNfc_Context_t));
100 
101     if (NULL == gpphTmlNfc_Context) {
102       wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
103     } else {
104       /*Configure transport layer for communication*/
105       if ((gpTransportObj == NULL) &&
106           (NFCSTATUS_SUCCESS != phTmlNfc_ConfigTransport()))
107         return NFCSTATUS_FAILED;
108 
109       if (gsIsFirstHalMinOpen) {
110         if (!gpTransportObj->Flushdata(pConfig)) {
111           NXPLOG_NCIHAL_E("Flushdata Failed");
112         }
113       }
114       /* Initialise all the internal TML variables */
115       memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE,
116              sizeof(phTmlNfc_Context_t));
117       /* Make sure that the thread runs once it is created */
118       gpphTmlNfc_Context->bThreadDone = 1;
119       /* Open the device file to which data is read/written */
120       wInitStatus = gpTransportObj->OpenAndConfigure(
121           pConfig, &(gpphTmlNfc_Context->pDevHandle));
122 
123       if (NFCSTATUS_SUCCESS != wInitStatus) {
124         wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE);
125         gpphTmlNfc_Context->pDevHandle = NULL;
126       } else {
127         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
128         gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
129         gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
130         gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
131         gpphTmlNfc_Context->fragment_len = pConfig->fragment_len;
132 
133         if (0 != sem_init(&gpphTmlNfc_Context->rxSemaphore, 0, 0)) {
134           wInitStatus = NFCSTATUS_FAILED;
135         } else if (0 != phTmlNfc_WaitReadInit()) {
136           wInitStatus = NFCSTATUS_FAILED;
137         } else if (0 != sem_init(&gpphTmlNfc_Context->txSemaphore, 0, 0)) {
138           wInitStatus = NFCSTATUS_FAILED;
139         } else if (0 != sem_init(&gpphTmlNfc_Context->postMsgSemaphore, 0, 0)) {
140           wInitStatus = NFCSTATUS_FAILED;
141         } else {
142           sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
143           /* Start TML thread (to handle write and read operations) */
144           if (NFCSTATUS_SUCCESS != phTmlNfc_StartThread()) {
145             wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
146           } else {
147             /* Create Timer used for Retransmission of NCI packets */
148             gpphTmlNfc_Context->dwTimerId = phOsalNfc_Timer_Create();
149             if (PH_OSALNFC_TIMER_ID_INVALID != gpphTmlNfc_Context->dwTimerId) {
150               /* Store the Thread Identifier to which Message is to be posted */
151               gpphTmlNfc_Context->dwCallbackThreadId =
152                   pConfig->dwGetMsgThreadId;
153               /* Enable retransmission of Nci packet & set retry count to
154                * default */
155               gpphTmlNfc_Context->eConfig = phTmlNfc_e_DisableRetrans;
156               /* Retry Count = Standby Recovery time of NFCC / Retransmission
157                * time + 1 */
158               gpphTmlNfc_Context->bRetryCount =
159                   (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
160               gpphTmlNfc_Context->bWriteCbInvoked = false;
161             } else {
162               wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
163             }
164           }
165         }
166       }
167     }
168   }
169   /* Clean up all the TML resources if any error */
170   if (NFCSTATUS_SUCCESS != wInitStatus) {
171     /* Clear all handles and memory locations initialized during init */
172     phTmlNfc_Shutdown_CleanUp();
173   }
174 
175   return wInitStatus;
176 }
177 
178 /*******************************************************************************
179 **
180 ** Function         phTmlNfc_ConfigTransport
181 **
182 ** Description      Configure Transport channel based on transport type provided
183 **                  in config file
184 **
185 ** Returns          NFCSTATUS_SUCCESS If transport channel is configured
186 **                  NFCSTATUS_FAILED If transport channel configuration failed
187 **
188 *******************************************************************************/
phTmlNfc_ConfigTransport()189 NFCSTATUS phTmlNfc_ConfigTransport() {
190   unsigned long transportType = UNKNOWN;
191   unsigned long value = 0;
192   int isfound = GetNxpNumValue(NAME_NXP_TRANSPORT, &value, sizeof(value));
193   if (isfound > 0) {
194     transportType = value;
195   }
196   gpTransportObj = transportFactory.getTransport((transportIntf)transportType);
197   if (gpTransportObj == nullptr) {
198     NXPLOG_TML_E("No Transport channel available \n");
199     return NFCSTATUS_FAILED;
200   }
201   return NFCSTATUS_SUCCESS;
202 }
203 /*******************************************************************************
204 **
205 ** Function         phTmlNfc_ConfigNciPktReTx
206 **
207 ** Description      Provides Enable/Disable Retransmission of NCI packets
208 **                  Needed in case of Timeout between Transmission and Reception
209 **                  of NCI packets. Retransmission can be enabled only if
210 **                  standby mode is enabled
211 **
212 ** Parameters       eConfig - values from phTmlNfc_ConfigRetrans_t
213 **                  bRetryCount - Number of times Nci packets shall be
214 **                                retransmitted (default = 3)
215 **
216 ** Returns          None
217 **
218 *******************************************************************************/
phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration,uint8_t bRetryCounter)219 void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration,
220                                uint8_t bRetryCounter) {
221   /* Enable/Disable Retransmission */
222 
223   gpphTmlNfc_Context->eConfig = eConfiguration;
224   if (phTmlNfc_e_EnableRetrans == eConfiguration) {
225     /* Check whether Retry counter passed is valid */
226     if (0 != bRetryCounter) {
227       gpphTmlNfc_Context->bRetryCount = bRetryCounter;
228     }
229     /* Set retry counter to its default value */
230     else {
231       /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1
232        */
233       gpphTmlNfc_Context->bRetryCount =
234           (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
235     }
236   }
237 
238   return;
239 }
240 
241 /*******************************************************************************
242 **
243 ** Function         phTmlNfc_StartThread
244 **
245 ** Description      Initializes comport, reader and writer threads
246 **
247 ** Parameters       None
248 **
249 ** Returns          NFC status:
250 **                  NFCSTATUS_SUCCESS - threads initialized successfully
251 **                  NFCSTATUS_FAILED - initialization failed due to system error
252 **
253 *******************************************************************************/
phTmlNfc_StartThread(void)254 static NFCSTATUS phTmlNfc_StartThread(void) {
255   NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS;
256   void* h_threadsEvent = 0x00;
257   int pthread_create_status = 0;
258 
259   /* Create Reader and Writer threads */
260   pthread_create_status =
261       pthread_create(&gpphTmlNfc_Context->readerThread, NULL,
262                      &phTmlNfc_TmlThread, (void*)h_threadsEvent);
263   if (0 != pthread_create_status) {
264     wStartStatus = NFCSTATUS_FAILED;
265   } else {
266     /*Start Writer Thread*/
267     pthread_create_status =
268         pthread_create(&gpphTmlNfc_Context->writerThread, NULL,
269                        &phTmlNfc_TmlWriterThread, (void*)h_threadsEvent);
270     if (0 != pthread_create_status) {
271       wStartStatus = NFCSTATUS_FAILED;
272     }
273   }
274 
275   return wStartStatus;
276 }
277 
278 /*******************************************************************************
279 **
280 ** Function         phTmlNfc_ReTxTimerCb
281 **
282 ** Description      This is the timer callback function after timer expiration.
283 **
284 ** Parameters       dwThreadId  - id of the thread posting message
285 **                  pContext    - context provided by upper layer
286 **
287 ** Returns          None
288 **
289 *******************************************************************************/
phTmlNfc_ReTxTimerCb(uint32_t dwTimerId,void * pContext)290 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext) {
291   if ((gpphTmlNfc_Context->dwTimerId == dwTimerId) && (NULL == pContext)) {
292     /* If Retry Count has reached its limit,Retransmit Nci
293        packet */
294     if (0 == bCurrentRetryCount) {
295       /* Since the count has reached its limit,return from timer callback
296          Upper layer Timeout would have happened */
297     } else {
298       bCurrentRetryCount--;
299       gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
300       gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
301     }
302     sem_post(&gpphTmlNfc_Context->txSemaphore);
303   }
304 
305   return;
306 }
307 
308 /*******************************************************************************
309 **
310 ** Function         phTmlNfc_InitiateTimer
311 **
312 ** Description      Start a timer for Tx and Rx thread.
313 **
314 ** Parameters       void
315 **
316 ** Returns          NFC status
317 **
318 *******************************************************************************/
phTmlNfc_InitiateTimer(void)319 static NFCSTATUS phTmlNfc_InitiateTimer(void) {
320   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
321 
322   /* Start Timer once Nci packet is sent */
323   wStatus = phOsalNfc_Timer_Start(gpphTmlNfc_Context->dwTimerId,
324                                   (uint32_t)PHTMLNFC_MAXTIME_RETRANSMIT,
325                                   phTmlNfc_ReTxTimerCb, NULL);
326 
327   return wStatus;
328 }
329 
330 /*******************************************************************************
331 **
332 ** Function         phTmlNfc_TmlThread
333 **
334 ** Description      Read the data from the lower layer driver
335 **
336 ** Parameters       pParam  - parameters for Writer thread function
337 **
338 ** Returns          None
339 **
340 *******************************************************************************/
phTmlNfc_TmlThread(void * pParam)341 static void* phTmlNfc_TmlThread(void* pParam) {
342   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
343   int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
344   uint8_t temp[260];
345   uint8_t readRetryDelay = 0;
346   /* Transaction info buffer to be passed to Callback Thread */
347   static phTmlNfc_TransactInfo_t tTransactionInfo;
348   /* Structure containing Tml callback function and parameters to be invoked
349      by the callback thread */
350   static phLibNfc_DeferredCall_t tDeferredInfo;
351   /* Initialize Message structure to post message onto Callback Thread */
352   static phLibNfc_Message_t tMsg;
353   UNUSED_PROP(pParam);
354   NXPLOG_TML_D("PN54X - Tml Reader Thread Started................\n");
355 
356   /* Reader thread loop shall be running till shutdown is invoked */
357   while (gpphTmlNfc_Context->bThreadDone) {
358     /* If Tml read is requested */
359     /* Set the variable to success initially */
360     wStatus = NFCSTATUS_SUCCESS;
361     if (-1 == sem_wait(&gpphTmlNfc_Context->rxSemaphore)) {
362       NXPLOG_TML_E("sem_wait didn't return success \n");
363     }
364 
365     /* If Tml read is requested */
366     if (1 == gpphTmlNfc_Context->tReadInfo.bEnable) {
367       NXPLOG_TML_D("PN54X - Read requested.....\n");
368       /* Set the variable to success initially */
369       wStatus = NFCSTATUS_SUCCESS;
370 
371       /* Variable to fetch the actual number of bytes read */
372       dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
373 
374       /* Read the data from the file onto the buffer */
375       if (NULL != gpphTmlNfc_Context->pDevHandle) {
376         NXPLOG_TML_D("PN54X - Invoking I2C Read.....\n");
377         dwNoBytesWrRd =
378             gpTransportObj->Read(gpphTmlNfc_Context->pDevHandle, temp, 260);
379 
380         if (-1 == dwNoBytesWrRd) {
381           NXPLOG_TML_E("PN54X - Error in I2C Read.....\n");
382           if (readRetryDelay < MAX_READ_RETRY_DELAY_IN_MILLISEC) {
383             /*sleep for 30/60/90/120/150 msec between each read trial incase of
384              * read error*/
385             readRetryDelay += 30;
386           }
387           usleep(readRetryDelay * 1000);
388           sem_post(&gpphTmlNfc_Context->rxSemaphore);
389         } else if (dwNoBytesWrRd > 260) {
390           NXPLOG_TML_E("Numer of bytes read exceeds the limit 260.....\n");
391           readRetryDelay = 0;
392           sem_post(&gpphTmlNfc_Context->rxSemaphore);
393         } else {
394           memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
395           readRetryDelay = 0;
396 
397           NXPLOG_TML_D("PN54X - I2C Read successful.....\n");
398           /* This has to be reset only after a successful read */
399           gpphTmlNfc_Context->tReadInfo.bEnable = 0;
400           if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
401               (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) {
402             NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n");
403             /* Stop Timer to prevent Retransmission */
404             uint32_t timerStatus =
405                 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId);
406             if (NFCSTATUS_SUCCESS != timerStatus) {
407               NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n");
408             } else {
409               gpphTmlNfc_Context->bWriteCbInvoked = false;
410             }
411           }
412           /* Update the actual number of bytes read including header */
413           gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
414           phNxpNciHal_print_packet("RECV",
415                                    gpphTmlNfc_Context->tReadInfo.pBuffer,
416                                    gpphTmlNfc_Context->tReadInfo.wLength);
417 
418           dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
419 
420           /* Fill the Transaction info structure to be passed to Callback
421            * Function */
422           tTransactionInfo.wStatus = wStatus;
423           tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer;
424           /* Actual number of bytes read is filled in the structure */
425           tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength;
426 
427           /* Read operation completed successfully. Post a Message onto Callback
428            * Thread*/
429           /* Prepare the message to be posted on User thread */
430           tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb;
431           tDeferredInfo.pParameter = &tTransactionInfo;
432           tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
433           tMsg.pMsgData = &tDeferredInfo;
434           tMsg.Size = sizeof(tDeferredInfo);
435           NXPLOG_TML_D("PN54X - Posting read message.....\n");
436           phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
437         }
438       } else {
439         NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL");
440       }
441     } else {
442       NXPLOG_TML_D("PN54X - read request NOT enabled");
443       usleep(10 * 1000);
444     }
445   } /* End of While loop */
446 
447   return NULL;
448 }
449 
450 /*******************************************************************************
451 **
452 ** Function         phTmlNfc_TmlWriterThread
453 **
454 ** Description      Writes the requested data onto the lower layer driver
455 **
456 ** Parameters       pParam  - context provided by upper layer
457 **
458 ** Returns          None
459 **
460 *******************************************************************************/
phTmlNfc_TmlWriterThread(void * pParam)461 static void* phTmlNfc_TmlWriterThread(void* pParam) {
462   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
463   int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
464   /* Transaction info buffer to be passed to Callback Thread */
465   static phTmlNfc_TransactInfo_t tTransactionInfo;
466   /* Structure containing Tml callback function and parameters to be invoked
467      by the callback thread */
468   static phLibNfc_DeferredCall_t tDeferredInfo;
469   /* Initialize Message structure to post message onto Callback Thread */
470   static phLibNfc_Message_t tMsg;
471   /* In case of I2C Write Retry */
472   static uint16_t retry_cnt;
473   UNUSED_PROP(pParam);
474   NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n");
475 
476   /* Writer thread loop shall be running till shutdown is invoked */
477   while (gpphTmlNfc_Context->bThreadDone) {
478     NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n");
479     if (-1 == sem_wait(&gpphTmlNfc_Context->txSemaphore)) {
480       NXPLOG_TML_E("sem_wait didn't return success \n");
481     }
482     /* If Tml write is requested */
483     if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) {
484       NXPLOG_TML_D("PN54X - Write requested.....\n");
485       /* Set the variable to success initially */
486       wStatus = NFCSTATUS_SUCCESS;
487       if (NULL != gpphTmlNfc_Context->pDevHandle) {
488       retry:
489         gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
490         /* Variable to fetch the actual number of bytes written */
491         dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
492         /* Write the data in the buffer onto the file */
493         NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n");
494         /* TML reader writer callback synchronization mutex lock --- START */
495         pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
496         gpphTmlNfc_Context->gWriterCbflag = false;
497         dwNoBytesWrRd =
498             gpTransportObj->Write(gpphTmlNfc_Context->pDevHandle,
499                                   gpphTmlNfc_Context->tWriteInfo.pBuffer,
500                                   gpphTmlNfc_Context->tWriteInfo.wLength);
501         /* TML reader writer callback synchronization mutex lock --- END */
502         pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
503 
504         /* Try I2C Write Five Times, if it fails : Raju */
505         if (-1 == dwNoBytesWrRd) {
506           if (gpTransportObj->IsFwDnldModeEnabled()) {
507             if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) {
508               NXPLOG_TML_D("PN54X - Error in I2C Write  - Retry 0x%x",
509                            retry_cnt);
510               // Add a 10 ms delay to ensure NFCC is not still in stand by mode.
511               usleep(10 * 1000);
512               goto retry;
513             }
514           }
515           NXPLOG_TML_D("PN54X - Error in I2C Write.....\n");
516           wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
517         } else {
518           phNxpNciHal_print_packet("SEND",
519                                    gpphTmlNfc_Context->tWriteInfo.pBuffer,
520                                    gpphTmlNfc_Context->tWriteInfo.wLength);
521         }
522         retry_cnt = 0;
523         if (NFCSTATUS_SUCCESS == wStatus) {
524           NXPLOG_TML_D("PN54X - I2C Write successful.....\n");
525           dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
526         }
527         /* Fill the Transaction info structure to be passed to Callback Function
528          */
529         tTransactionInfo.wStatus = wStatus;
530         tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
531         /* Actual number of bytes written is filled in the structure */
532         tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
533 
534         /* Prepare the message to be posted on the User thread */
535         tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
536         tDeferredInfo.pParameter = &tTransactionInfo;
537         /* Write operation completed successfully. Post a Message onto Callback
538          * Thread*/
539         tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
540         tMsg.pMsgData = &tDeferredInfo;
541         tMsg.Size = sizeof(tDeferredInfo);
542 
543         /* Check whether Retransmission needs to be started,
544          * If yes, Post message only if
545          * case 1. Message is not posted &&
546          * case 11. Write status is success ||
547          * case 12. Last retry of write is also failure
548          */
549         if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
550             (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
551           if (gpphTmlNfc_Context->bWriteCbInvoked == false) {
552             if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) {
553               NXPLOG_TML_D("PN54X - Posting Write message.....\n");
554               phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
555                                     &tMsg);
556               gpphTmlNfc_Context->bWriteCbInvoked = true;
557             }
558           }
559         } else {
560           NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n");
561           phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
562           if (NFCSTATUS_SUCCESS == wStatus) {
563             /*TML reader writer thread callback synchronization---START*/
564             pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
565             gpphTmlNfc_Context->gWriterCbflag = true;
566             phTmlNfc_SignalWriteComplete();
567             /*TML reader writer thread callback synchronization---END*/
568             pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
569           }
570         }
571       } else {
572         NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL");
573       }
574 
575       /* If Data packet is sent, then NO retransmission */
576       if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
577           (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
578         NXPLOG_TML_D("PN54X - Starting timer for Retransmission case");
579         wStatus = phTmlNfc_InitiateTimer();
580         if (NFCSTATUS_SUCCESS != wStatus) {
581           /* Reset Variables used for Retransmission */
582           NXPLOG_TML_D("PN54X - Retransmission timer initiate failed");
583           gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
584           bCurrentRetryCount = 0;
585         }
586       }
587     } else {
588       NXPLOG_TML_D("PN54X - Write request NOT enabled");
589       usleep(10000);
590     }
591 
592   } /* End of While loop */
593 
594   return NULL;
595 }
596 
597 /*******************************************************************************
598 **
599 ** Function         phTmlNfc_CleanUp
600 **
601 ** Description      Clears all handles opened during TML initialization
602 **
603 ** Parameters       None
604 **
605 ** Returns          None
606 **
607 *******************************************************************************/
phTmlNfc_CleanUp(void)608 void phTmlNfc_CleanUp(void) {
609   if (NULL == gpphTmlNfc_Context) {
610     return;
611   }
612   sem_destroy(&gpphTmlNfc_Context->rxSemaphore);
613   sem_destroy(&gpphTmlNfc_Context->txSemaphore);
614   sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore);
615   pthread_mutex_destroy(&gpphTmlNfc_Context->wait_busy_lock);
616   pthread_cond_destroy(&gpphTmlNfc_Context->wait_busy_condition);
617   gpTransportObj = NULL;
618   /* Clear memory allocated for storing Context variables */
619   free((void*)gpphTmlNfc_Context);
620   /* Set the pointer to NULL to indicate De-Initialization */
621   gpphTmlNfc_Context = NULL;
622 
623   return;
624 }
625 
626 /*******************************************************************************
627 **
628 ** Function         phTmlNfc_Shutdown
629 **
630 ** Description      Uninitializes TML layer and hardware interface
631 **
632 ** Parameters       None
633 **
634 ** Returns          NFC status:
635 **                  NFCSTATUS_SUCCESS - TML configuration released successfully
636 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
637 **                                                invalid
638 **                  NFCSTATUS_FAILED - un-initialization failed (example: unable
639 **                                     to close interface)
640 **
641 *******************************************************************************/
phTmlNfc_Shutdown(void)642 NFCSTATUS phTmlNfc_Shutdown(void) {
643   NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS;
644 
645   /* Check whether TML is Initialized */
646   if (NULL != gpphTmlNfc_Context) {
647     /* Reset thread variable to terminate the thread */
648     gpphTmlNfc_Context->bThreadDone = 0;
649     usleep(1000);
650     /* Clear All the resources allocated during initialization */
651     sem_post(&gpphTmlNfc_Context->rxSemaphore);
652     usleep(1000);
653     sem_post(&gpphTmlNfc_Context->txSemaphore);
654     usleep(1000);
655     sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
656     usleep(1000);
657     sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
658     usleep(1000);
659 
660     if (nfcFL.chipType < sn100u) {
661       (void)gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
662                                       MODE_POWER_OFF);
663     }
664 
665     gpTransportObj->Close(gpphTmlNfc_Context->pDevHandle);
666     gpphTmlNfc_Context->pDevHandle = NULL;
667     if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) {
668       NXPLOG_TML_E("Fail to kill reader thread!");
669     }
670     if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) {
671       NXPLOG_TML_E("Fail to kill writer thread!");
672     }
673     NXPLOG_TML_D("bThreadDone == 0");
674 
675   } else {
676     wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
677   }
678 
679   return wShutdownStatus;
680 }
681 
682 /*******************************************************************************
683 **
684 ** Function         phTmlNfc_Write
685 **
686 ** Description      Asynchronously writes given data block to hardware
687 **                  interface/driver. Enables writer thread if there are no
688 **                  write requests pending. Returns successfully once writer
689 **                  thread completes write operation. Notifies upper layer using
690 **                  callback mechanism.
691 **
692 **                  NOTE:
693 **                  * it is important to post a message with id
694 **                    PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data
695 **                    has been written to PN54X
696 **                  * if CRC needs to be computed, then input buffer should be
697 **                    capable to store two more bytes apart from length of
698 **                    packet
699 **
700 ** Parameters       pBuffer - data to be sent
701 **                  wLength - length of data buffer
702 **                  pTmlWriteComplete - pointer to the function to be invoked
703 **                                      upon completion
704 **                  pContext - context provided by upper layer
705 **
706 ** Returns          NFC status:
707 **                  NFCSTATUS_PENDING - command is yet to be processed
708 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
709 **                                                invalid
710 **                  NFCSTATUS_BUSY - write request is already in progress
711 **
712 *******************************************************************************/
phTmlNfc_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,void * pContext)713 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength,
714                          pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,
715                          void* pContext) {
716   NFCSTATUS wWriteStatus;
717 
718   /* Check whether TML is Initialized */
719 
720   if (NULL != gpphTmlNfc_Context) {
721     if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) &&
722         (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
723       if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
724         /* Setting the flag marks beginning of a Write Operation */
725         gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
726         /* Copy the buffer, length and Callback function,
727            This shall be utilized while invoking the Callback function in thread
728            */
729         gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer;
730         gpphTmlNfc_Context->tWriteInfo.wLength = wLength;
731         gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
732         gpphTmlNfc_Context->tWriteInfo.pContext = pContext;
733 
734         wWriteStatus = NFCSTATUS_PENDING;
735         // FIXME: If retry is going on. Stop the retry thread/timer
736         if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) {
737           /* Set retry count to default value */
738           // FIXME: If the timer expired there, and meanwhile we have created
739           // a new request. The expired timer will think that retry is still
740           // ongoing.
741           bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount;
742           gpphTmlNfc_Context->bWriteCbInvoked = false;
743         }
744         /* Set event to invoke Writer Thread */
745         gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
746         sem_post(&gpphTmlNfc_Context->txSemaphore);
747       } else {
748         wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
749       }
750     } else {
751       wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
752     }
753   } else {
754     wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
755   }
756 
757   return wWriteStatus;
758 }
759 
760 /*******************************************************************************
761 **
762 ** Function         phTmlNfc_Read
763 **
764 ** Description      Asynchronously reads data from the driver
765 **                  Number of bytes to be read and buffer are passed by upper
766 **                  layer.
767 **                  Enables reader thread if there are no read requests pending
768 **                  Returns successfully once read operation is completed
769 **                  Notifies upper layer using callback mechanism
770 **
771 ** Parameters       pBuffer - location to send read data to the upper layer via
772 **                            callback
773 **                  wLength - length of read data buffer passed by upper layer
774 **                  pTmlReadComplete - pointer to the function to be invoked
775 **                                     upon completion of read operation
776 **                  pContext - context provided by upper layer
777 **
778 ** Returns          NFC status:
779 **                  NFCSTATUS_PENDING - command is yet to be processed
780 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
781 **                                                invalid
782 **                  NFCSTATUS_BUSY - read request is already in progress
783 **
784 *******************************************************************************/
phTmlNfc_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,void * pContext)785 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength,
786                         pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,
787                         void* pContext) {
788   NFCSTATUS wReadStatus;
789   int rxSemVal = 0, ret = 0;
790 
791   /* Check whether TML is Initialized */
792   if (NULL != gpphTmlNfc_Context) {
793     if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
794         (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) {
795       if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) {
796         /* Setting the flag marks beginning of a Read Operation */
797         gpphTmlNfc_Context->tReadInfo.bThreadBusy = true;
798         /* Copy the buffer, length and Callback function,
799            This shall be utilized while invoking the Callback function in thread
800            */
801         gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer;
802         gpphTmlNfc_Context->tReadInfo.wLength = wLength;
803         gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
804         gpphTmlNfc_Context->tReadInfo.pContext = pContext;
805         wReadStatus = NFCSTATUS_PENDING;
806 
807         /* Set event to invoke Reader Thread */
808         gpphTmlNfc_Context->tReadInfo.bEnable = 1;
809         ret = sem_getvalue(&gpphTmlNfc_Context->rxSemaphore, &rxSemVal);
810         /* Post rxSemaphore either if sem_getvalue() is failed or rxSemVal is 0
811          */
812         if (ret || !rxSemVal) {
813           sem_post(&gpphTmlNfc_Context->rxSemaphore);
814         } else {
815           NXPLOG_TML_D(
816               "%s: skip reader thread scheduling, ret=%x, rxSemaVal=%x",
817               __func__, ret, rxSemVal);
818         }
819       } else {
820         wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
821       }
822     } else {
823       wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
824     }
825   } else {
826     wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
827   }
828 
829   return wReadStatus;
830 }
831 
832 /*******************************************************************************
833 **
834 ** Function         phTmlNfc_ReadAbort
835 **
836 ** Description      Aborts pending read request (if any)
837 **
838 ** Parameters       None
839 **
840 ** Returns          NFC status:
841 **                  NFCSTATUS_SUCCESS - ongoing read operation aborted
842 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
843 **                                                invalid
844 **                  NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
845 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read
846 **                                                        operation
847 **
848 *******************************************************************************/
phTmlNfc_ReadAbort(void)849 NFCSTATUS phTmlNfc_ReadAbort(void) {
850   NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
851   gpphTmlNfc_Context->tReadInfo.bEnable = 0;
852 
853   /*Reset the flag to accept another Read Request */
854   gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
855   wStatus = NFCSTATUS_SUCCESS;
856 
857   return wStatus;
858 }
859 
860 /*******************************************************************************
861 **
862 ** Function         phTmlNfc_WriteAbort
863 **
864 ** Description      Aborts pending write request (if any)
865 **
866 ** Parameters       None
867 **
868 ** Returns          NFC status:
869 **                  NFCSTATUS_SUCCESS - ongoing write operation aborted
870 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
871 **                                                invalid
872 **                  NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
873 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write
874 **                                                        operation
875 **
876 *******************************************************************************/
phTmlNfc_WriteAbort(void)877 NFCSTATUS phTmlNfc_WriteAbort(void) {
878   NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
879 
880   gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
881   /* Stop if any retransmission is in progress */
882   bCurrentRetryCount = 0;
883 
884   /* Reset the flag to accept another Write Request */
885   gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
886   wStatus = NFCSTATUS_SUCCESS;
887 
888   return wStatus;
889 }
890 
891 /*******************************************************************************
892 **
893 ** Function         phTmlNfc_IoCtl
894 **
895 ** Description      Resets device when insisted by upper layer
896 **                  Number of bytes to be read and buffer are passed by upper
897 **                  layer
898 **                  Enables reader thread if there are no read requests pending
899 **                  Returns successfully once read operation is completed
900 **                  Notifies upper layer using callback mechanism
901 **
902 ** Parameters       eControlCode       - control code for a specific operation
903 **
904 ** Returns          NFC status:
905 **                  NFCSTATUS_SUCCESS  - ioctl command completed successfully
906 **                  NFCSTATUS_FAILED   - ioctl command request failed
907 **
908 *******************************************************************************/
phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)909 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) {
910   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
911 
912   if (NULL == gpphTmlNfc_Context) {
913     wStatus = NFCSTATUS_FAILED;
914   } else {
915     uint8_t read_flag = (gpphTmlNfc_Context->tReadInfo.bEnable > 0);
916 
917     switch (eControlCode) {
918       case phTmlNfc_e_PowerReset: {
919         if (nfcFL.chipType >= sn100u) {
920           /*VEN_RESET*/
921           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
922                                     MODE_POWER_RESET);
923         } else {
924           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
925                                     MODE_POWER_ON);
926           usleep(100 * 1000);
927           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
928                                     MODE_POWER_OFF);
929           usleep(100 * 1000);
930           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
931                                     MODE_POWER_ON);
932         }
933         break;
934       }
935       case phTmlNfc_e_EnableVen: {
936         if (nfcFL.chipType < sn100u) {
937           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
938                                     MODE_POWER_ON);
939           usleep(100 * 1000);
940         }
941         break;
942       }
943       case phTmlNfc_e_ResetDevice:
944 
945       {
946 #if (NXP_EXTNS == TRUE)
947         if (nfcFL.chipType < sn100u) {
948 #endif
949           /*Reset PN54X*/
950           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
951                                     MODE_POWER_ON);
952           usleep(100 * 1000);
953           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
954                                     MODE_POWER_OFF);
955           usleep(100 * 1000);
956           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
957                                     MODE_POWER_ON);
958 #if (NXP_EXTNS == TRUE)
959         }
960 #endif
961         break;
962       }
963       case phTmlNfc_e_EnableNormalMode: {
964         /*Reset PN54X*/
965         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
966         if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
967           NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with VEN RESET ");
968           if (nfcFL.chipType < sn100u) {
969             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
970                                       MODE_POWER_OFF);
971             usleep(10 * 1000);
972             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
973                                       MODE_POWER_ON);
974             usleep(100 * 1000);
975           } else {
976             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
977                                       MODE_FW_GPIO_LOW);
978           }
979         } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
980           NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with NCI CMD ");
981           if (nfcFL.chipType < sn100u) {
982             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
983                                       MODE_POWER_ON);
984           } else {
985             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
986                                       MODE_FW_GPIO_LOW);
987           }
988         }
989         break;
990       }
991       case phTmlNfc_e_EnableDownloadMode: {
992         phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
993         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
994         if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
995           NXPLOG_TML_D(
996               " phTmlNfc_e_EnableDownloadMode complete with VEN RESET ");
997           wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
998                                               MODE_FW_DWNLD_WITH_VEN);
999         } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
1000           NXPLOG_TML_D(" phTmlNfc_e_EnableDownloadMode complete with NCI CMD ");
1001           wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
1002                                               MODE_FW_DWND_HIGH);
1003         }
1004         break;
1005       }
1006       case phTmlNfc_e_EnableDownloadModeWithVenRst: {
1007         phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
1008         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
1009         NXPLOG_TML_D(
1010             " phTmlNfc_e_EnableDownloadModewithVenRst complete with "
1011             "VEN RESET ");
1012         wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
1013                                             MODE_FW_DWNLD_WITH_VEN);
1014         break;
1015       }
1016       case phTmlNfc_e_setFragmentSize: {
1017         if (nfcFL.chipType != pn557) {
1018           gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_SNXXX;
1019           NXPLOG_TML_D("phTmlNfc_e_setFragmentSize 0x22A");
1020         } else {
1021           gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_PN557;
1022           NXPLOG_TML_D("phTmlNfc_e_setFragmentSize 0x100");
1023         }
1024         break;
1025       }
1026       default: {
1027         wStatus = NFCSTATUS_INVALID_PARAMETER;
1028         break;
1029       }
1030     }
1031     if (read_flag && (gpphTmlNfc_Context->tReadInfo.bEnable == 0x00)) {
1032       gpphTmlNfc_Context->tReadInfo.bEnable = 1;
1033       sem_post(&gpphTmlNfc_Context->rxSemaphore);
1034     }
1035   }
1036 
1037   return wStatus;
1038 }
1039 
1040 /*******************************************************************************
1041 **
1042 ** Function         phTmlNfc_DeferredCall
1043 **
1044 ** Description      Posts message on upper layer thread
1045 **                  upon successful read or write operation
1046 **
1047 ** Parameters       dwThreadId  - id of the thread posting message
1048 **                  ptWorkerMsg - message to be posted
1049 **
1050 ** Returns          None
1051 **
1052 *******************************************************************************/
phTmlNfc_DeferredCall(uintptr_t dwThreadId,phLibNfc_Message_t * ptWorkerMsg)1053 void phTmlNfc_DeferredCall(uintptr_t dwThreadId,
1054                            phLibNfc_Message_t* ptWorkerMsg) {
1055   intptr_t bPostStatus;
1056   UNUSED_PROP(dwThreadId);
1057   /* Post message on the user thread to invoke the callback function */
1058   if (-1 == sem_wait(&gpphTmlNfc_Context->postMsgSemaphore)) {
1059     NXPLOG_TML_E("sem_wait didn't return success \n");
1060   }
1061   bPostStatus =
1062       phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0);
1063   sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
1064 }
1065 
1066 /*******************************************************************************
1067 **
1068 ** Function         phTmlNfc_ReadDeferredCb
1069 **
1070 ** Description      Read thread call back function
1071 **
1072 ** Parameters       pParams - context provided by upper layer
1073 **
1074 ** Returns          None
1075 **
1076 *******************************************************************************/
phTmlNfc_ReadDeferredCb(void * pParams)1077 static void phTmlNfc_ReadDeferredCb(void* pParams) {
1078   /* Transaction info buffer to be passed to Callback Function */
1079   phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1080 
1081   /* Reset the flag to accept another Read Request */
1082   gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
1083   gpphTmlNfc_Context->tReadInfo.pThread_Callback(
1084       gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo);
1085 
1086   return;
1087 }
1088 
1089 /*******************************************************************************
1090 **
1091 ** Function         phTmlNfc_WriteDeferredCb
1092 **
1093 ** Description      Write thread call back function
1094 **
1095 ** Parameters       pParams - context provided by upper layer
1096 **
1097 ** Returns          None
1098 **
1099 *******************************************************************************/
phTmlNfc_WriteDeferredCb(void * pParams)1100 static void phTmlNfc_WriteDeferredCb(void* pParams) {
1101   /* Transaction info buffer to be passed to Callback Function */
1102   phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1103 
1104   /* Reset the flag to accept another Write Request */
1105   gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
1106   gpphTmlNfc_Context->tWriteInfo.pThread_Callback(
1107       gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo);
1108 
1109   return;
1110 }
1111 
phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)1112 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) {
1113   fragmentation_enabled = result;
1114 }
1115 
phTmlNfc_get_fragmentation_enabled()1116 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() {
1117   return fragmentation_enabled;
1118 }
1119 
1120 /*******************************************************************************
1121 **
1122 ** Function         phTmlNfc_SignalWriteComplete
1123 **
1124 ** Description      function to invoke reader thread
1125 **
1126 ** Parameters       None
1127 **
1128 ** Returns          None
1129 **
1130 *******************************************************************************/
phTmlNfc_SignalWriteComplete(void)1131 static void phTmlNfc_SignalWriteComplete(void) {
1132   int ret = -1;
1133   if (gpphTmlNfc_Context->wait_busy_flag == true) {
1134     NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - enter");
1135     gpphTmlNfc_Context->wait_busy_flag = false;
1136 
1137     ret = pthread_cond_signal(&gpphTmlNfc_Context->wait_busy_condition);
1138     if (ret) {
1139       NXPLOG_TML_E(" phTmlNfc_SignalWriteComplete failed, error = 0x%X", ret);
1140     }
1141     NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - exit");
1142   }
1143 }
1144 
1145 /*******************************************************************************
1146 **
1147 ** Function         phTmlNfc_WaitReadInit
1148 **
1149 ** Description      init function for reader thread
1150 **
1151 ** Parameters       None
1152 **
1153 ** Returns          int
1154 **
1155 *******************************************************************************/
phTmlNfc_WaitReadInit(void)1156 static int phTmlNfc_WaitReadInit(void) {
1157   int ret = -1;
1158   pthread_condattr_t attr;
1159   pthread_condattr_init(&attr);
1160   pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
1161   memset(&gpphTmlNfc_Context->wait_busy_condition, 0,
1162          sizeof(gpphTmlNfc_Context->wait_busy_condition));
1163   pthread_mutex_init(&gpphTmlNfc_Context->wait_busy_lock, NULL);
1164   ret = pthread_cond_init(&gpphTmlNfc_Context->wait_busy_condition, &attr);
1165   if (ret) {
1166     NXPLOG_TML_E(" phTphTmlNfc_WaitReadInit failed, error = 0x%X", ret);
1167   }
1168   return ret;
1169 }
1170 
1171 /*******************************************************************************
1172 **
1173 ** Function         phTmlNfc_EnableFwDnldMode
1174 **
1175 ** Description      wrapper function for enabling/disabling FW download mode
1176 **
1177 ** Parameters       True/False
1178 **
1179 ** Returns          NFCSTATUS
1180 **
1181 *******************************************************************************/
phTmlNfc_EnableFwDnldMode(bool mode)1182 void phTmlNfc_EnableFwDnldMode(bool mode) {
1183   gpTransportObj->EnableFwDnldMode(mode);
1184 }
1185 
1186 /*******************************************************************************
1187 **
1188 ** Function         phTmlNfc_IsFwDnldModeEnabled
1189 **
1190 ** Description      wrapper function  to get the FW download flag
1191 **
1192 ** Parameters       None
1193 **
1194 ** Returns          True/False status of FW download flag
1195 **
1196 *******************************************************************************/
phTmlNfc_IsFwDnldModeEnabled(void)1197 bool phTmlNfc_IsFwDnldModeEnabled(void) {
1198   return gpTransportObj->IsFwDnldModeEnabled();
1199 }
1200 
1201 /*******************************************************************************
1202 **
1203 ** Function         phTmlNfc_Shutdown_CleanUp
1204 **
1205 ** Description      wrapper function  for shutdown  and cleanup of resources
1206 **
1207 ** Parameters       None
1208 **
1209 ** Returns          NFCSTATUS
1210 **
1211 *******************************************************************************/
phTmlNfc_Shutdown_CleanUp()1212 NFCSTATUS phTmlNfc_Shutdown_CleanUp() {
1213   NFCSTATUS wShutdownStatus = phTmlNfc_Shutdown();
1214   phTmlNfc_CleanUp();
1215   return wShutdownStatus;
1216 }
1217