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_CleanUp(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) == -1) {
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 /* 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 pthread_mutex_lock(&gpphTmlNfc_Context->readInfoUpdateMutex);
343 memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
344
345 NXPLOG_TML_D("PN54X - I2C Read successful.....\n");
346 /* This has to be reset only after a successful read */
347 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
348 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
349 (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) {
350 NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n");
351 /* Stop Timer to prevent Retransmission */
352 uint32_t timerStatus =
353 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId);
354 if (NFCSTATUS_SUCCESS != timerStatus) {
355 NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n");
356 } else {
357 gpphTmlNfc_Context->bWriteCbInvoked = false;
358 }
359 }
360 if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
361 NXPLOG_TML_D("Delay Read if write thread is busy");
362 usleep(2000); /*2ms delay to give prio to write complete */
363 }
364 /* Update the actual number of bytes read including header */
365 gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
366 phNxpNciHal_print_packet("RECV",
367 gpphTmlNfc_Context->tReadInfo.pBuffer,
368 gpphTmlNfc_Context->tReadInfo.wLength);
369
370 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
371
372 /* Fill the Transaction info structure to be passed to Callback
373 * Function */
374 tTransactionInfo.wStatus = wStatus;
375 tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer;
376 /* Actual number of bytes read is filled in the structure */
377 tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength;
378
379 /* Read operation completed successfully. Post a Message onto Callback
380 * Thread*/
381 /* Prepare the message to be posted on User thread */
382 tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb;
383 tDeferredInfo.pParameter = &tTransactionInfo;
384 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
385 tMsg.pMsgData = &tDeferredInfo;
386 tMsg.Size = sizeof(tDeferredInfo);
387 pthread_mutex_unlock(&gpphTmlNfc_Context->readInfoUpdateMutex);
388 NXPLOG_TML_D("PN54X - Posting read message.....\n");
389 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
390 }
391 } else {
392 NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL");
393 }
394 } else {
395 NXPLOG_TML_D("PN54X - read request NOT enabled");
396 usleep(10 * 1000);
397 }
398 } /* End of While loop */
399
400 return NULL;
401 }
402
403 /*******************************************************************************
404 **
405 ** Function phTmlNfc_TmlWriterThread
406 **
407 ** Description Writes the requested data onto the lower layer driver
408 **
409 ** Parameters pParam - context provided by upper layer
410 **
411 ** Returns None
412 **
413 *******************************************************************************/
phTmlNfc_TmlWriterThread(void * pParam)414 static void * phTmlNfc_TmlWriterThread(void* pParam) {
415 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
416 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
417 /* Transaction info buffer to be passed to Callback Thread */
418 static phTmlNfc_TransactInfo_t tTransactionInfo;
419 /* Structure containing Tml callback function and parameters to be invoked
420 by the callback thread */
421 static phLibNfc_DeferredCall_t tDeferredInfo;
422 /* Initialize Message structure to post message onto Callback Thread */
423 static phLibNfc_Message_t tMsg;
424 /* In case of I2C Write Retry */
425 static uint16_t retry_cnt;
426 UNUSED(pParam);
427 NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n");
428
429 /* Writer thread loop shall be running till shutdown is invoked */
430 while (gpphTmlNfc_Context->bThreadDone) {
431 NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n");
432 sem_wait(&gpphTmlNfc_Context->txSemaphore);
433 /* If Tml write is requested */
434 if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) {
435 NXPLOG_TML_D("PN54X - Write requested.....\n");
436 /* Set the variable to success initially */
437 wStatus = NFCSTATUS_SUCCESS;
438 if (NULL != gpphTmlNfc_Context->pDevHandle) {
439 retry:
440 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
441 /* Variable to fetch the actual number of bytes written */
442 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
443 /* Write the data in the buffer onto the file */
444 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n");
445 dwNoBytesWrRd =
446 phTmlNfc_i2c_write(gpphTmlNfc_Context->pDevHandle,
447 gpphTmlNfc_Context->tWriteInfo.pBuffer,
448 gpphTmlNfc_Context->tWriteInfo.wLength);
449
450 /* Try I2C Write Five Times, if it fails : Raju */
451 if (-1 == dwNoBytesWrRd) {
452 if (getDownloadFlag() == true) {
453 if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) {
454 NXPLOG_NCIHAL_E("PN54X - Error in I2C Write - Retry 0x%x",
455 retry_cnt);
456 // Add a 10 ms delay to ensure NFCC is not still in stand by mode.
457 usleep(10 * 1000);
458 goto retry;
459 }
460 }
461 NXPLOG_TML_E("PN54X - Error in I2C Write.....\n");
462 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
463 } else {
464 phNxpNciHal_print_packet("SEND",
465 gpphTmlNfc_Context->tWriteInfo.pBuffer,
466 gpphTmlNfc_Context->tWriteInfo.wLength);
467 }
468 retry_cnt = 0;
469 if (NFCSTATUS_SUCCESS == wStatus) {
470 NXPLOG_TML_D("PN54X - I2C Write successful.....\n");
471 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
472 }
473 /* Fill the Transaction info structure to be passed to Callback Function
474 */
475 tTransactionInfo.wStatus = wStatus;
476 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
477 /* Actual number of bytes written is filled in the structure */
478 tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
479
480 /* Prepare the message to be posted on the User thread */
481 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
482 tDeferredInfo.pParameter = &tTransactionInfo;
483 /* Write operation completed successfully. Post a Message onto Callback
484 * Thread*/
485 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
486 tMsg.pMsgData = &tDeferredInfo;
487 tMsg.Size = sizeof(tDeferredInfo);
488
489 /* Check whether Retransmission needs to be started,
490 * If yes, Post message only if
491 * case 1. Message is not posted &&
492 * case 11. Write status is success ||
493 * case 12. Last retry of write is also failure
494 */
495 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
496 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
497 if (gpphTmlNfc_Context->bWriteCbInvoked == false) {
498 if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) {
499 NXPLOG_TML_D("PN54X - Posting Write message.....\n");
500 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
501 &tMsg);
502 gpphTmlNfc_Context->bWriteCbInvoked = true;
503 }
504 }
505 } else {
506 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n");
507 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
508 }
509 } else {
510 NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL");
511 }
512
513 /* If Data packet is sent, then NO retransmission */
514 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
515 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
516 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case");
517 wStatus = phTmlNfc_InitiateTimer();
518 if (NFCSTATUS_SUCCESS != wStatus) {
519 /* Reset Variables used for Retransmission */
520 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed");
521 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
522 bCurrentRetryCount = 0;
523 }
524 }
525 } else {
526 NXPLOG_TML_D("PN54X - Write request NOT enabled");
527 usleep(10000);
528 }
529
530 } /* End of While loop */
531
532 return NULL;
533 }
534
535 /*******************************************************************************
536 **
537 ** Function phTmlNfc_CleanUp
538 **
539 ** Description Clears all handles opened during TML initialization
540 **
541 ** Parameters None
542 **
543 ** Returns None
544 **
545 *******************************************************************************/
phTmlNfc_CleanUp(void)546 static void phTmlNfc_CleanUp(void) {
547 if (NULL == gpphTmlNfc_Context) {
548 return;
549 }
550 if (NULL != gpphTmlNfc_Context->pDevHandle) {
551 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
552 gpphTmlNfc_Context->bThreadDone = 0;
553 }
554 sem_destroy(&gpphTmlNfc_Context->rxSemaphore);
555 sem_destroy(&gpphTmlNfc_Context->txSemaphore);
556 sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore);
557 phTmlNfc_i2c_close(gpphTmlNfc_Context->pDevHandle);
558 gpphTmlNfc_Context->pDevHandle = NULL;
559 /* Clear memory allocated for storing Context variables */
560 free((void*)gpphTmlNfc_Context);
561 /* Set the pointer to NULL to indicate De-Initialization */
562 gpphTmlNfc_Context = NULL;
563
564 return;
565 }
566
567 /*******************************************************************************
568 **
569 ** Function phTmlNfc_Shutdown
570 **
571 ** Description Uninitializes TML layer and hardware interface
572 **
573 ** Parameters None
574 **
575 ** Returns NFC status:
576 ** NFCSTATUS_SUCCESS - TML configuration released successfully
577 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
578 ** invalid
579 ** NFCSTATUS_FAILED - un-initialization failed (example: unable
580 ** to close interface)
581 **
582 *******************************************************************************/
phTmlNfc_Shutdown(void)583 NFCSTATUS phTmlNfc_Shutdown(void) {
584 NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS;
585
586 /* Check whether TML is Initialized */
587 if (NULL != gpphTmlNfc_Context) {
588 /* Reset thread variable to terminate the thread */
589 gpphTmlNfc_Context->bThreadDone = 0;
590 usleep(1000);
591 /* Clear All the resources allocated during initialization */
592 sem_post(&gpphTmlNfc_Context->rxSemaphore);
593 usleep(1000);
594 sem_post(&gpphTmlNfc_Context->txSemaphore);
595 usleep(1000);
596 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
597 usleep(1000);
598 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
599 usleep(1000);
600 pthread_mutex_destroy(&gpphTmlNfc_Context->readInfoUpdateMutex);
601 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) {
602 NXPLOG_TML_E("Fail to kill reader thread!");
603 }
604 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) {
605 NXPLOG_TML_E("Fail to kill writer thread!");
606 }
607 NXPLOG_TML_D("bThreadDone == 0");
608
609 phTmlNfc_CleanUp();
610 } else {
611 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
612 }
613
614 return wShutdownStatus;
615 }
616
617 /*******************************************************************************
618 **
619 ** Function phTmlNfc_Write
620 **
621 ** Description Asynchronously writes given data block to hardware
622 ** interface/driver. Enables writer thread if there are no
623 ** write requests pending. Returns successfully once writer
624 ** thread completes write operation. Notifies upper layer using
625 ** callback mechanism.
626 **
627 ** NOTE:
628 ** * it is important to post a message with id
629 ** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data
630 ** has been written to PN54X
631 ** * if CRC needs to be computed, then input buffer should be
632 ** capable to store two more bytes apart from length of
633 ** packet
634 **
635 ** Parameters pBuffer - data to be sent
636 ** wLength - length of data buffer
637 ** pTmlWriteComplete - pointer to the function to be invoked
638 ** upon completion
639 ** pContext - context provided by upper layer
640 **
641 ** Returns NFC status:
642 ** NFCSTATUS_PENDING - command is yet to be processed
643 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
644 ** invalid
645 ** NFCSTATUS_BUSY - write request is already in progress
646 **
647 *******************************************************************************/
phTmlNfc_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,void * pContext)648 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength,
649 pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,
650 void* pContext) {
651 NFCSTATUS wWriteStatus;
652
653 /* Check whether TML is Initialized */
654
655 if (NULL != gpphTmlNfc_Context) {
656 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) &&
657 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
658 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
659 /* Setting the flag marks beginning of a Write Operation */
660 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
661 /* Copy the buffer, length and Callback function,
662 This shall be utilized while invoking the Callback function in thread
663 */
664 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer;
665 gpphTmlNfc_Context->tWriteInfo.wLength = wLength;
666 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
667 gpphTmlNfc_Context->tWriteInfo.pContext = pContext;
668
669 wWriteStatus = NFCSTATUS_PENDING;
670 // FIXME: If retry is going on. Stop the retry thread/timer
671 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) {
672 /* Set retry count to default value */
673 // FIXME: If the timer expired there, and meanwhile we have created
674 // a new request. The expired timer will think that retry is still
675 // ongoing.
676 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount;
677 gpphTmlNfc_Context->bWriteCbInvoked = false;
678 }
679 /* Set event to invoke Writer Thread */
680 gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
681 sem_post(&gpphTmlNfc_Context->txSemaphore);
682 } else {
683 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
684 }
685 } else {
686 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
687 }
688 } else {
689 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
690 }
691
692 return wWriteStatus;
693 }
694
695 /*******************************************************************************
696 **
697 ** Function phTmlNfc_UpdateReadCompleteCallback
698 **
699 ** Description Updates the callback to be invoked after read completed
700 **
701 ** Parameters pTmlReadComplete - pointer to the function to be invoked
702 ** upon completion of read operation
703 **
704 ** Returns NFC status:
705 ** NFCSTATUS_SUCCESS - if TmlNfc context available
706 ** NFCSTATUS_FAILED - otherwise
707 **
708 *******************************************************************************/
phTmlNfc_UpdateReadCompleteCallback(pphTmlNfc_TransactCompletionCb_t pTmlReadComplete)709 NFCSTATUS phTmlNfc_UpdateReadCompleteCallback (
710 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete) {
711 NFCSTATUS wStatus = NFCSTATUS_FAILED;
712 if ((NULL != gpphTmlNfc_Context) && (NULL != pTmlReadComplete)) {
713 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
714 wStatus = NFCSTATUS_SUCCESS;
715 }
716 return wStatus;
717 }
718
719 /*******************************************************************************
720 **
721 ** Function phTmlNfc_Read
722 **
723 ** Description Asynchronously reads data from the driver
724 ** Number of bytes to be read and buffer are passed by upper
725 ** layer.
726 ** Enables reader thread if there are no read requests pending
727 ** Returns successfully once read operation is completed
728 ** Notifies upper layer using callback mechanism
729 **
730 ** Parameters pBuffer - location to send read data to the upper layer via
731 ** callback
732 ** wLength - length of read data buffer passed by upper layer
733 ** pTmlReadComplete - pointer to the function to be invoked
734 ** upon completion of read operation
735 ** pContext - context provided by upper layer
736 **
737 ** Returns NFC status:
738 ** NFCSTATUS_PENDING - command is yet to be processed
739 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
740 ** invalid
741 ** NFCSTATUS_BUSY - read request is already in progress
742 **
743 *******************************************************************************/
phTmlNfc_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,void * pContext)744 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength,
745 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,
746 void* pContext) {
747 NFCSTATUS wReadStatus;
748
749 /* Check whether TML is Initialized */
750 if (NULL != gpphTmlNfc_Context) {
751 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
752 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) {
753 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) {
754 pthread_mutex_lock(&gpphTmlNfc_Context->readInfoUpdateMutex);
755 /* Setting the flag marks beginning of a Read Operation */
756 gpphTmlNfc_Context->tReadInfo.bThreadBusy = true;
757 /* Copy the buffer, length and Callback function,
758 This shall be utilized while invoking the Callback function in thread
759 */
760 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer;
761 gpphTmlNfc_Context->tReadInfo.wLength = wLength;
762 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
763 gpphTmlNfc_Context->tReadInfo.pContext = pContext;
764 wReadStatus = NFCSTATUS_PENDING;
765
766 /* Set event to invoke Reader Thread */
767 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
768 pthread_mutex_unlock(&gpphTmlNfc_Context->readInfoUpdateMutex);
769
770 sem_post(&gpphTmlNfc_Context->rxSemaphore);
771 } else {
772 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
773 }
774 } else {
775 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
776 }
777 } else {
778 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
779 }
780
781 return wReadStatus;
782 }
783
784 /*******************************************************************************
785 **
786 ** Function phTmlNfc_ReadAbort
787 **
788 ** Description Aborts pending read request (if any)
789 **
790 ** Parameters None
791 **
792 ** Returns NFC status:
793 ** NFCSTATUS_SUCCESS - ongoing read operation aborted
794 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
795 ** invalid
796 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
797 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read
798 ** operation
799 **
800 *******************************************************************************/
phTmlNfc_ReadAbort(void)801 NFCSTATUS phTmlNfc_ReadAbort(void) {
802 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
803 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
804
805 /*Reset the flag to accept another Read Request */
806 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
807 wStatus = NFCSTATUS_SUCCESS;
808
809 return wStatus;
810 }
811
812 /*******************************************************************************
813 **
814 ** Function phTmlNfc_WriteAbort
815 **
816 ** Description Aborts pending write request (if any)
817 **
818 ** Parameters None
819 **
820 ** Returns NFC status:
821 ** NFCSTATUS_SUCCESS - ongoing write operation aborted
822 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
823 ** invalid
824 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
825 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write
826 ** operation
827 **
828 *******************************************************************************/
phTmlNfc_WriteAbort(void)829 NFCSTATUS phTmlNfc_WriteAbort(void) {
830 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
831
832 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
833 /* Stop if any retransmission is in progress */
834 bCurrentRetryCount = 0;
835
836 /* Reset the flag to accept another Write Request */
837 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
838 wStatus = NFCSTATUS_SUCCESS;
839
840 return wStatus;
841 }
842
843 /*******************************************************************************
844 **
845 ** Function phTmlNfc_IoCtl
846 **
847 ** Description Resets device when insisted by upper layer
848 ** Number of bytes to be read and buffer are passed by upper
849 ** layer
850 ** Enables reader thread if there are no read requests pending
851 ** Returns successfully once read operation is completed
852 ** Notifies upper layer using callback mechanism
853 **
854 ** Parameters eControlCode - control code for a specific operation
855 **
856 ** Returns NFC status:
857 ** NFCSTATUS_SUCCESS - ioctl command completed successfully
858 ** NFCSTATUS_FAILED - ioctl command request failed
859 **
860 *******************************************************************************/
phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)861 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) {
862 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
863
864 if (NULL == gpphTmlNfc_Context) {
865 wStatus = NFCSTATUS_FAILED;
866 } else {
867 switch (eControlCode) {
868 case phTmlNfc_e_ResetDevice: {
869 /*Reset PN54X*/
870 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
871 usleep(100 * 1000);
872 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
873 usleep(100 * 1000);
874 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
875 break;
876 }
877 case phTmlNfc_e_EnableNormalMode: {
878 /*Reset PN54X*/
879 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 0);
880 usleep(10 * 1000);
881 phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 1);
882 usleep(100 * 1000);
883 break;
884 }
885 case phTmlNfc_e_EnableDownloadMode: {
886 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
887 (void)phTmlNfc_i2c_reset(gpphTmlNfc_Context->pDevHandle, 2);
888 usleep(100 * 1000);
889 break;
890 }
891 default: {
892 wStatus = NFCSTATUS_INVALID_PARAMETER;
893 break;
894 }
895 }
896 }
897
898 return wStatus;
899 }
900
901 /*******************************************************************************
902 **
903 ** Function phTmlNfc_DeferredCall
904 **
905 ** Description Posts message on upper layer thread
906 ** upon successful read or write operation
907 **
908 ** Parameters dwThreadId - id of the thread posting message
909 ** ptWorkerMsg - message to be posted
910 **
911 ** Returns None
912 **
913 *******************************************************************************/
phTmlNfc_DeferredCall(uintptr_t dwThreadId,phLibNfc_Message_t * ptWorkerMsg)914 void phTmlNfc_DeferredCall(uintptr_t dwThreadId,
915 phLibNfc_Message_t* ptWorkerMsg) {
916 intptr_t bPostStatus;
917 UNUSED(dwThreadId);
918 /* Post message on the user thread to invoke the callback function */
919 sem_wait(&gpphTmlNfc_Context->postMsgSemaphore);
920 bPostStatus =
921 phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0);
922 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
923 }
924
925 /*******************************************************************************
926 **
927 ** Function phTmlNfc_ReadDeferredCb
928 **
929 ** Description Read thread call back function
930 **
931 ** Parameters pParams - context provided by upper layer
932 **
933 ** Returns None
934 **
935 *******************************************************************************/
phTmlNfc_ReadDeferredCb(void * pParams)936 static void phTmlNfc_ReadDeferredCb(void* pParams) {
937 /* Transaction info buffer to be passed to Callback Function */
938 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
939
940 /* Reset the flag to accept another Read Request */
941 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
942 gpphTmlNfc_Context->tReadInfo.pThread_Callback(
943 gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo);
944
945 return;
946 }
947
948 /*******************************************************************************
949 **
950 ** Function phTmlNfc_WriteDeferredCb
951 **
952 ** Description Write thread call back function
953 **
954 ** Parameters pParams - context provided by upper layer
955 **
956 ** Returns None
957 **
958 *******************************************************************************/
phTmlNfc_WriteDeferredCb(void * pParams)959 static void phTmlNfc_WriteDeferredCb(void* pParams) {
960 /* Transaction info buffer to be passed to Callback Function */
961 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
962
963 /* Reset the flag to accept another Write Request */
964 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
965 gpphTmlNfc_Context->tWriteInfo.pThread_Callback(
966 gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo);
967
968 return;
969 }
970
phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)971 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) {
972 fragmentation_enabled = result;
973 }
974
phTmlNfc_get_fragmentation_enabled()975 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() {
976 return fragmentation_enabled;
977 }
978