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