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