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