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