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