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