• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 = NULL;
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 (NULL != 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 if (dwNoBytesWrRd > 260)
370                 {
371                     NXPLOG_TML_E ("Numer of bytes read exceeds the limit 260.....\n");
372                     sem_post (&gpphTmlNfc_Context->rxSemaphore);
373                 }
374                 else
375                 {
376                     memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
377 
378                     NXPLOG_TML_D("PN54X - I2C Read successful.....\n");
379                     /* This has to be reset only after a successful read */
380                     gpphTmlNfc_Context->tReadInfo.bEnable = 0;
381                     if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
382                             (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0)))
383                     {
384 
385                         NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n");
386                         /* Stop Timer to prevent Retransmission */
387                         uint32_t timerStatus = phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId);
388                         if (NFCSTATUS_SUCCESS != timerStatus)
389                         {
390                             NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n");
391                         }
392                         else
393                         {
394                             gpphTmlNfc_Context->bWriteCbInvoked = FALSE;
395                         }
396                     }
397                     if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy)
398                     {
399                         NXPLOG_TML_D ("Delay Read if write thread is busy");
400                         usleep (2000); /*2ms delay to give prio to write complete */
401                     }
402                     /* Update the actual number of bytes read including header */
403                     gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t) (dwNoBytesWrRd);
404                     phNxpNciHal_print_packet("RECV", gpphTmlNfc_Context->tReadInfo.pBuffer,
405                             gpphTmlNfc_Context->tReadInfo.wLength);
406 
407                     dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
408 
409                     /* Fill the Transaction info structure to be passed to Callback Function */
410                     tTransactionInfo.wStatus = wStatus;
411                     tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer;
412                     /* Actual number of bytes read is filled in the structure */
413                     tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength;
414 
415                     /* Read operation completed successfully. Post a Message onto Callback Thread*/
416                     /* Prepare the message to be posted on User thread */
417                     tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb;
418                     tDeferredInfo.pParameter = &tTransactionInfo;
419                     tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
420                     tMsg.pMsgData = &tDeferredInfo;
421                     tMsg.Size = sizeof(tDeferredInfo);
422                     NXPLOG_TML_D("PN54X - Posting read message.....\n");
423                     phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
424 
425                 }
426             }
427             else
428             {
429                 NXPLOG_TML_D ("PN54X -gpphTmlNfc_Context->pDevHandle is NULL");
430             }
431         }
432         else
433         {
434             NXPLOG_TML_D("PN54X - read request NOT enabled");
435             usleep(10*1000);
436         }
437     }/* End of While loop */
438 
439     return;
440 }
441 
442 /*******************************************************************************
443 **
444 ** Function         phTmlNfc_TmlWriterThread
445 **
446 ** Description      Writes the requested data onto the lower layer driver
447 **
448 ** Parameters       pParam  - context provided by upper layer
449 **
450 ** Returns          None
451 **
452 *******************************************************************************/
phTmlNfc_TmlWriterThread(void * pParam)453 static void phTmlNfc_TmlWriterThread(void *pParam)
454 {
455     NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
456     int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
457     /* Transaction info buffer to be passed to Callback Thread */
458     static phTmlNfc_TransactInfo_t tTransactionInfo;
459     /* Structure containing Tml callback function and parameters to be invoked
460        by the callback thread */
461     static phLibNfc_DeferredCall_t tDeferredInfo;
462     /* Initialize Message structure to post message onto Callback Thread */
463     static phLibNfc_Message_t tMsg;
464     /* In case of I2C Write Retry */
465     static uint16_t retry_cnt;
466     UNUSED(pParam);
467     NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n");
468 
469     /* Writer thread loop shall be running till shutdown is invoked */
470     while (gpphTmlNfc_Context->bThreadDone)
471     {
472         NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n");
473         sem_wait(&gpphTmlNfc_Context->txSemaphore);
474         /* If Tml write is requested */
475         if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable)
476         {
477             NXPLOG_TML_D("PN54X - Write requested.....\n");
478             /* Set the variable to success initially */
479             wStatus = NFCSTATUS_SUCCESS;
480             if (NULL != gpphTmlNfc_Context->pDevHandle)
481             {
482             retry:
483                 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
484                 /* Variable to fetch the actual number of bytes written */
485                 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
486                 /* Write the data in the buffer onto the file */
487                 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n");
488                 dwNoBytesWrRd = phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle,
489                         gpphTmlNfc_Context->tWriteInfo.pBuffer,
490                         gpphTmlNfc_Context->tWriteInfo.wLength
491                         );
492 
493                 /* Try I2C Write Five Times, if it fails : Raju */
494                 if (-1 == dwNoBytesWrRd)
495                 {
496                     if (getDownloadFlag() == TRUE)
497                     {
498                         if (retry_cnt++ < MAX_WRITE_RETRY_COUNT)
499                         {
500                             NXPLOG_NCIHAL_E(
501                                     "PN54X - Error in I2C Write  - Retry 0x%x", retry_cnt);
502                             goto retry;
503                         }
504                     }
505                     NXPLOG_TML_E("PN54X - Error in I2C Write.....\n");
506                     wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
507                 }
508                 else
509                 {
510                     phNxpNciHal_print_packet("SEND", gpphTmlNfc_Context->tWriteInfo.pBuffer,
511                             gpphTmlNfc_Context->tWriteInfo.wLength);
512                 }
513                 retry_cnt = 0;
514                 if (NFCSTATUS_SUCCESS == wStatus)
515                 {
516                     NXPLOG_TML_D("PN54X - I2C Write successful.....\n");
517                     dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
518                 }
519                 /* Fill the Transaction info structure to be passed to Callback Function */
520                 tTransactionInfo.wStatus = wStatus;
521                 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
522                 /* Actual number of bytes written is filled in the structure */
523                 tTransactionInfo.wLength = (uint16_t) dwNoBytesWrRd;
524 
525                 /* Prepare the message to be posted on the User thread */
526                 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
527                 tDeferredInfo.pParameter = &tTransactionInfo;
528                 /* Write operation completed successfully. Post a Message onto Callback Thread*/
529                 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
530                 tMsg.pMsgData = &tDeferredInfo;
531                 tMsg.Size = sizeof(tDeferredInfo);
532 
533                 /* Check whether Retransmission needs to be started,
534                  * If yes, Post message only if
535                  * case 1. Message is not posted &&
536                  * case 11. Write status is success ||
537                  * case 12. Last retry of write is also failure
538                  */
539                 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
540                         (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0)))
541                 {
542                     if (FALSE == gpphTmlNfc_Context->bWriteCbInvoked)
543                     {
544                         if ((NFCSTATUS_SUCCESS == wStatus) ||
545                                 (bCurrentRetryCount == 0))
546                         {
547                                 NXPLOG_TML_D("PN54X - Posting Write message.....\n");
548                                 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
549                                         &tMsg);
550                                 gpphTmlNfc_Context->bWriteCbInvoked = TRUE;
551                         }
552                     }
553                 }
554                 else
555                 {
556                     NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n");
557                     phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
558                 }
559             }
560             else
561             {
562                 NXPLOG_TML_D ("PN54X - gpphTmlNfc_Context->pDevHandle is NULL");
563             }
564 
565             /* If Data packet is sent, then NO retransmission */
566             if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
567                     (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0)))
568             {
569                 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case");
570                 wStatus = phTmlNfc_InitiateTimer();
571                 if (NFCSTATUS_SUCCESS != wStatus)
572                 {
573                     /* Reset Variables used for Retransmission */
574                     NXPLOG_TML_D("PN54X - Retransmission timer initiate failed");
575                     gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
576                     bCurrentRetryCount = 0;
577                 }
578             }
579         }
580         else
581         {
582             NXPLOG_TML_D("PN54X - Write request NOT enabled");
583             usleep(10000);
584         }
585 
586     }/* End of While loop */
587 
588     return;
589 }
590 
591 /*******************************************************************************
592 **
593 ** Function         phTmlNfc_CleanUp
594 **
595 ** Description      Clears all handles opened during TML initialization
596 **
597 ** Parameters       None
598 **
599 ** Returns          None
600 **
601 *******************************************************************************/
phTmlNfc_CleanUp(void)602 static void phTmlNfc_CleanUp(void)
603 {
604     NFCSTATUS wRetval = NFCSTATUS_SUCCESS;
605 
606     if (NULL != gpphTmlNfc_Context->pDevHandle)
607     {
608         (void) phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
609         gpphTmlNfc_Context->bThreadDone = 0;
610     }
611     sem_destroy(&gpphTmlNfc_Context->rxSemaphore);
612     sem_destroy(&gpphTmlNfc_Context->txSemaphore);
613     sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore);
614     phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle);
615     gpphTmlNfc_Context->pDevHandle = NULL;
616     /* Clear memory allocated for storing Context variables */
617     free((void *) gpphTmlNfc_Context);
618     /* Set the pointer to NULL to indicate De-Initialization */
619     gpphTmlNfc_Context = NULL;
620 
621     return;
622 }
623 
624 /*******************************************************************************
625 **
626 ** Function         phTmlNfc_Shutdown
627 **
628 ** Description      Uninitializes TML layer and hardware interface
629 **
630 ** Parameters       None
631 **
632 ** Returns          NFC status:
633 **                  NFCSTATUS_SUCCESS            - TML configuration released successfully
634 **                  NFCSTATUS_INVALID_PARAMETER  - at least one parameter is invalid
635 **                  NFCSTATUS_FAILED             - un-initialization failed (example: unable to close interface)
636 **
637 *******************************************************************************/
phTmlNfc_Shutdown(void)638 NFCSTATUS phTmlNfc_Shutdown(void)
639 {
640     NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS;
641 
642     /* Check whether TML is Initialized */
643     if (NULL != gpphTmlNfc_Context)
644     {
645         /* Reset thread variable to terminate the thread */
646         gpphTmlNfc_Context->bThreadDone = 0;
647         usleep(1000);
648         /* Clear All the resources allocated during initialization */
649         sem_post(&gpphTmlNfc_Context->rxSemaphore);
650         usleep(1000);
651         sem_post(&gpphTmlNfc_Context->txSemaphore);
652         usleep(1000);
653         sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
654         usleep(1000);
655         sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
656         usleep(1000);
657         if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL))
658         {
659             NXPLOG_TML_E ("Fail to kill reader thread!");
660         }
661         if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL))
662         {
663             NXPLOG_TML_E ("Fail to kill writer thread!");
664         }
665         NXPLOG_TML_D ("bThreadDone == 0");
666 
667         phTmlNfc_CleanUp();
668     }
669     else
670     {
671         wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
672     }
673 
674     return wShutdownStatus;
675 }
676 
677 /*******************************************************************************
678 **
679 ** Function         phTmlNfc_Write
680 **
681 ** Description      Asynchronously writes given data block to hardware interface/driver
682 **                  Enables writer thread if there are no write requests pending
683 **                  Returns successfully once writer thread completes write operation
684 **                  Notifies upper layer using callback mechanism
685 **                  NOTE:
686 **                  * it is important to post a message with id PH_TMLNFC_WRITE_MESSAGE
687 **                    to IntegrationThread after data has been written to PN54X
688 **                  * if CRC needs to be computed, then input buffer should be capable to store
689 **                    two more bytes apart from length of packet
690 **
691 ** Parameters       pBuffer              - data to be sent
692 **                  wLength              - length of data buffer
693 **                  pTmlWriteComplete    - pointer to the function to be invoked upon completion
694 **                  pContext             - context provided by upper layer
695 **
696 ** Returns          NFC status:
697 **                  NFCSTATUS_PENDING             - command is yet to be processed
698 **                  NFCSTATUS_INVALID_PARAMETER   - at least one parameter is invalid
699 **                  NFCSTATUS_BUSY                - write request is already in progress
700 **
701 *******************************************************************************/
phTmlNfc_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,void * pContext)702 NFCSTATUS phTmlNfc_Write(uint8_t *pBuffer, uint16_t wLength, pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete, void *pContext)
703 {
704     NFCSTATUS wWriteStatus;
705 
706     /* Check whether TML is Initialized */
707 
708     if (NULL != gpphTmlNfc_Context)
709     {
710         if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) &&
711                 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete))
712         {
713             if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy)
714             {
715                 /* Setting the flag marks beginning of a Write Operation */
716                 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = TRUE;
717                 /* Copy the buffer, length and Callback function,
718                    This shall be utilized while invoking the Callback function in thread */
719                 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer;
720                 gpphTmlNfc_Context->tWriteInfo.wLength = wLength;
721                 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
722                 gpphTmlNfc_Context->tWriteInfo.pContext = pContext;
723 
724                 wWriteStatus = NFCSTATUS_PENDING;
725                 //FIXME: If retry is going on. Stop the retry thread/timer
726                 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig)
727                 {
728                     /* Set retry count to default value */
729                     //FIXME: If the timer expired there, and meanwhile we have created
730                     // a new request. The expired timer will think that retry is still
731                     // ongoing.
732                     bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount;
733                     gpphTmlNfc_Context->bWriteCbInvoked = FALSE;
734                 }
735                 /* Set event to invoke Writer Thread */
736                 gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
737                 sem_post(&gpphTmlNfc_Context->txSemaphore);
738             }
739             else
740             {
741                 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
742             }
743         }
744         else
745         {
746             wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
747         }
748     }
749     else
750     {
751         wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
752     }
753 
754     return wWriteStatus;
755 }
756 
757 /*******************************************************************************
758 **
759 ** Function         phTmlNfc_Read
760 **
761 ** Description      Asynchronously reads data from the driver
762 **                  Number of bytes to be read and buffer are passed by upper layer
763 **                  Enables reader thread if there are no read requests pending
764 **                  Returns successfully once read operation is completed
765 **                  Notifies upper layer using callback mechanism
766 **
767 ** Parameters       pBuffer              - location to send read data to the upper layer via callback
768 **                  wLength              - length of read data buffer passed by upper layer
769 **                  pTmlReadComplete     - pointer to the function to be invoked upon completion of read operation
770 **                  pContext             - context provided by upper layer
771 **
772 ** Returns          NFC status:
773 **                  NFCSTATUS_PENDING             - command is yet to be processed
774 **                  NFCSTATUS_INVALID_PARAMETER   - at least one parameter is invalid
775 **                  NFCSTATUS_BUSY                - read request is already in progress
776 **
777 *******************************************************************************/
phTmlNfc_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,void * pContext)778 NFCSTATUS phTmlNfc_Read(uint8_t *pBuffer, uint16_t wLength, pphTmlNfc_TransactCompletionCb_t pTmlReadComplete, void *pContext)
779 {
780     NFCSTATUS wReadStatus;
781 
782     /* Check whether TML is Initialized */
783     if (NULL != gpphTmlNfc_Context)
784     {
785         if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
786                 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete))
787         {
788             if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy)
789             {
790                 /* Setting the flag marks beginning of a Read Operation */
791                 gpphTmlNfc_Context->tReadInfo.bThreadBusy = TRUE;
792                 /* Copy the buffer, length and Callback function,
793                    This shall be utilized while invoking the Callback function in thread */
794                 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer;
795                 gpphTmlNfc_Context->tReadInfo.wLength = wLength;
796                 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
797                 gpphTmlNfc_Context->tReadInfo.pContext = pContext;
798                 wReadStatus = NFCSTATUS_PENDING;
799 
800                 /* Set event to invoke Reader Thread */
801                 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
802                 sem_post(&gpphTmlNfc_Context->rxSemaphore);
803             }
804             else
805             {
806                 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
807             }
808         }
809         else
810         {
811             wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
812         }
813     }
814     else
815     {
816         wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
817     }
818 
819     return wReadStatus;
820 }
821 
822 /*******************************************************************************
823 **
824 ** Function         phTmlNfc_ReadAbort
825 **
826 ** Description      Aborts pending read request (if any)
827 **
828 ** Parameters       None
829 **
830 ** Returns          NFC status:
831 **                  NFCSTATUS_SUCCESS                    - ongoing read operation aborted
832 **                  NFCSTATUS_INVALID_PARAMETER          - at least one parameter is invalid
833 **                  NFCSTATUS_NOT_INITIALIZED            - TML layer is not initialized
834 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR  - unable to cancel read operation
835 **
836 *******************************************************************************/
phTmlNfc_ReadAbort(void)837 NFCSTATUS phTmlNfc_ReadAbort(void)
838 {
839     NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
840     gpphTmlNfc_Context->tReadInfo.bEnable = 0;
841 
842     /*Reset the flag to accept another Read Request */
843     gpphTmlNfc_Context->tReadInfo.bThreadBusy=FALSE;
844     wStatus = NFCSTATUS_SUCCESS;
845 
846     return wStatus;
847 }
848 
849 /*******************************************************************************
850 **
851 ** Function         phTmlNfc_WriteAbort
852 **
853 ** Description      Aborts pending write request (if any)
854 **
855 ** Parameters       None
856 **
857 ** Returns          NFC status:
858 **                  NFCSTATUS_SUCCESS                    - ongoing write operation aborted
859 **                  NFCSTATUS_INVALID_PARAMETER          - at least one parameter is invalid
860 **                  NFCSTATUS_NOT_INITIALIZED            - TML layer is not initialized
861 **                  NFCSTATUS_BOARD_COMMUNICATION_ERROR  - unable to cancel write operation
862 **
863 *******************************************************************************/
phTmlNfc_WriteAbort(void)864 NFCSTATUS phTmlNfc_WriteAbort(void)
865 {
866     NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
867 
868     gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
869     /* Stop if any retransmission is in progress */
870     bCurrentRetryCount = 0;
871 
872     /* Reset the flag to accept another Write Request */
873     gpphTmlNfc_Context->tWriteInfo.bThreadBusy=FALSE;
874     wStatus = NFCSTATUS_SUCCESS;
875 
876     return wStatus;
877 }
878 
879 /*******************************************************************************
880 **
881 ** Function         phTmlNfc_IoCtl
882 **
883 ** Description      Resets device when insisted by upper layer
884 **                  Number of bytes to be read and buffer are passed by upper layer
885 **                  Enables reader thread if there are no read requests pending
886 **                  Returns successfully once read operation is completed
887 **                  Notifies upper layer using callback mechanism
888 **
889 ** Parameters       eControlCode       - control code for a specific operation
890 **
891 ** Returns          NFC status:
892 **                  NFCSTATUS_SUCCESS  - ioctl command completed successfully
893 **                  NFCSTATUS_FAILED   - ioctl command request failed
894 **
895 *******************************************************************************/
phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)896 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)
897 {
898     NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
899 
900     if (NULL == gpphTmlNfc_Context)
901     {
902         wStatus = NFCSTATUS_FAILED;
903     }
904     else
905     {
906         switch (eControlCode)
907         {
908             case phTmlNfc_e_ResetDevice:
909                 {
910                     /*Reset PN54X*/
911                     phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
912                     usleep(100 * 1000);
913                     phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
914                     usleep(100 * 1000);
915                     phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
916                     break;
917                 }
918             case phTmlNfc_e_EnableNormalMode:
919                 {
920                     /*Reset PN54X*/
921                     phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
922                     usleep(10 * 1000);
923                     phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
924                     usleep(100 * 1000);
925                     break;
926                 }
927             case phTmlNfc_e_EnableDownloadMode:
928                 {
929                     phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
930                     (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle,2);
931                     usleep(100 * 1000);
932                     break;
933                 }
934             default:
935                 {
936                     wStatus = NFCSTATUS_INVALID_PARAMETER;
937                     break;
938                 }
939         }
940     }
941 
942     return wStatus;
943 }
944 
945 /*******************************************************************************
946 **
947 ** Function         phTmlNfc_DeferredCall
948 **
949 ** Description      Posts message on upper layer thread
950 **                  upon successful read or write operation
951 **
952 ** Parameters       dwThreadId  - id of the thread posting message
953 **                  ptWorkerMsg - message to be posted
954 **
955 ** Returns          None
956 **
957 *******************************************************************************/
phTmlNfc_DeferredCall(uintptr_t dwThreadId,phLibNfc_Message_t * ptWorkerMsg)958 void phTmlNfc_DeferredCall(uintptr_t dwThreadId, phLibNfc_Message_t *ptWorkerMsg)
959 {
960     intptr_t bPostStatus;
961     UNUSED(dwThreadId);
962     /* Post message on the user thread to invoke the callback function */
963     sem_wait(&gpphTmlNfc_Context->postMsgSemaphore);
964     bPostStatus = phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId,
965             ptWorkerMsg,
966             0
967             );
968     sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
969 }
970 
971 /*******************************************************************************
972 **
973 ** Function         phTmlNfc_ReadDeferredCb
974 **
975 ** Description      Read thread call back function
976 **
977 ** Parameters       pParams - context provided by upper layer
978 **
979 ** Returns          None
980 **
981 *******************************************************************************/
phTmlNfc_ReadDeferredCb(void * pParams)982 static void phTmlNfc_ReadDeferredCb(void *pParams)
983 {
984     /* Transaction info buffer to be passed to Callback Function */
985     phTmlNfc_TransactInfo_t *pTransactionInfo = (phTmlNfc_TransactInfo_t *) pParams;
986 
987     /* Reset the flag to accept another Read Request */
988     gpphTmlNfc_Context->tReadInfo.bThreadBusy = FALSE;
989     gpphTmlNfc_Context->tReadInfo.pThread_Callback(gpphTmlNfc_Context->tReadInfo.pContext,
990             pTransactionInfo);
991 
992     return;
993 }
994 
995 /*******************************************************************************
996 **
997 ** Function         phTmlNfc_WriteDeferredCb
998 **
999 ** Description      Write thread call back function
1000 **
1001 ** Parameters       pParams - context provided by upper layer
1002 **
1003 ** Returns          None
1004 **
1005 *******************************************************************************/
phTmlNfc_WriteDeferredCb(void * pParams)1006 static void phTmlNfc_WriteDeferredCb(void *pParams)
1007 {
1008     /* Transaction info buffer to be passed to Callback Function */
1009     phTmlNfc_TransactInfo_t *pTransactionInfo = (phTmlNfc_TransactInfo_t *) pParams;
1010 
1011     /* Reset the flag to accept another Write Request */
1012     gpphTmlNfc_Context->tWriteInfo.bThreadBusy = FALSE;
1013     gpphTmlNfc_Context->tWriteInfo.pThread_Callback(gpphTmlNfc_Context->tWriteInfo.pContext,
1014             pTransactionInfo);
1015 
1016     return;
1017 }
1018 
phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)1019 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)
1020 {
1021     fragmentation_enabled = result;
1022 }
1023 
phTmlNfc_get_fragmentation_enabled()1024 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled()
1025 {
1026     return  fragmentation_enabled;
1027 }
1028