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