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