1 /*
2  * Copyright 2010-2024 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_SignalWriteComplete(void);
56 static int phTmlNfc_WaitReadInit(void);
57 
58 /* Function definitions */
59 
60 /*******************************************************************************
61 **
62 ** Function         phTmlNfc_Init
63 **
64 ** Description      Provides initialization of TML layer and hardware interface
65 **                  Configures given hardware interface and sends handle to the
66 **                  caller
67 **
68 ** Parameters       pConfig - TML configuration details as provided by the upper
69 **                            layer
70 **
71 ** Returns          NFC status:
72 **                  NFCSTATUS_SUCCESS - initialization successful
73 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
74 **                                                invalid
75 **                  NFCSTATUS_FAILED - initialization failed (for example,
76 **                                     unable to open hardware interface)
77 **                  NFCSTATUS_INVALID_DEVICE - device has not been opened or has
78 **                                             been disconnected
79 **
80 *******************************************************************************/
phTmlNfc_Init(pphTmlNfc_Config_t pConfig)81 NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) {
82   NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS;
83 
84   /* Check if TML layer is already Initialized */
85   if (NULL != gpphTmlNfc_Context) {
86     /* TML initialization is already completed */
87     wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED);
88   }
89   /* Validate Input parameters */
90   else if ((NULL == pConfig) ||
91            (PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) {
92     /*Parameters passed to TML init are wrong */
93     wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
94   } else {
95     /* Allocate memory for TML context */
96     gpphTmlNfc_Context =
97         (phTmlNfc_Context_t*)malloc(sizeof(phTmlNfc_Context_t));
98 
99     if (NULL == gpphTmlNfc_Context) {
100       wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
101     } else {
102       /*Configure transport layer for communication*/
103       if ((gpTransportObj == NULL) &&
104           (NFCSTATUS_SUCCESS != phTmlNfc_ConfigTransport()))
105         return NFCSTATUS_FAILED;
106 
107       if (gsIsFirstHalMinOpen) {
108         if (!gpTransportObj->Flushdata(pConfig)) {
109           NXPLOG_NCIHAL_E("Flushdata Failed");
110         }
111       }
112       /* Initialise all the internal TML variables */
113       memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE,
114              sizeof(phTmlNfc_Context_t));
115       /* Make sure that the thread runs once it is created */
116       gpphTmlNfc_Context->bThreadDone = 1;
117       /* Open the device file to which data is read/written */
118       wInitStatus = gpTransportObj->OpenAndConfigure(
119           pConfig, &(gpphTmlNfc_Context->pDevHandle));
120 
121       if (NFCSTATUS_SUCCESS != wInitStatus) {
122         wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE);
123         gpphTmlNfc_Context->pDevHandle = NULL;
124       } else {
125         phTmlNfc_IoCtl(phTmlNfc_e_SetNfcState);
126         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
127         gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
128         gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
129         gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
130         if (pConfig->fragment_len == 0x00)
131           pConfig->fragment_len = PH_TMLNFC_FRGMENT_SIZE_PN557;
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_TmlThread
282 **
283 ** Description      Read the data from the lower layer driver
284 **
285 ** Parameters       pParam  - parameters for Writer thread function
286 **
287 ** Returns          None
288 **
289 *******************************************************************************/
phTmlNfc_TmlThread(void * pParam)290 static void* phTmlNfc_TmlThread(void* pParam) {
291   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
292   int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
293   uint8_t temp[PH_TMLNFC_MAX_READ_NCI_BUFF_LEN];
294   uint8_t readRetryDelay = 0;
295   /* Transaction info buffer to be passed to Callback Thread */
296   static phTmlNfc_TransactInfo_t tTransactionInfo;
297   /* Structure containing Tml callback function and parameters to be invoked
298      by the callback thread */
299   static phLibNfc_DeferredCall_t tDeferredInfo;
300   /* Initialize Message structure to post message onto Callback Thread */
301   static phLibNfc_Message_t tMsg;
302   UNUSED_PROP(pParam);
303   NXPLOG_TML_D("NFCC - Tml Reader Thread Started................\n");
304 
305   /* Reader thread loop shall be running till shutdown is invoked */
306   while (gpphTmlNfc_Context->bThreadDone) {
307     /* If Tml read is requested */
308     /* Set the variable to success initially */
309     wStatus = NFCSTATUS_SUCCESS;
310     if (-1 == sem_wait(&gpphTmlNfc_Context->rxSemaphore)) {
311       NXPLOG_TML_E("sem_wait didn't return success \n");
312     }
313 
314     /* If Tml read is requested */
315     if (1 == gpphTmlNfc_Context->tReadInfo.bEnable) {
316       NXPLOG_TML_D("NFCC - Read requested.....\n");
317       /* Set the variable to success initially */
318       wStatus = NFCSTATUS_SUCCESS;
319 
320       /* Variable to fetch the actual number of bytes read */
321       dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
322 
323       /* Read the data from the file onto the buffer */
324       if (NULL != gpphTmlNfc_Context->pDevHandle) {
325         NXPLOG_TML_D("NFCC - Invoking Read.....\n");
326         dwNoBytesWrRd =
327             gpTransportObj->Read(gpphTmlNfc_Context->pDevHandle, temp,
328                                  PH_TMLNFC_MAX_READ_NCI_BUFF_LEN);
329 
330         if (-1 == dwNoBytesWrRd) {
331           NXPLOG_TML_E("NFCC - Error in Read.....\n");
332           if (readRetryDelay < MAX_READ_RETRY_DELAY_IN_MILLISEC) {
333             /*sleep for 30/60/90/120/150 msec between each read trial incase of
334              * read error*/
335             readRetryDelay += 30;
336           }
337           usleep(readRetryDelay * 1000);
338           sem_post(&gpphTmlNfc_Context->rxSemaphore);
339         } else if (dwNoBytesWrRd == PH_TMNFC_VBAT_LOW_ERROR) {
340           NXPLOG_TML_E(
341               "Platform VBAT Error detected by NFCC "
342               "NFC restart... : %d\n",
343               dwNoBytesWrRd);
344           abort();
345         } else if (dwNoBytesWrRd > PH_TMLNFC_MAX_READ_NCI_BUFF_LEN) {
346           NXPLOG_TML_E("Numer of bytes read exceeds the limit 260.....\n");
347           readRetryDelay = 0;
348           sem_post(&gpphTmlNfc_Context->rxSemaphore);
349         } else {
350           memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
351           readRetryDelay = 0;
352 
353           NXPLOG_TML_D("NFCC - Read successful.....\n");
354           /* This has to be reset only after a successful read */
355           gpphTmlNfc_Context->tReadInfo.bEnable = 0;
356           if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
357               (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) {
358             NXPLOG_TML_D("NFCC - Retransmission timer stopped.....\n");
359             /* Stop Timer to prevent Retransmission */
360             uint32_t timerStatus =
361                 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId);
362             if (NFCSTATUS_SUCCESS != timerStatus) {
363               NXPLOG_TML_E("NFCC - timer stopped returned failure.....\n");
364             } else {
365               gpphTmlNfc_Context->bWriteCbInvoked = false;
366             }
367           }
368           /* Update the actual number of bytes read including header */
369           gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
370           phNxpNciHal_print_packet("RECV",
371                                    gpphTmlNfc_Context->tReadInfo.pBuffer,
372                                    gpphTmlNfc_Context->tReadInfo.wLength);
373 
374           dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
375 
376           /* Fill the Transaction info structure to be passed to Callback
377            * Function */
378           tTransactionInfo.wStatus = wStatus;
379           tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer;
380           /* Actual number of bytes read is filled in the structure */
381           tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength;
382 
383           /* Read operation completed successfully. Post a Message onto Callback
384            * Thread*/
385           /* Prepare the message to be posted on User thread */
386           tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb;
387           tDeferredInfo.pParameter = &tTransactionInfo;
388           tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
389           tMsg.pMsgData = &tDeferredInfo;
390           tMsg.Size = sizeof(tDeferredInfo);
391           NXPLOG_TML_D("NFCC - Posting read message.....\n");
392           phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
393         }
394       } else {
395         NXPLOG_TML_D("NFCC -gpphTmlNfc_Context->pDevHandle is NULL");
396       }
397     } else {
398       NXPLOG_TML_D("NFCC - read request NOT enabled");
399       usleep(10 * 1000);
400     }
401   } /* End of While loop */
402 
403   return NULL;
404 }
405 
406 /*******************************************************************************
407 **
408 ** Function         phTmlNfc_TmlWriterThread
409 **
410 ** Description      Writes the requested data onto the lower layer driver
411 **
412 ** Parameters       pParam  - context provided by upper layer
413 **
414 ** Returns          None
415 **
416 *******************************************************************************/
phTmlNfc_TmlWriterThread(void * pParam)417 static void* phTmlNfc_TmlWriterThread(void* pParam) {
418   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
419   int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
420   /* Transaction info buffer to be passed to Callback Thread */
421   static phTmlNfc_TransactInfo_t tTransactionInfo;
422   /* Structure containing Tml callback function and parameters to be invoked
423      by the callback thread */
424   static phLibNfc_DeferredCall_t tDeferredInfo;
425   /* Initialize Message structure to post message onto Callback Thread */
426   static phLibNfc_Message_t tMsg;
427   /* In case of I2C Write Retry */
428   static uint16_t retry_cnt;
429   UNUSED_PROP(pParam);
430   NXPLOG_TML_D("NFCC - Tml Writer Thread Started................\n");
431 
432   /* Writer thread loop shall be running till shutdown is invoked */
433   while (gpphTmlNfc_Context->bThreadDone) {
434     NXPLOG_TML_D("NFCC - Tml Writer Thread Running................\n");
435     if (-1 == sem_wait(&gpphTmlNfc_Context->txSemaphore)) {
436       NXPLOG_TML_E("sem_wait didn't return success \n");
437     }
438     /* If Tml write is requested */
439     if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) {
440       NXPLOG_TML_D("NFCC - Write requested.....\n");
441       /* Set the variable to success initially */
442       wStatus = NFCSTATUS_SUCCESS;
443       if (NULL != gpphTmlNfc_Context->pDevHandle) {
444       retry:
445         gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
446         /* Variable to fetch the actual number of bytes written */
447         dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
448         /* Write the data in the buffer onto the file */
449         NXPLOG_TML_D("NFCC - Invoking Write.....\n");
450         /* TML reader writer callback synchronization mutex lock --- START */
451         pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
452         gpphTmlNfc_Context->gWriterCbflag = false;
453         dwNoBytesWrRd =
454             gpTransportObj->Write(gpphTmlNfc_Context->pDevHandle,
455                                   gpphTmlNfc_Context->tWriteInfo.pBuffer,
456                                   gpphTmlNfc_Context->tWriteInfo.wLength);
457         /* TML reader writer callback synchronization mutex lock --- END */
458         pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
459 
460         /* Try NFCC Write Five Times, if it fails: */
461         if (-1 == dwNoBytesWrRd) {
462           if (gpTransportObj->IsFwDnldModeEnabled()) {
463             if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) {
464               NXPLOG_TML_D("NFCC - Error in Write  - Retry 0x%x", retry_cnt);
465               // Add a 10 ms delay to ensure NFCC is not still in stand by mode.
466               usleep(10 * 1000);
467               goto retry;
468             }
469           }
470           NXPLOG_TML_D("NFCC - Error in Write.....\n");
471           wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
472         } else {
473           phNxpNciHal_print_packet("SEND",
474                                    gpphTmlNfc_Context->tWriteInfo.pBuffer,
475                                    gpphTmlNfc_Context->tWriteInfo.wLength);
476         }
477         retry_cnt = 0;
478         if (NFCSTATUS_SUCCESS == wStatus) {
479           NXPLOG_TML_D("NFCC - Write successful.....\n");
480           dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
481         }
482         /* Fill the Transaction info structure to be passed to Callback Function
483          */
484         tTransactionInfo.wStatus = wStatus;
485         tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
486         /* Actual number of bytes written is filled in the structure */
487         tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
488 
489         /* Prepare the message to be posted on the User thread */
490         tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
491         tDeferredInfo.pParameter = &tTransactionInfo;
492         /* Write operation completed successfully. Post a Message onto Callback
493          * Thread*/
494         tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
495         tMsg.pMsgData = &tDeferredInfo;
496         tMsg.Size = sizeof(tDeferredInfo);
497 
498         /* Check whether Retransmission needs to be started,
499          * If yes, Post message only if
500          * case 1. Message is not posted &&
501          * case 11. Write status is success ||
502          * case 12. Last retry of write is also failure
503          */
504         if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
505             (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
506           if (gpphTmlNfc_Context->bWriteCbInvoked == false) {
507             if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) {
508               NXPLOG_TML_D("NFCC - Posting Write message.....\n");
509               phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
510                                     &tMsg);
511               gpphTmlNfc_Context->bWriteCbInvoked = true;
512             }
513           }
514         } else {
515           NXPLOG_TML_D("NFCC - Posting Fresh Write message.....\n");
516           phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
517           if (NFCSTATUS_SUCCESS == wStatus) {
518             /*TML reader writer thread callback synchronization---START*/
519             pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
520             gpphTmlNfc_Context->gWriterCbflag = true;
521             phTmlNfc_SignalWriteComplete();
522             /*TML reader writer thread callback synchronization---END*/
523             pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
524           }
525         }
526       } else {
527         NXPLOG_TML_D("NFCC - gpphTmlNfc_Context->pDevHandle is NULL");
528       }
529     } else {
530       NXPLOG_TML_D("NFCC - Write request NOT enabled");
531       usleep(10000);
532     }
533 
534   } /* End of While loop */
535 
536   return NULL;
537 }
538 
539 /*******************************************************************************
540 **
541 ** Function         phTmlNfc_CleanUp
542 **
543 ** Description      Clears all handles opened during TML initialization
544 **
545 ** Parameters       None
546 **
547 ** Returns          None
548 **
549 *******************************************************************************/
phTmlNfc_CleanUp(void)550 void phTmlNfc_CleanUp(void) {
551   if (NULL == gpphTmlNfc_Context) {
552     return;
553   }
554   sem_destroy(&gpphTmlNfc_Context->rxSemaphore);
555   sem_destroy(&gpphTmlNfc_Context->txSemaphore);
556   sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore);
557   pthread_mutex_destroy(&gpphTmlNfc_Context->wait_busy_lock);
558   pthread_cond_destroy(&gpphTmlNfc_Context->wait_busy_condition);
559   gpTransportObj = NULL;
560   /* Clear memory allocated for storing Context variables */
561   free((void*)gpphTmlNfc_Context);
562   /* Set the pointer to NULL to indicate De-Initialization */
563   gpphTmlNfc_Context = NULL;
564 
565   return;
566 }
567 
568 /*******************************************************************************
569 **
570 ** Function         phTmlNfc_Shutdown
571 **
572 ** Description      Uninitializes TML layer and hardware interface
573 **
574 ** Parameters       None
575 **
576 ** Returns          NFC status:
577 **                  NFCSTATUS_SUCCESS - TML configuration released successfully
578 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
579 **                                                invalid
580 **                  NFCSTATUS_FAILED - un-initialization failed (example: unable
581 **                                     to close interface)
582 **
583 *******************************************************************************/
phTmlNfc_Shutdown(void)584 NFCSTATUS phTmlNfc_Shutdown(void) {
585   NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS;
586 
587   /* Check whether TML is Initialized */
588   if (NULL != gpphTmlNfc_Context) {
589     /* Reset thread variable to terminate the thread */
590     gpphTmlNfc_Context->bThreadDone = 0;
591     usleep(1000);
592     /* Clear All the resources allocated during initialization */
593     sem_post(&gpphTmlNfc_Context->rxSemaphore);
594     usleep(1000);
595     sem_post(&gpphTmlNfc_Context->txSemaphore);
596     usleep(1000);
597     sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
598     usleep(1000);
599     sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
600     usleep(1000);
601 
602     if (IS_CHIP_TYPE_L(sn100u)) {
603       (void)gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
604                                       MODE_POWER_OFF);
605     }
606     phTmlNfc_IoCtl(phTmlNfc_e_ResetNfcState);
607     gpTransportObj->Close(gpphTmlNfc_Context->pDevHandle);
608     gpphTmlNfc_Context->pDevHandle = NULL;
609     if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) {
610       NXPLOG_TML_E("Fail to kill reader thread!");
611     }
612     if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) {
613       NXPLOG_TML_E("Fail to kill writer thread!");
614     }
615     NXPLOG_TML_D("bThreadDone == 0");
616 
617   } else {
618     wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
619   }
620 
621   return wShutdownStatus;
622 }
623 
624 /*******************************************************************************
625 **
626 ** Function         phTmlNfc_Write
627 **
628 ** Description      Asynchronously writes given data block to hardware
629 **                  interface/driver. Enables writer thread if there are no
630 **                  write requests pending. Returns successfully once writer
631 **                  thread completes write operation. Notifies upper layer using
632 **                  callback mechanism.
633 **
634 **                  NOTE:
635 **                  * it is important to post a message with id
636 **                    PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data
637 **                    has been written to NFCC
638 **                  * if CRC needs to be computed, then input buffer should be
639 **                    capable to store two more bytes apart from length of
640 **                    packet
641 **
642 ** Parameters       pBuffer - data to be sent
643 **                  wLength - length of data buffer
644 **                  pTmlWriteComplete - pointer to the function to be invoked
645 **                                      upon completion
646 **                  pContext - context provided by upper layer
647 **
648 ** Returns          NFC status:
649 **                  NFCSTATUS_PENDING - command is yet to be processed
650 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
651 **                                                invalid
652 **                  NFCSTATUS_BUSY - write request is already in progress
653 **
654 *******************************************************************************/
phTmlNfc_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,void * pContext)655 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength,
656                          pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,
657                          void* pContext) {
658   NFCSTATUS wWriteStatus;
659 
660   /* Check whether TML is Initialized */
661 
662   if (NULL != gpphTmlNfc_Context) {
663     if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) &&
664         (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
665       if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
666         /* Setting the flag marks beginning of a Write Operation */
667         gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
668         /* Copy the buffer, length and Callback function,
669            This shall be utilized while invoking the Callback function in thread
670            */
671         gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer;
672         gpphTmlNfc_Context->tWriteInfo.wLength = wLength;
673         gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
674         gpphTmlNfc_Context->tWriteInfo.pContext = pContext;
675 
676         wWriteStatus = NFCSTATUS_PENDING;
677         // FIXME: If retry is going on. Stop the retry thread/timer
678         if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) {
679           /* Set retry count to default value */
680           // FIXME: If the timer expired there, and meanwhile we have created
681           // a new request. The expired timer will think that retry is still
682           // ongoing.
683           bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount;
684           gpphTmlNfc_Context->bWriteCbInvoked = false;
685         }
686         /* Set event to invoke Writer Thread */
687         gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
688         sem_post(&gpphTmlNfc_Context->txSemaphore);
689       } else {
690         wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
691       }
692     } else {
693       wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
694     }
695   } else {
696     wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
697   }
698 
699   return wWriteStatus;
700 }
701 
702 /*******************************************************************************
703 **
704 ** Function         phTmlNfc_Read
705 **
706 ** Description      Asynchronously reads data from the driver
707 **                  Number of bytes to be read and buffer are passed by upper
708 **                  layer.
709 **                  Enables reader thread if there are no read requests pending
710 **                  Returns successfully once read operation is completed
711 **                  Notifies upper layer using callback mechanism
712 **
713 ** Parameters       pBuffer - location to send read data to the upper layer via
714 **                            callback
715 **                  wLength - length of read data buffer passed by upper layer
716 **                  pTmlReadComplete - pointer to the function to be invoked
717 **                                     upon completion of read operation
718 **                  pContext - context provided by upper layer
719 **
720 ** Returns          NFC status:
721 **                  NFCSTATUS_PENDING - command is yet to be processed
722 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
723 **                                                invalid
724 **                  NFCSTATUS_BUSY - read request is already in progress
725 **
726 *******************************************************************************/
phTmlNfc_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,void * pContext)727 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength,
728                         pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,
729                         void* pContext) {
730   NFCSTATUS wReadStatus;
731   int rxSemVal = 0, ret = 0;
732 
733   /* Check whether TML is Initialized */
734   if (NULL != gpphTmlNfc_Context) {
735     if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
736         (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) {
737       if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) {
738         /* Setting the flag marks beginning of a Read Operation */
739         gpphTmlNfc_Context->tReadInfo.bThreadBusy = true;
740         /* Copy the buffer, length and Callback function,
741            This shall be utilized while invoking the Callback function in thread
742            */
743         gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer;
744         gpphTmlNfc_Context->tReadInfo.wLength = wLength;
745         gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
746         gpphTmlNfc_Context->tReadInfo.pContext = pContext;
747         wReadStatus = NFCSTATUS_PENDING;
748 
749         /* Set event to invoke Reader Thread */
750         gpphTmlNfc_Context->tReadInfo.bEnable = 1;
751         ret = sem_getvalue(&gpphTmlNfc_Context->rxSemaphore, &rxSemVal);
752         /* Post rxSemaphore either if sem_getvalue() is failed or rxSemVal is 0
753          */
754         if (ret || !rxSemVal) {
755           sem_post(&gpphTmlNfc_Context->rxSemaphore);
756         } else {
757           NXPLOG_TML_D(
758               "%s: skip reader thread scheduling, ret=%x, rxSemaVal=%x",
759               __func__, ret, rxSemVal);
760         }
761       } else {
762         wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
763       }
764     } else {
765       wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
766     }
767   } else {
768     wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
769   }
770 
771   return wReadStatus;
772 }
773 
774 /*******************************************************************************
775 **
776 ** Function         phTmlNfc_ReadAbort
777 **
778 ** Description      Aborts pending read request (if any)
779 **
780 ** Parameters       None
781 **
782 ** Returns          NFC status:
783 **                  NFCSTATUS_SUCCESS - ongoing read operation aborted
784 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
785 **                                                invalid
786 **                  NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
787 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read
788 **                                                        operation
789 **
790 *******************************************************************************/
phTmlNfc_ReadAbort(void)791 NFCSTATUS phTmlNfc_ReadAbort(void) {
792   NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
793   gpphTmlNfc_Context->tReadInfo.bEnable = 0;
794 
795   /*Reset the flag to accept another Read Request */
796   gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
797   wStatus = NFCSTATUS_SUCCESS;
798 
799   return wStatus;
800 }
801 
802 /*******************************************************************************
803 **
804 ** Function         phTmlNfc_WriteAbort
805 **
806 ** Description      Aborts pending write request (if any)
807 **
808 ** Parameters       None
809 **
810 ** Returns          NFC status:
811 **                  NFCSTATUS_SUCCESS - ongoing write operation aborted
812 **                  NFCSTATUS_INVALID_PARAMETER - at least one parameter is
813 **                                                invalid
814 **                  NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
815 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write
816 **                                                        operation
817 **
818 *******************************************************************************/
phTmlNfc_WriteAbort(void)819 NFCSTATUS phTmlNfc_WriteAbort(void) {
820   NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
821 
822   gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
823   /* Stop if any retransmission is in progress */
824   bCurrentRetryCount = 0;
825 
826   /* Reset the flag to accept another Write Request */
827   gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
828   wStatus = NFCSTATUS_SUCCESS;
829 
830   return wStatus;
831 }
832 
833 /*******************************************************************************
834 **
835 ** Function         phTmlNfc_IoCtl
836 **
837 ** Description      Resets device when insisted by upper layer
838 **                  Number of bytes to be read and buffer are passed by upper
839 **                  layer
840 **                  Enables reader thread if there are no read requests pending
841 **                  Returns successfully once read operation is completed
842 **                  Notifies upper layer using callback mechanism
843 **
844 ** Parameters       eControlCode       - control code for a specific operation
845 **
846 ** Returns          NFC status:
847 **                  NFCSTATUS_SUCCESS  - ioctl command completed successfully
848 **                  NFCSTATUS_FAILED   - ioctl command request failed
849 **
850 *******************************************************************************/
phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)851 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) {
852   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
853 
854   if (NULL == gpphTmlNfc_Context) {
855     wStatus = NFCSTATUS_FAILED;
856   } else {
857     uint8_t read_flag = (gpphTmlNfc_Context->tReadInfo.bEnable > 0);
858 
859     switch (eControlCode) {
860       case phTmlNfc_e_PowerReset: {
861         if (IS_CHIP_TYPE_GE(sn100u)) {
862           /*VEN_RESET*/
863           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
864                                     MODE_POWER_RESET);
865         } else {
866           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
867                                     MODE_POWER_ON);
868           usleep(100 * 1000);
869           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
870                                     MODE_POWER_OFF);
871           usleep(100 * 1000);
872           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
873                                     MODE_POWER_ON);
874         }
875         break;
876       }
877       case phTmlNfc_e_EnableVen: {
878         if (IS_CHIP_TYPE_L(sn100u)) {
879           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
880                                     MODE_POWER_ON);
881           usleep(100 * 1000);
882         }
883         break;
884       }
885       case phTmlNfc_e_ResetDevice:
886 
887       {
888         if (IS_CHIP_TYPE_L(sn100u)) {
889           /*Reset NFCC*/
890           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
891                                     MODE_POWER_ON);
892           usleep(100 * 1000);
893           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
894                                     MODE_POWER_OFF);
895           usleep(100 * 1000);
896           gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
897                                     MODE_POWER_ON);
898         }
899         break;
900       }
901       case phTmlNfc_e_EnableNormalMode: {
902         /*Reset NFCC*/
903         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
904         if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
905           NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with VEN RESET ");
906           if (IS_CHIP_TYPE_L(sn100u)) {
907             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
908                                       MODE_POWER_OFF);
909             usleep(10 * 1000);
910             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
911                                       MODE_POWER_ON);
912             usleep(100 * 1000);
913           } else {
914             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
915                                       MODE_FW_GPIO_LOW);
916           }
917         } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
918           NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with NCI CMD ");
919           if (IS_CHIP_TYPE_L(sn100u)) {
920             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
921                                       MODE_POWER_ON);
922           } else {
923             gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
924                                       MODE_FW_GPIO_LOW);
925           }
926         }
927         break;
928       }
929       case phTmlNfc_e_EnableDownloadMode: {
930         phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
931         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
932         if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
933           NXPLOG_TML_D(
934               " phTmlNfc_e_EnableDownloadMode complete with VEN RESET ");
935           wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
936                                               MODE_FW_DWNLD_WITH_VEN);
937         } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
938           NXPLOG_TML_D(" phTmlNfc_e_EnableDownloadMode complete with NCI CMD ");
939           wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
940                                               MODE_FW_DWND_HIGH);
941         }
942         break;
943       }
944       case phTmlNfc_e_EnableDownloadModeWithVenRst: {
945         phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
946         gpphTmlNfc_Context->tReadInfo.bEnable = 0;
947         NXPLOG_TML_D(
948             " phTmlNfc_e_EnableDownloadModewithVenRst complete with "
949             "VEN RESET ");
950         wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
951                                             MODE_FW_DWNLD_WITH_VEN);
952         break;
953       }
954       case phTmlNfc_e_setFragmentSize: {
955         if (IS_CHIP_TYPE_EQ(sn300u)) {
956           if (phTmlNfc_IsFwDnldModeEnabled() && IS_4K_SUPPORT) {
957             gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_SN300;
958           } else {
959             gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_SNXXX;
960           }
961         } else if (IS_CHIP_TYPE_NE(pn557)) {
962           gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_SNXXX;
963         } else {
964           gpphTmlNfc_Context->fragment_len = PH_TMLNFC_FRGMENT_SIZE_PN557;
965         }
966         NXPLOG_TML_D("Set FragmentSize: %u", gpphTmlNfc_Context->fragment_len);
967         break;
968       }
969       case phTmlNfc_e_SetNfcState: {
970         gpTransportObj->UpdateReadPending(gpphTmlNfc_Context->pDevHandle,
971                                           MODE_NFC_SET_READ_PENDING);
972         break;
973       }
974       case phTmlNfc_e_ResetNfcState: {
975         gpTransportObj->UpdateReadPending(gpphTmlNfc_Context->pDevHandle,
976                                           MODE_NFC_RESET_READ_PENDING);
977         break;
978       }
979       case phTmlNfc_e_PullVenLow: {
980         gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
981                                   MODE_POWER_OFF);
982         break;
983       }
984       case phTmlNfc_e_PullVenHigh: {
985         gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
986                                   MODE_POWER_ON);
987         break;
988       }
989       default: {
990         wStatus = NFCSTATUS_INVALID_PARAMETER;
991         break;
992       }
993     }
994     if (read_flag && (gpphTmlNfc_Context->tReadInfo.bEnable == 0x00)) {
995       gpphTmlNfc_Context->tReadInfo.bEnable = 1;
996       sem_post(&gpphTmlNfc_Context->rxSemaphore);
997     }
998   }
999 
1000   return wStatus;
1001 }
1002 
1003 /*******************************************************************************
1004 **
1005 ** Function         phTmlNfc_DeferredCall
1006 **
1007 ** Description      Posts message on upper layer thread
1008 **                  upon successful read or write operation
1009 **
1010 ** Parameters       dwThreadId  - id of the thread posting message
1011 **                  ptWorkerMsg - message to be posted
1012 **
1013 ** Returns          None
1014 **
1015 *******************************************************************************/
phTmlNfc_DeferredCall(uintptr_t dwThreadId,phLibNfc_Message_t * ptWorkerMsg)1016 void phTmlNfc_DeferredCall(uintptr_t dwThreadId,
1017                            phLibNfc_Message_t* ptWorkerMsg) {
1018   UNUSED_PROP(dwThreadId);
1019   /* Post message on the user thread to invoke the callback function */
1020   if (-1 == sem_wait(&gpphTmlNfc_Context->postMsgSemaphore)) {
1021     NXPLOG_TML_E("sem_wait didn't return success \n");
1022   }
1023   phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0);
1024   sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
1025 }
1026 
1027 /*******************************************************************************
1028 **
1029 ** Function         phTmlNfc_ReadDeferredCb
1030 **
1031 ** Description      Read thread call back function
1032 **
1033 ** Parameters       pParams - context provided by upper layer
1034 **
1035 ** Returns          None
1036 **
1037 *******************************************************************************/
phTmlNfc_ReadDeferredCb(void * pParams)1038 static void phTmlNfc_ReadDeferredCb(void* pParams) {
1039   /* Transaction info buffer to be passed to Callback Function */
1040   phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1041 
1042   /* Reset the flag to accept another Read Request */
1043   gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
1044   gpphTmlNfc_Context->tReadInfo.pThread_Callback(
1045       gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo);
1046 
1047   return;
1048 }
1049 
1050 /*******************************************************************************
1051 **
1052 ** Function         phTmlNfc_WriteDeferredCb
1053 **
1054 ** Description      Write thread call back function
1055 **
1056 ** Parameters       pParams - context provided by upper layer
1057 **
1058 ** Returns          None
1059 **
1060 *******************************************************************************/
phTmlNfc_WriteDeferredCb(void * pParams)1061 static void phTmlNfc_WriteDeferredCb(void* pParams) {
1062   /* Transaction info buffer to be passed to Callback Function */
1063   phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1064 
1065   /* Reset the flag to accept another Write Request */
1066   gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
1067   gpphTmlNfc_Context->tWriteInfo.pThread_Callback(
1068       gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo);
1069 
1070   return;
1071 }
1072 
phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)1073 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) {
1074   fragmentation_enabled = result;
1075 }
1076 
1077 /*******************************************************************************
1078 **
1079 ** Function         phTmlNfc_SignalWriteComplete
1080 **
1081 ** Description      function to invoke reader thread
1082 **
1083 ** Parameters       None
1084 **
1085 ** Returns          None
1086 **
1087 *******************************************************************************/
phTmlNfc_SignalWriteComplete(void)1088 static void phTmlNfc_SignalWriteComplete(void) {
1089   int ret = -1;
1090   if (gpphTmlNfc_Context->wait_busy_flag == true) {
1091     NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - enter");
1092     gpphTmlNfc_Context->wait_busy_flag = false;
1093 
1094     ret = pthread_cond_signal(&gpphTmlNfc_Context->wait_busy_condition);
1095     if (ret) {
1096       NXPLOG_TML_E(" phTmlNfc_SignalWriteComplete failed, error = 0x%X", ret);
1097     }
1098     NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - exit");
1099   }
1100 }
1101 
1102 /*******************************************************************************
1103 **
1104 ** Function         phTmlNfc_WaitReadInit
1105 **
1106 ** Description      init function for reader thread
1107 **
1108 ** Parameters       None
1109 **
1110 ** Returns          int
1111 **
1112 *******************************************************************************/
phTmlNfc_WaitReadInit(void)1113 static int phTmlNfc_WaitReadInit(void) {
1114   int ret = -1;
1115   pthread_condattr_t attr;
1116   pthread_condattr_init(&attr);
1117   pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
1118   memset(&gpphTmlNfc_Context->wait_busy_condition, 0,
1119          sizeof(gpphTmlNfc_Context->wait_busy_condition));
1120   pthread_mutex_init(&gpphTmlNfc_Context->wait_busy_lock, NULL);
1121   ret = pthread_cond_init(&gpphTmlNfc_Context->wait_busy_condition, &attr);
1122   if (ret) {
1123     NXPLOG_TML_E(" phTphTmlNfc_WaitReadInit failed, error = 0x%X", ret);
1124   }
1125   return ret;
1126 }
1127 
1128 /*******************************************************************************
1129 **
1130 ** Function         phTmlNfc_EnableFwDnldMode
1131 **
1132 ** Description      wrapper function for enabling/disabling FW download mode
1133 **
1134 ** Parameters       True/False
1135 **
1136 ** Returns          NFCSTATUS
1137 **
1138 *******************************************************************************/
phTmlNfc_EnableFwDnldMode(bool mode)1139 void phTmlNfc_EnableFwDnldMode(bool mode) {
1140   gpTransportObj->EnableFwDnldMode(mode);
1141 }
1142 
1143 /*******************************************************************************
1144 **
1145 ** Function         phTmlNfc_IsFwDnldModeEnabled
1146 **
1147 ** Description      wrapper function  to get the FW download flag
1148 **
1149 ** Parameters       None
1150 **
1151 ** Returns          True/False status of FW download flag
1152 **
1153 *******************************************************************************/
phTmlNfc_IsFwDnldModeEnabled(void)1154 bool phTmlNfc_IsFwDnldModeEnabled(void) {
1155   return gpTransportObj->IsFwDnldModeEnabled();
1156 }
1157 
1158 /*******************************************************************************
1159 **
1160 ** Function         phTmlNfc_Shutdown_CleanUp
1161 **
1162 ** Description      wrapper function  for shutdown  and cleanup of resources
1163 **
1164 ** Parameters       None
1165 **
1166 ** Returns          NFCSTATUS
1167 **
1168 *******************************************************************************/
phTmlNfc_Shutdown_CleanUp()1169 NFCSTATUS phTmlNfc_Shutdown_CleanUp() {
1170   NFCSTATUS wShutdownStatus = phTmlNfc_Shutdown();
1171   phTmlNfc_CleanUp();
1172   return wShutdownStatus;
1173 }
1174