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