1 /*
2 * Copyright 2010-2021 NXP
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 <phNxpConfig.h>
23 #include <phNxpLog.h>
24 #include <phNxpNciHal_utils.h>
25 #include <phOsalNfc_Timer.h>
26 #include <phTmlNfc.h>
27 #include "NfccTransportFactory.h"
28
29 /*
30 * Duration of Timer to wait after sending an Nci packet
31 */
32 #define PHTMLNFC_MAXTIME_RETRANSMIT (200U)
33 #define MAX_WRITE_RETRY_COUNT 0x03
34 #define MAX_READ_RETRY_DELAY_IN_MILLISEC (150U)
35 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1 */
36 static uint8_t bCurrentRetryCount = (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
37
38 /* Value to reset variables of TML */
39 #define PH_TMLNFC_RESET_VALUE (0x00)
40
41 /* Indicates a Initial or offset value */
42 #define PH_TMLNFC_VALUE_ONE (0x01)
43
44 #define PH_TMLNFC_WAIT_FOR_IRQ_LOW_MAX_RETRY_CNT (5)
45
46 spTransport gpTransportObj;
47
48 /* Initialize Context structure pointer used to access context structure */
49 phTmlNfc_Context_t* gpphTmlNfc_Context = NULL;
50 /* Local Function prototypes */
51 static NFCSTATUS phTmlNfc_StartThread(void);
52 static void phTmlNfc_ReadDeferredCb(void* pParams);
53 static void phTmlNfc_WriteDeferredCb(void* pParams);
54 static void* phTmlNfc_TmlThread(void* pParam);
55 static void* phTmlNfc_TmlWriterThread(void* pParam);
56 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext);
57 static NFCSTATUS phTmlNfc_InitiateTimer(void);
58 static void phTmlNfc_WaitWriteComplete(void);
59 static void phTmlNfc_SignalWriteComplete(void);
60 static int phTmlNfc_WaitReadInit(void);
61
62 /* Function definitions */
63
64 /*******************************************************************************
65 **
66 ** Function phTmlNfc_Init
67 **
68 ** Description Provides initialization of TML layer and hardware interface
69 ** Configures given hardware interface and sends handle to the
70 ** caller
71 **
72 ** Parameters pConfig - TML configuration details as provided by the upper
73 ** layer
74 **
75 ** Returns NFC status:
76 ** NFCSTATUS_SUCCESS - initialization successful
77 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
78 ** invalid
79 ** NFCSTATUS_FAILED - initialization failed (for example,
80 ** unable to open hardware interface)
81 ** NFCSTATUS_INVALID_DEVICE - device has not been opened or has
82 ** been disconnected
83 **
84 *******************************************************************************/
phTmlNfc_Init(pphTmlNfc_Config_t pConfig)85 NFCSTATUS phTmlNfc_Init(pphTmlNfc_Config_t pConfig) {
86 NFCSTATUS wInitStatus = NFCSTATUS_SUCCESS;
87
88 /* Check if TML layer is already Initialized */
89 if (NULL != gpphTmlNfc_Context) {
90 /* TML initialization is already completed */
91 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_ALREADY_INITIALISED);
92 }
93 /* Validate Input parameters */
94 else if ((NULL == pConfig) ||
95 (PH_TMLNFC_RESET_VALUE == pConfig->dwGetMsgThreadId)) {
96 /*Parameters passed to TML init are wrong */
97 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
98 } else {
99 /* Allocate memory for TML context */
100 gpphTmlNfc_Context =
101 (phTmlNfc_Context_t*)malloc(sizeof(phTmlNfc_Context_t));
102
103 if (NULL == gpphTmlNfc_Context) {
104 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
105 } else {
106 /*Configure transport layer for communication*/
107 if (NFCSTATUS_SUCCESS != phTmlNfc_ConfigTransport())
108 return NFCSTATUS_FAILED;
109 /* Initialise all the internal TML variables */
110 memset(gpphTmlNfc_Context, PH_TMLNFC_RESET_VALUE,
111 sizeof(phTmlNfc_Context_t));
112 /* Make sure that the thread runs once it is created */
113 gpphTmlNfc_Context->bThreadDone = 1;
114 /* Open the device file to which data is read/written */
115 wInitStatus = gpTransportObj->OpenAndConfigure(
116 pConfig, &(gpphTmlNfc_Context->pDevHandle));
117
118 if (NFCSTATUS_SUCCESS != wInitStatus) {
119 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_DEVICE);
120 gpphTmlNfc_Context->pDevHandle = NULL;
121 } else {
122 gpphTmlNfc_Context->platform_type =
123 gpTransportObj->GetPlatform(gpphTmlNfc_Context->pDevHandle);
124 gpphTmlNfc_Context->nfc_state = NFC_STATE_UNKNOWN;
125 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
126 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
127 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
128 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
129
130 if (0 != sem_init(&gpphTmlNfc_Context->rxSemaphore, 0, 0)) {
131 wInitStatus = NFCSTATUS_FAILED;
132 } else if (0 != phTmlNfc_WaitReadInit()) {
133 wInitStatus = NFCSTATUS_FAILED;
134 } else if (0 != sem_init(&gpphTmlNfc_Context->txSemaphore, 0, 0)) {
135 wInitStatus = NFCSTATUS_FAILED;
136 } else if (0 != sem_init(&gpphTmlNfc_Context->postMsgSemaphore, 0, 0)) {
137 wInitStatus = NFCSTATUS_FAILED;
138 } else {
139 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
140 /* Start TML thread (to handle write and read operations) */
141 if (NFCSTATUS_SUCCESS != phTmlNfc_StartThread()) {
142 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
143 } else {
144 /* Create Timer used for Retransmission of NCI packets */
145 gpphTmlNfc_Context->dwTimerId = phOsalNfc_Timer_Create();
146 if (PH_OSALNFC_TIMER_ID_INVALID != gpphTmlNfc_Context->dwTimerId) {
147 /* Store the Thread Identifier to which Message is to be posted */
148 gpphTmlNfc_Context->dwCallbackThreadId =
149 pConfig->dwGetMsgThreadId;
150 /* Enable retransmission of Nci packet & set retry count to
151 * default */
152 gpphTmlNfc_Context->eConfig = phTmlNfc_e_DisableRetrans;
153 /* Retry Count = Standby Recovery time of NFCC / Retransmission
154 * time + 1 */
155 gpphTmlNfc_Context->bRetryCount =
156 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
157 gpphTmlNfc_Context->bWriteCbInvoked = false;
158 } else {
159 wInitStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
160 }
161 }
162 }
163 }
164 }
165 }
166 /* Clean up all the TML resources if any error */
167 if (NFCSTATUS_SUCCESS != wInitStatus) {
168 /* Clear all handles and memory locations initialized during init */
169 phTmlNfc_CleanUp();
170 }
171
172 return wInitStatus;
173 }
174
175 /*******************************************************************************
176 **
177 ** Function phTmlNfc_ConfigTransport
178 **
179 ** Description Configure Transport channel based on transport type provided
180 ** in config file
181 **
182 ** Returns NFCSTATUS_SUCCESS If transport channel is configured
183 ** NFCSTATUS_FAILED If transport channel configuration failed
184 **
185 *******************************************************************************/
phTmlNfc_ConfigTransport()186 NFCSTATUS phTmlNfc_ConfigTransport() {
187 unsigned long transportType = UNKNOWN;
188 unsigned long value = 0;
189 int isfound = GetNxpNumValue(NAME_NXP_TRANSPORT, &value, sizeof(value));
190 if (isfound > 0) {
191 transportType = value;
192 }
193 gpTransportObj = transportFactory.getTransport((transportIntf)transportType);
194 if (gpTransportObj == nullptr) {
195 NXPLOG_TML_E("No Transport channel available \n");
196 return NFCSTATUS_FAILED;
197 }
198 return NFCSTATUS_SUCCESS;
199 }
200 /*******************************************************************************
201 **
202 ** Function phTmlNfc_ConfigNciPktReTx
203 **
204 ** Description Provides Enable/Disable Retransmission of NCI packets
205 ** Needed in case of Timeout between Transmission and Reception
206 ** of NCI packets. Retransmission can be enabled only if
207 ** standby mode is enabled
208 **
209 ** Parameters eConfig - values from phTmlNfc_ConfigRetrans_t
210 ** bRetryCount - Number of times Nci packets shall be
211 ** retransmitted (default = 3)
212 **
213 ** Returns None
214 **
215 *******************************************************************************/
phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration,uint8_t bRetryCounter)216 void phTmlNfc_ConfigNciPktReTx(phTmlNfc_ConfigRetrans_t eConfiguration,
217 uint8_t bRetryCounter) {
218 /* Enable/Disable Retransmission */
219
220 gpphTmlNfc_Context->eConfig = eConfiguration;
221 if (phTmlNfc_e_EnableRetrans == eConfiguration) {
222 /* Check whether Retry counter passed is valid */
223 if (0 != bRetryCounter) {
224 gpphTmlNfc_Context->bRetryCount = bRetryCounter;
225 }
226 /* Set retry counter to its default value */
227 else {
228 /* Retry Count = Standby Recovery time of NFCC / Retransmission time + 1
229 */
230 gpphTmlNfc_Context->bRetryCount =
231 (2000 / PHTMLNFC_MAXTIME_RETRANSMIT) + 1;
232 }
233 }
234
235 return;
236 }
237
238 /*******************************************************************************
239 **
240 ** Function phTmlNfc_StartThread
241 **
242 ** Description Initializes comport, reader and writer threads
243 **
244 ** Parameters None
245 **
246 ** Returns NFC status:
247 ** NFCSTATUS_SUCCESS - threads initialized successfully
248 ** NFCSTATUS_FAILED - initialization failed due to system error
249 **
250 *******************************************************************************/
phTmlNfc_StartThread(void)251 static NFCSTATUS phTmlNfc_StartThread(void) {
252 NFCSTATUS wStartStatus = NFCSTATUS_SUCCESS;
253 void* h_threadsEvent = 0x00;
254 int pthread_create_status = 0;
255
256 /* Create Reader and Writer threads */
257 pthread_create_status =
258 pthread_create(&gpphTmlNfc_Context->readerThread, NULL,
259 &phTmlNfc_TmlThread, (void*)h_threadsEvent);
260 if (0 != pthread_create_status) {
261 wStartStatus = NFCSTATUS_FAILED;
262 } else {
263 /*Start Writer Thread*/
264 pthread_create_status =
265 pthread_create(&gpphTmlNfc_Context->writerThread, NULL,
266 &phTmlNfc_TmlWriterThread, (void*)h_threadsEvent);
267 if (0 != pthread_create_status) {
268 wStartStatus = NFCSTATUS_FAILED;
269 }
270 }
271
272 return wStartStatus;
273 }
274
275 /*******************************************************************************
276 **
277 ** Function phTmlNfc_ReTxTimerCb
278 **
279 ** Description This is the timer callback function after timer expiration.
280 **
281 ** Parameters dwThreadId - id of the thread posting message
282 ** pContext - context provided by upper layer
283 **
284 ** Returns None
285 **
286 *******************************************************************************/
phTmlNfc_ReTxTimerCb(uint32_t dwTimerId,void * pContext)287 static void phTmlNfc_ReTxTimerCb(uint32_t dwTimerId, void* pContext) {
288 if ((gpphTmlNfc_Context->dwTimerId == dwTimerId) && (NULL == pContext)) {
289 /* If Retry Count has reached its limit,Retransmit Nci
290 packet */
291 if (0 == bCurrentRetryCount) {
292 /* Since the count has reached its limit,return from timer callback
293 Upper layer Timeout would have happened */
294 } else {
295 bCurrentRetryCount--;
296 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
297 gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
298 }
299 sem_post(&gpphTmlNfc_Context->txSemaphore);
300 }
301
302 return;
303 }
304
305 /*******************************************************************************
306 **
307 ** Function phTmlNfc_InitiateTimer
308 **
309 ** Description Start a timer for Tx and Rx thread.
310 **
311 ** Parameters void
312 **
313 ** Returns NFC status
314 **
315 *******************************************************************************/
phTmlNfc_InitiateTimer(void)316 static NFCSTATUS phTmlNfc_InitiateTimer(void) {
317 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
318
319 /* Start Timer once Nci packet is sent */
320 wStatus = phOsalNfc_Timer_Start(gpphTmlNfc_Context->dwTimerId,
321 (uint32_t)PHTMLNFC_MAXTIME_RETRANSMIT,
322 phTmlNfc_ReTxTimerCb, NULL);
323
324 return wStatus;
325 }
326
327 /*******************************************************************************
328 **
329 ** Function phTmlNfc_TmlThread
330 **
331 ** Description Read the data from the lower layer driver
332 **
333 ** Parameters pParam - parameters for Writer thread function
334 **
335 ** Returns None
336 **
337 *******************************************************************************/
phTmlNfc_TmlThread(void * pParam)338 static void* phTmlNfc_TmlThread(void* pParam) {
339 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
340 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
341 uint8_t temp[260];
342 uint8_t readRetryDelay = 0;
343 /* Transaction info buffer to be passed to Callback Thread */
344 static phTmlNfc_TransactInfo_t tTransactionInfo;
345 /* Structure containing Tml callback function and parameters to be invoked
346 by the callback thread */
347 static phLibNfc_DeferredCall_t tDeferredInfo;
348 /* Initialize Message structure to post message onto Callback Thread */
349 static phLibNfc_Message_t tMsg;
350 UNUSED_PROP(pParam);
351 NXPLOG_TML_D("PN54X - Tml Reader Thread Started................\n");
352
353 /* Writer thread loop shall be running till shutdown is invoked */
354 while (gpphTmlNfc_Context->bThreadDone) {
355 /* If Tml write is requested */
356 /* Set the variable to success initially */
357 wStatus = NFCSTATUS_SUCCESS;
358 if (-1 == sem_wait(&gpphTmlNfc_Context->rxSemaphore)) {
359 NXPLOG_TML_E("sem_wait didn't return success \n");
360 }
361
362 /* If Tml read is requested */
363 if (1 == gpphTmlNfc_Context->tReadInfo.bEnable) {
364 NXPLOG_TML_D("PN54X - Read requested.....\n");
365 /* Set the variable to success initially */
366 wStatus = NFCSTATUS_SUCCESS;
367
368 /* Variable to fetch the actual number of bytes read */
369 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
370
371 /* Read the data from the file onto the buffer */
372 if (NULL != gpphTmlNfc_Context->pDevHandle) {
373 NXPLOG_TML_D("PN54X - Invoking I2C Read.....\n");
374 dwNoBytesWrRd =
375 gpTransportObj->Read(gpphTmlNfc_Context->pDevHandle, temp, 260);
376
377 if (-1 == dwNoBytesWrRd) {
378 NXPLOG_TML_E("PN54X - Error in I2C Read.....\n");
379 if (readRetryDelay < MAX_READ_RETRY_DELAY_IN_MILLISEC) {
380 /*sleep for 30/60/90/120/150 msec between each read trial incase of
381 * read error*/
382 readRetryDelay += 30;
383 }
384 usleep(readRetryDelay * 1000);
385 sem_post(&gpphTmlNfc_Context->rxSemaphore);
386 } else if (dwNoBytesWrRd > 260) {
387 NXPLOG_TML_E("Numer of bytes read exceeds the limit 260.....\n");
388 readRetryDelay = 0;
389 sem_post(&gpphTmlNfc_Context->rxSemaphore);
390 } else {
391 memcpy(gpphTmlNfc_Context->tReadInfo.pBuffer, temp, dwNoBytesWrRd);
392 readRetryDelay = 0;
393
394 NXPLOG_TML_D("PN54X - I2C Read successful.....\n");
395 /* This has to be reset only after a successful read */
396 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
397 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
398 (0x00 != (gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0xE0))) {
399 NXPLOG_TML_D("PN54X - Retransmission timer stopped.....\n");
400 /* Stop Timer to prevent Retransmission */
401 uint32_t timerStatus =
402 phOsalNfc_Timer_Stop(gpphTmlNfc_Context->dwTimerId);
403 if (NFCSTATUS_SUCCESS != timerStatus) {
404 NXPLOG_TML_E("PN54X - timer stopped returned failure.....\n");
405 } else {
406 gpphTmlNfc_Context->bWriteCbInvoked = false;
407 }
408 }
409 if (gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
410 NXPLOG_TML_D("Delay Read if write thread is busy");
411 usleep(2000); /*2ms delay to give prio to write complete */
412 }
413 /* Update the actual number of bytes read including header */
414 gpphTmlNfc_Context->tReadInfo.wLength = (uint16_t)(dwNoBytesWrRd);
415 phNxpNciHal_print_packet("RECV",
416 gpphTmlNfc_Context->tReadInfo.pBuffer,
417 gpphTmlNfc_Context->tReadInfo.wLength);
418
419 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
420
421 /* Fill the Transaction info structure to be passed to Callback
422 * Function */
423 tTransactionInfo.wStatus = wStatus;
424 tTransactionInfo.pBuff = gpphTmlNfc_Context->tReadInfo.pBuffer;
425 /* Actual number of bytes read is filled in the structure */
426 tTransactionInfo.wLength = gpphTmlNfc_Context->tReadInfo.wLength;
427
428 /* Read operation completed successfully. Post a Message onto Callback
429 * Thread*/
430 /* Prepare the message to be posted on User thread */
431 tDeferredInfo.pCallback = &phTmlNfc_ReadDeferredCb;
432 tDeferredInfo.pParameter = &tTransactionInfo;
433 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
434 tMsg.pMsgData = &tDeferredInfo;
435 tMsg.Size = sizeof(tDeferredInfo);
436 /*Don't wait for posting notifications. Only wait for posting
437 * responses*/
438 /*TML reader writer callback synchronization-- START*/
439 pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
440 if ((gpphTmlNfc_Context->gWriterCbflag == false) &&
441 ((gpphTmlNfc_Context->tReadInfo.pBuffer[0] & 0x60) != 0x60)) {
442 phTmlNfc_WaitWriteComplete();
443 }
444 /*TML reader writer callback synchronization-- END*/
445 pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
446 NXPLOG_TML_D("PN54X - Posting read message.....\n");
447 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
448 }
449 } else {
450 NXPLOG_TML_D("PN54X -gpphTmlNfc_Context->pDevHandle is NULL");
451 }
452 } else {
453 NXPLOG_TML_D("PN54X - read request NOT enabled");
454 usleep(10 * 1000);
455 }
456 } /* End of While loop */
457
458 return NULL;
459 }
460
461 /*******************************************************************************
462 **
463 ** Function phTmlNfc_TmlWriterThread
464 **
465 ** Description Writes the requested data onto the lower layer driver
466 **
467 ** Parameters pParam - context provided by upper layer
468 **
469 ** Returns None
470 **
471 *******************************************************************************/
phTmlNfc_TmlWriterThread(void * pParam)472 static void* phTmlNfc_TmlWriterThread(void* pParam) {
473 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
474 int32_t dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
475 /* Transaction info buffer to be passed to Callback Thread */
476 static phTmlNfc_TransactInfo_t tTransactionInfo;
477 /* Structure containing Tml callback function and parameters to be invoked
478 by the callback thread */
479 static phLibNfc_DeferredCall_t tDeferredInfo;
480 /* Initialize Message structure to post message onto Callback Thread */
481 static phLibNfc_Message_t tMsg;
482 /* In case of I2C Write Retry */
483 static uint16_t retry_cnt;
484 UNUSED_PROP(pParam);
485 NXPLOG_TML_D("PN54X - Tml Writer Thread Started................\n");
486
487 /* Writer thread loop shall be running till shutdown is invoked */
488 while (gpphTmlNfc_Context->bThreadDone) {
489 NXPLOG_TML_D("PN54X - Tml Writer Thread Running................\n");
490 if (-1 == sem_wait(&gpphTmlNfc_Context->txSemaphore)) {
491 NXPLOG_TML_E("sem_wait didn't return success \n");
492 }
493 /* If Tml write is requested */
494 if (1 == gpphTmlNfc_Context->tWriteInfo.bEnable) {
495 NXPLOG_TML_D("PN54X - Write requested.....\n");
496 /* Set the variable to success initially */
497 wStatus = NFCSTATUS_SUCCESS;
498 if (NULL != gpphTmlNfc_Context->pDevHandle) {
499 retry:
500 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
501 /* Variable to fetch the actual number of bytes written */
502 dwNoBytesWrRd = PH_TMLNFC_RESET_VALUE;
503 /* Write the data in the buffer onto the file */
504 NXPLOG_TML_D("PN54X - Invoking I2C Write.....\n");
505 /* TML reader writer callback synchronization mutex lock --- START */
506 pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
507 gpphTmlNfc_Context->gWriterCbflag = false;
508 dwNoBytesWrRd =
509 gpTransportObj->Write(gpphTmlNfc_Context->pDevHandle,
510 gpphTmlNfc_Context->tWriteInfo.pBuffer,
511 gpphTmlNfc_Context->tWriteInfo.wLength);
512 /* TML reader writer callback synchronization mutex lock --- END */
513 pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
514
515 /* Try I2C Write Five Times, if it fails : Raju */
516 if (-1 == dwNoBytesWrRd) {
517 if (gpTransportObj->IsFwDnldModeEnabled()) {
518 if (retry_cnt++ < MAX_WRITE_RETRY_COUNT) {
519 NXPLOG_TML_D("PN54X - Error in I2C Write - Retry 0x%x",
520 retry_cnt);
521 // Add a 10 ms delay to ensure NFCC is not still in stand by mode.
522 usleep(10 * 1000);
523 goto retry;
524 }
525 }
526 NXPLOG_TML_D("PN54X - Error in I2C Write.....\n");
527 wStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_FAILED);
528 } else {
529 phNxpNciHal_print_packet("SEND",
530 gpphTmlNfc_Context->tWriteInfo.pBuffer,
531 gpphTmlNfc_Context->tWriteInfo.wLength);
532 }
533 retry_cnt = 0;
534 if (NFCSTATUS_SUCCESS == wStatus) {
535 NXPLOG_TML_D("PN54X - I2C Write successful.....\n");
536 dwNoBytesWrRd = PH_TMLNFC_VALUE_ONE;
537 }
538 /* Fill the Transaction info structure to be passed to Callback Function
539 */
540 tTransactionInfo.wStatus = wStatus;
541 tTransactionInfo.pBuff = gpphTmlNfc_Context->tWriteInfo.pBuffer;
542 /* Actual number of bytes written is filled in the structure */
543 tTransactionInfo.wLength = (uint16_t)dwNoBytesWrRd;
544
545 /* Prepare the message to be posted on the User thread */
546 tDeferredInfo.pCallback = &phTmlNfc_WriteDeferredCb;
547 tDeferredInfo.pParameter = &tTransactionInfo;
548 /* Write operation completed successfully. Post a Message onto Callback
549 * Thread*/
550 tMsg.eMsgType = PH_LIBNFC_DEFERREDCALL_MSG;
551 tMsg.pMsgData = &tDeferredInfo;
552 tMsg.Size = sizeof(tDeferredInfo);
553
554 /* Check whether Retransmission needs to be started,
555 * If yes, Post message only if
556 * case 1. Message is not posted &&
557 * case 11. Write status is success ||
558 * case 12. Last retry of write is also failure
559 */
560 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
561 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
562 if (gpphTmlNfc_Context->bWriteCbInvoked == false) {
563 if ((NFCSTATUS_SUCCESS == wStatus) || (bCurrentRetryCount == 0)) {
564 NXPLOG_TML_D("PN54X - Posting Write message.....\n");
565 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId,
566 &tMsg);
567 gpphTmlNfc_Context->bWriteCbInvoked = true;
568 }
569 }
570 } else {
571 NXPLOG_TML_D("PN54X - Posting Fresh Write message.....\n");
572 phTmlNfc_DeferredCall(gpphTmlNfc_Context->dwCallbackThreadId, &tMsg);
573 if (NFCSTATUS_SUCCESS == wStatus) {
574 /*TML reader writer thread callback synchronization---START*/
575 pthread_mutex_lock(&gpphTmlNfc_Context->wait_busy_lock);
576 gpphTmlNfc_Context->gWriterCbflag = true;
577 phTmlNfc_SignalWriteComplete();
578 /*TML reader writer thread callback synchronization---END*/
579 pthread_mutex_unlock(&gpphTmlNfc_Context->wait_busy_lock);
580 }
581 }
582 } else {
583 NXPLOG_TML_D("PN54X - gpphTmlNfc_Context->pDevHandle is NULL");
584 }
585
586 /* If Data packet is sent, then NO retransmission */
587 if ((phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) &&
588 (0x00 != (gpphTmlNfc_Context->tWriteInfo.pBuffer[0] & 0xE0))) {
589 NXPLOG_TML_D("PN54X - Starting timer for Retransmission case");
590 wStatus = phTmlNfc_InitiateTimer();
591 if (NFCSTATUS_SUCCESS != wStatus) {
592 /* Reset Variables used for Retransmission */
593 NXPLOG_TML_D("PN54X - Retransmission timer initiate failed");
594 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
595 bCurrentRetryCount = 0;
596 }
597 }
598 } else {
599 NXPLOG_TML_D("PN54X - Write request NOT enabled");
600 usleep(10000);
601 }
602
603 } /* End of While loop */
604
605 return NULL;
606 }
607
608 /*******************************************************************************
609 **
610 ** Function phTmlNfc_CleanUp
611 **
612 ** Description Clears all handles opened during TML initialization
613 **
614 ** Parameters None
615 **
616 ** Returns None
617 **
618 *******************************************************************************/
phTmlNfc_CleanUp(void)619 void phTmlNfc_CleanUp(void) {
620 if (NULL == gpphTmlNfc_Context) {
621 return;
622 }
623 if (NULL != gpphTmlNfc_Context->pDevHandle) {
624 #if (NXP_EXTNS == TRUE)
625 if (nfcFL.chipType < sn100u) {
626 #endif
627 (void)gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
628 MODE_POWER_OFF);
629 #if (NXP_EXTNS == TRUE)
630 }
631 #endif
632 gpphTmlNfc_Context->bThreadDone = 0;
633 }
634 sem_destroy(&gpphTmlNfc_Context->rxSemaphore);
635 sem_destroy(&gpphTmlNfc_Context->txSemaphore);
636 sem_destroy(&gpphTmlNfc_Context->postMsgSemaphore);
637 pthread_mutex_destroy(&gpphTmlNfc_Context->wait_busy_lock);
638 pthread_cond_destroy(&gpphTmlNfc_Context->wait_busy_condition);
639 gpTransportObj->Close(gpphTmlNfc_Context->pDevHandle);
640 gpTransportObj = NULL;
641 gpphTmlNfc_Context->pDevHandle = NULL;
642 /* Clear memory allocated for storing Context variables */
643 free((void*)gpphTmlNfc_Context);
644 /* Set the pointer to NULL to indicate De-Initialization */
645 gpphTmlNfc_Context = NULL;
646
647 return;
648 }
649
650 /*******************************************************************************
651 **
652 ** Function phTmlNfc_Shutdown
653 **
654 ** Description Uninitializes TML layer and hardware interface
655 **
656 ** Parameters None
657 **
658 ** Returns NFC status:
659 ** NFCSTATUS_SUCCESS - TML configuration released successfully
660 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
661 ** invalid
662 ** NFCSTATUS_FAILED - un-initialization failed (example: unable
663 ** to close interface)
664 **
665 *******************************************************************************/
phTmlNfc_Shutdown(void)666 NFCSTATUS phTmlNfc_Shutdown(void) {
667 NFCSTATUS wShutdownStatus = NFCSTATUS_SUCCESS;
668
669 /* Check whether TML is Initialized */
670 if (NULL != gpphTmlNfc_Context) {
671 /* Reset thread variable to terminate the thread */
672 gpphTmlNfc_Context->bThreadDone = 0;
673 usleep(1000);
674 /* Clear All the resources allocated during initialization */
675 sem_post(&gpphTmlNfc_Context->rxSemaphore);
676 usleep(1000);
677 sem_post(&gpphTmlNfc_Context->txSemaphore);
678 usleep(1000);
679 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
680 usleep(1000);
681 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
682 usleep(1000);
683 if (0 != pthread_join(gpphTmlNfc_Context->readerThread, (void**)NULL)) {
684 NXPLOG_TML_E("Fail to kill reader thread!");
685 }
686 if (0 != pthread_join(gpphTmlNfc_Context->writerThread, (void**)NULL)) {
687 NXPLOG_TML_E("Fail to kill writer thread!");
688 }
689 NXPLOG_TML_D("bThreadDone == 0");
690
691 } else {
692 wShutdownStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
693 }
694
695 return wShutdownStatus;
696 }
697
698 /*******************************************************************************
699 **
700 ** Function phTmlNfc_Write
701 **
702 ** Description Asynchronously writes given data block to hardware
703 ** interface/driver. Enables writer thread if there are no
704 ** write requests pending. Returns successfully once writer
705 ** thread completes write operation. Notifies upper layer using
706 ** callback mechanism.
707 **
708 ** NOTE:
709 ** * it is important to post a message with id
710 ** PH_TMLNFC_WRITE_MESSAGE to IntegrationThread after data
711 ** has been written to PN54X
712 ** * if CRC needs to be computed, then input buffer should be
713 ** capable to store two more bytes apart from length of
714 ** packet
715 **
716 ** Parameters pBuffer - data to be sent
717 ** wLength - length of data buffer
718 ** pTmlWriteComplete - pointer to the function to be invoked
719 ** upon completion
720 ** pContext - context provided by upper layer
721 **
722 ** Returns NFC status:
723 ** NFCSTATUS_PENDING - command is yet to be processed
724 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
725 ** invalid
726 ** NFCSTATUS_BUSY - write request is already in progress
727 **
728 *******************************************************************************/
phTmlNfc_Write(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,void * pContext)729 NFCSTATUS phTmlNfc_Write(uint8_t* pBuffer, uint16_t wLength,
730 pphTmlNfc_TransactCompletionCb_t pTmlWriteComplete,
731 void* pContext) {
732 NFCSTATUS wWriteStatus;
733
734 /* Check whether TML is Initialized */
735
736 if (NULL != gpphTmlNfc_Context) {
737 if ((NULL != gpphTmlNfc_Context->pDevHandle) && (NULL != pBuffer) &&
738 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlWriteComplete)) {
739 if (!gpphTmlNfc_Context->tWriteInfo.bThreadBusy) {
740 /* Setting the flag marks beginning of a Write Operation */
741 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = true;
742 /* Copy the buffer, length and Callback function,
743 This shall be utilized while invoking the Callback function in thread
744 */
745 gpphTmlNfc_Context->tWriteInfo.pBuffer = pBuffer;
746 gpphTmlNfc_Context->tWriteInfo.wLength = wLength;
747 gpphTmlNfc_Context->tWriteInfo.pThread_Callback = pTmlWriteComplete;
748 gpphTmlNfc_Context->tWriteInfo.pContext = pContext;
749
750 wWriteStatus = NFCSTATUS_PENDING;
751 // FIXME: If retry is going on. Stop the retry thread/timer
752 if (phTmlNfc_e_EnableRetrans == gpphTmlNfc_Context->eConfig) {
753 /* Set retry count to default value */
754 // FIXME: If the timer expired there, and meanwhile we have created
755 // a new request. The expired timer will think that retry is still
756 // ongoing.
757 bCurrentRetryCount = gpphTmlNfc_Context->bRetryCount;
758 gpphTmlNfc_Context->bWriteCbInvoked = false;
759 }
760 /* Set event to invoke Writer Thread */
761 gpphTmlNfc_Context->tWriteInfo.bEnable = 1;
762 sem_post(&gpphTmlNfc_Context->txSemaphore);
763 } else {
764 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
765 }
766 } else {
767 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
768 }
769 } else {
770 wWriteStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
771 }
772
773 return wWriteStatus;
774 }
775
776 /*******************************************************************************
777 **
778 ** Function phTmlNfc_Read
779 **
780 ** Description Asynchronously reads data from the driver
781 ** Number of bytes to be read and buffer are passed by upper
782 ** layer.
783 ** Enables reader thread if there are no read requests pending
784 ** Returns successfully once read operation is completed
785 ** Notifies upper layer using callback mechanism
786 **
787 ** Parameters pBuffer - location to send read data to the upper layer via
788 ** callback
789 ** wLength - length of read data buffer passed by upper layer
790 ** pTmlReadComplete - pointer to the function to be invoked
791 ** upon completion of read operation
792 ** pContext - context provided by upper layer
793 **
794 ** Returns NFC status:
795 ** NFCSTATUS_PENDING - command is yet to be processed
796 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
797 ** invalid
798 ** NFCSTATUS_BUSY - read request is already in progress
799 **
800 *******************************************************************************/
phTmlNfc_Read(uint8_t * pBuffer,uint16_t wLength,pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,void * pContext)801 NFCSTATUS phTmlNfc_Read(uint8_t* pBuffer, uint16_t wLength,
802 pphTmlNfc_TransactCompletionCb_t pTmlReadComplete,
803 void* pContext) {
804 NFCSTATUS wReadStatus;
805 int rxSemVal = 0, ret = 0;
806
807 /* Check whether TML is Initialized */
808 if (NULL != gpphTmlNfc_Context) {
809 if ((gpphTmlNfc_Context->pDevHandle != NULL) && (NULL != pBuffer) &&
810 (PH_TMLNFC_RESET_VALUE != wLength) && (NULL != pTmlReadComplete)) {
811 if (!gpphTmlNfc_Context->tReadInfo.bThreadBusy) {
812 /* Setting the flag marks beginning of a Read Operation */
813 gpphTmlNfc_Context->tReadInfo.bThreadBusy = true;
814 /* Copy the buffer, length and Callback function,
815 This shall be utilized while invoking the Callback function in thread
816 */
817 gpphTmlNfc_Context->tReadInfo.pBuffer = pBuffer;
818 gpphTmlNfc_Context->tReadInfo.wLength = wLength;
819 gpphTmlNfc_Context->tReadInfo.pThread_Callback = pTmlReadComplete;
820 gpphTmlNfc_Context->tReadInfo.pContext = pContext;
821 wReadStatus = NFCSTATUS_PENDING;
822
823 /* Set event to invoke Reader Thread */
824 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
825 ret = sem_getvalue(&gpphTmlNfc_Context->rxSemaphore, &rxSemVal);
826 /* Post rxSemaphore either if sem_getvalue() is failed or rxSemVal is 0
827 */
828 if (ret || !rxSemVal) {
829 sem_post(&gpphTmlNfc_Context->rxSemaphore);
830 } else {
831 NXPLOG_TML_D(
832 "%s: skip reader thread scheduling, ret=%x, rxSemaVal=%x",
833 __func__, ret, rxSemVal);
834 }
835 } else {
836 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_BUSY);
837 }
838 } else {
839 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_INVALID_PARAMETER);
840 }
841 } else {
842 wReadStatus = PHNFCSTVAL(CID_NFC_TML, NFCSTATUS_NOT_INITIALISED);
843 }
844
845 return wReadStatus;
846 }
847
848 /*******************************************************************************
849 **
850 ** Function phTmlNfc_ReadAbort
851 **
852 ** Description Aborts pending read request (if any)
853 **
854 ** Parameters None
855 **
856 ** Returns NFC status:
857 ** NFCSTATUS_SUCCESS - ongoing read operation aborted
858 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
859 ** invalid
860 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
861 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel read
862 ** operation
863 **
864 *******************************************************************************/
phTmlNfc_ReadAbort(void)865 NFCSTATUS phTmlNfc_ReadAbort(void) {
866 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
867 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
868
869 /*Reset the flag to accept another Read Request */
870 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
871 wStatus = NFCSTATUS_SUCCESS;
872
873 return wStatus;
874 }
875
876 /*******************************************************************************
877 **
878 ** Function phTmlNfc_WriteAbort
879 **
880 ** Description Aborts pending write request (if any)
881 **
882 ** Parameters None
883 **
884 ** Returns NFC status:
885 ** NFCSTATUS_SUCCESS - ongoing write operation aborted
886 ** NFCSTATUS_INVALID_PARAMETER - at least one parameter is
887 ** invalid
888 ** NFCSTATUS_NOT_INITIALIZED - TML layer is not initialized
889 ** NFCSTATUS_BOARD_COMMUNICATION_ERROR - unable to cancel write
890 ** operation
891 **
892 *******************************************************************************/
phTmlNfc_WriteAbort(void)893 NFCSTATUS phTmlNfc_WriteAbort(void) {
894 NFCSTATUS wStatus = NFCSTATUS_INVALID_PARAMETER;
895
896 gpphTmlNfc_Context->tWriteInfo.bEnable = 0;
897 /* Stop if any retransmission is in progress */
898 bCurrentRetryCount = 0;
899
900 /* Reset the flag to accept another Write Request */
901 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
902 wStatus = NFCSTATUS_SUCCESS;
903
904 return wStatus;
905 }
906
907 /*******************************************************************************
908 **
909 ** Function phTmlNfc_IoCtl
910 **
911 ** Description Resets device when insisted by upper layer
912 ** Number of bytes to be read and buffer are passed by upper
913 ** layer
914 ** Enables reader thread if there are no read requests pending
915 ** Returns successfully once read operation is completed
916 ** Notifies upper layer using callback mechanism
917 **
918 ** Parameters eControlCode - control code for a specific operation
919 **
920 ** Returns NFC status:
921 ** NFCSTATUS_SUCCESS - ioctl command completed successfully
922 ** NFCSTATUS_FAILED - ioctl command request failed
923 **
924 *******************************************************************************/
phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode)925 NFCSTATUS phTmlNfc_IoCtl(phTmlNfc_ControlCode_t eControlCode) {
926 NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
927
928 if (NULL == gpphTmlNfc_Context) {
929 wStatus = NFCSTATUS_FAILED;
930 } else {
931 switch (eControlCode) {
932 case phTmlNfc_e_PowerReset: {
933 /*VEN_RESET*/
934 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
935 MODE_POWER_RESET);
936 break;
937 }
938 case phTmlNfc_e_ResetDevice:
939
940 {
941 #if (NXP_EXTNS == TRUE)
942 if (PLATFORM_IF_I3C == gpphTmlNfc_Context->platform_type) {
943 /* TODO: Remove I3C I/F check once hot-join is enabled
944 */
945 NXPLOG_TML_D(" phTmlNfc_e_ResetDevice do nothing for i3c platfoms");
946 } else if (nfcFL.chipType < sn100u) {
947 #endif
948 /*Reset PN54X*/
949 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
950 MODE_POWER_ON);
951 usleep(100 * 1000);
952 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
953 MODE_POWER_OFF);
954 usleep(100 * 1000);
955 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
956 MODE_POWER_ON);
957 #if (NXP_EXTNS == TRUE)
958 }
959 #endif
960 break;
961 }
962 case phTmlNfc_e_EnableNormalMode: {
963 /*Reset PN54X*/
964 uint8_t read_flag = false;
965 if (gpphTmlNfc_Context->tReadInfo.bEnable) {
966 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
967 read_flag = true;
968 }
969 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
970 if (PLATFORM_IF_I3C == gpphTmlNfc_Context->platform_type) {
971 /* TODO: Remove I3C I/F check once hot-join is enabled
972 */
973 NXPLOG_TML_D(
974 " phTmlNfc_e_EnableNormalMode do nothing for i3c platfoms");
975 } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
976 NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with VEN RESET ");
977 if (nfcFL.chipType < sn100u) {
978 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
979 MODE_POWER_OFF);
980 usleep(10 * 1000);
981 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
982 MODE_POWER_ON);
983 } else {
984 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
985 MODE_FW_GPIO_LOW);
986 }
987 usleep(100 * 1000);
988 } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
989 NXPLOG_TML_D(" phTmlNfc_e_EnableNormalMode complete with NCI CMD ");
990 if (nfcFL.chipType < sn100u) {
991 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
992 MODE_POWER_ON);
993 } else {
994 gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
995 MODE_FW_GPIO_LOW);
996 }
997 }
998 if (read_flag) {
999 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
1000 sem_post(&gpphTmlNfc_Context->rxSemaphore);
1001 }
1002 break;
1003 }
1004 case phTmlNfc_e_EnableDownloadMode: {
1005 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
1006 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
1007 gpphTmlNfc_Context->nfc_state =
1008 gpTransportObj->GetNfcState(gpphTmlNfc_Context->pDevHandle);
1009 if (PLATFORM_IF_I3C == gpphTmlNfc_Context->platform_type &&
1010 gpphTmlNfc_Context->nfc_state == NFC_STATE_FW_DWL) {
1011 /* when the NFCC is already in the FW DN or teared state
1012 */
1013 NXPLOG_TML_D(
1014 " phTmlNfc_e_EnableDownloadMode do nothing, already in FW "
1015 "DN state");
1016 } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_VEN_RESET) {
1017 NXPLOG_TML_D(
1018 " phTmlNfc_e_EnableDownloadMode complete with VEN RESET ");
1019 wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
1020 MODE_FW_DWNLD_WITH_VEN);
1021 } else if (nfcFL.nfccFL._NFCC_DWNLD_MODE == NFCC_DWNLD_WITH_NCI_CMD) {
1022 NXPLOG_TML_D(" phTmlNfc_e_EnableDownloadMode complete with NCI CMD ");
1023 wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
1024 MODE_FW_DWND_HIGH);
1025 }
1026 usleep(100 * 1000);
1027 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
1028 sem_post(&gpphTmlNfc_Context->rxSemaphore);
1029 break;
1030 }
1031 case phTmlNfc_e_EnableDownloadModeWithVenRst: {
1032 phTmlNfc_ConfigNciPktReTx(phTmlNfc_e_DisableRetrans, 0);
1033 gpphTmlNfc_Context->tReadInfo.bEnable = 0;
1034 NXPLOG_TML_D(
1035 " phTmlNfc_e_EnableDownloadModewithVenRst complete with VEN "
1036 "RESET ");
1037 wStatus = gpTransportObj->NfccReset(gpphTmlNfc_Context->pDevHandle,
1038 MODE_FW_DWNLD_WITH_VEN);
1039 usleep(100 * 1000);
1040 gpphTmlNfc_Context->tReadInfo.bEnable = 1;
1041 sem_post(&gpphTmlNfc_Context->rxSemaphore);
1042 break;
1043 }
1044 default: {
1045 wStatus = NFCSTATUS_INVALID_PARAMETER;
1046 break;
1047 }
1048 }
1049 }
1050
1051 return wStatus;
1052 }
1053
1054 /*******************************************************************************
1055 **
1056 ** Function phTmlNfc_DeferredCall
1057 **
1058 ** Description Posts message on upper layer thread
1059 ** upon successful read or write operation
1060 **
1061 ** Parameters dwThreadId - id of the thread posting message
1062 ** ptWorkerMsg - message to be posted
1063 **
1064 ** Returns None
1065 **
1066 *******************************************************************************/
phTmlNfc_DeferredCall(uintptr_t dwThreadId,phLibNfc_Message_t * ptWorkerMsg)1067 void phTmlNfc_DeferredCall(uintptr_t dwThreadId,
1068 phLibNfc_Message_t* ptWorkerMsg) {
1069 intptr_t bPostStatus;
1070 UNUSED_PROP(dwThreadId);
1071 /* Post message on the user thread to invoke the callback function */
1072 if (-1 == sem_wait(&gpphTmlNfc_Context->postMsgSemaphore)) {
1073 NXPLOG_TML_E("sem_wait didn't return success \n");
1074 }
1075 bPostStatus =
1076 phDal4Nfc_msgsnd(gpphTmlNfc_Context->dwCallbackThreadId, ptWorkerMsg, 0);
1077 sem_post(&gpphTmlNfc_Context->postMsgSemaphore);
1078 }
1079
1080 /*******************************************************************************
1081 **
1082 ** Function phTmlNfc_ReadDeferredCb
1083 **
1084 ** Description Read thread call back function
1085 **
1086 ** Parameters pParams - context provided by upper layer
1087 **
1088 ** Returns None
1089 **
1090 *******************************************************************************/
phTmlNfc_ReadDeferredCb(void * pParams)1091 static void phTmlNfc_ReadDeferredCb(void* pParams) {
1092 /* Transaction info buffer to be passed to Callback Function */
1093 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1094
1095 /* Reset the flag to accept another Read Request */
1096 gpphTmlNfc_Context->tReadInfo.bThreadBusy = false;
1097 gpphTmlNfc_Context->tReadInfo.pThread_Callback(
1098 gpphTmlNfc_Context->tReadInfo.pContext, pTransactionInfo);
1099
1100 return;
1101 }
1102
1103 /*******************************************************************************
1104 **
1105 ** Function phTmlNfc_WriteDeferredCb
1106 **
1107 ** Description Write thread call back function
1108 **
1109 ** Parameters pParams - context provided by upper layer
1110 **
1111 ** Returns None
1112 **
1113 *******************************************************************************/
phTmlNfc_WriteDeferredCb(void * pParams)1114 static void phTmlNfc_WriteDeferredCb(void* pParams) {
1115 /* Transaction info buffer to be passed to Callback Function */
1116 phTmlNfc_TransactInfo_t* pTransactionInfo = (phTmlNfc_TransactInfo_t*)pParams;
1117
1118 /* Reset the flag to accept another Write Request */
1119 gpphTmlNfc_Context->tWriteInfo.bThreadBusy = false;
1120 gpphTmlNfc_Context->tWriteInfo.pThread_Callback(
1121 gpphTmlNfc_Context->tWriteInfo.pContext, pTransactionInfo);
1122
1123 return;
1124 }
1125
phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result)1126 void phTmlNfc_set_fragmentation_enabled(phTmlNfc_i2cfragmentation_t result) {
1127 fragmentation_enabled = result;
1128 }
1129
phTmlNfc_get_fragmentation_enabled()1130 phTmlNfc_i2cfragmentation_t phTmlNfc_get_fragmentation_enabled() {
1131 return fragmentation_enabled;
1132 }
1133
1134 /*******************************************************************************
1135 **
1136 ** Function phTmlNfc_WaitWriteComplete
1137 **
1138 ** Description wait function for reader thread
1139 **
1140 ** Parameters None
1141 **
1142 ** Returns None
1143 **
1144 *******************************************************************************/
phTmlNfc_WaitWriteComplete(void)1145 static void phTmlNfc_WaitWriteComplete(void) {
1146 int ret = -1;
1147 struct timespec absTimeout;
1148 if (clock_gettime(CLOCK_MONOTONIC, &absTimeout) == -1) {
1149 NXPLOG_TML_E("Reader Thread clock_gettime failed");
1150 } else {
1151 absTimeout.tv_sec += 1; /*1 second timeout*/
1152 gpphTmlNfc_Context->wait_busy_flag = true;
1153 NXPLOG_TML_D("phTmlNfc_WaitWriteComplete - enter");
1154 ret = pthread_cond_timedwait(&gpphTmlNfc_Context->wait_busy_condition,
1155 &gpphTmlNfc_Context->wait_busy_lock,
1156 &absTimeout);
1157 if ((ret != 0) && (ret != ETIMEDOUT)) {
1158 NXPLOG_TML_E("Reader Thread wait failed");
1159 }
1160 NXPLOG_TML_D("phTmlNfc_WaitWriteComplete - exit");
1161 }
1162 }
1163
1164 /*******************************************************************************
1165 **
1166 ** Function phTmlNfc_SignalWriteComplete
1167 **
1168 ** Description function to invoke reader thread
1169 **
1170 ** Parameters None
1171 **
1172 ** Returns None
1173 **
1174 *******************************************************************************/
phTmlNfc_SignalWriteComplete(void)1175 static void phTmlNfc_SignalWriteComplete(void) {
1176 int ret = -1;
1177 if (gpphTmlNfc_Context->wait_busy_flag == true) {
1178 NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - enter");
1179 gpphTmlNfc_Context->wait_busy_flag = false;
1180
1181 ret = pthread_cond_signal(&gpphTmlNfc_Context->wait_busy_condition);
1182 if (ret) {
1183 NXPLOG_TML_E(" phTmlNfc_SignalWriteComplete failed, error = 0x%X", ret);
1184 }
1185 NXPLOG_TML_D("phTmlNfc_SignalWriteComplete - exit");
1186 }
1187 }
1188
1189 /*******************************************************************************
1190 **
1191 ** Function phTmlNfc_WaitReadInit
1192 **
1193 ** Description init function for reader thread
1194 **
1195 ** Parameters None
1196 **
1197 ** Returns int
1198 **
1199 *******************************************************************************/
phTmlNfc_WaitReadInit(void)1200 static int phTmlNfc_WaitReadInit(void) {
1201 int ret = -1;
1202 pthread_condattr_t attr;
1203 pthread_condattr_init(&attr);
1204 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
1205 memset(&gpphTmlNfc_Context->wait_busy_condition, 0,
1206 sizeof(gpphTmlNfc_Context->wait_busy_condition));
1207 pthread_mutex_init(&gpphTmlNfc_Context->wait_busy_lock, NULL);
1208 ret = pthread_cond_init(&gpphTmlNfc_Context->wait_busy_condition, &attr);
1209 if (ret) {
1210 NXPLOG_TML_E(" phTphTmlNfc_WaitReadInit failed, error = 0x%X", ret);
1211 }
1212 return ret;
1213 }
1214
1215 /*******************************************************************************
1216 **
1217 ** Function phTmlNfc_EnableFwDnldMode
1218 **
1219 ** Description wrapper function for enabling/disabling FW download mode
1220 **
1221 ** Parameters True/False
1222 **
1223 ** Returns NFCSTATUS
1224 **
1225 *******************************************************************************/
phTmlNfc_EnableFwDnldMode(bool mode)1226 void phTmlNfc_EnableFwDnldMode(bool mode) {
1227 gpTransportObj->EnableFwDnldMode(mode);
1228 }
1229
1230 /*******************************************************************************
1231 **
1232 ** Function phTmlNfc_IsFwDnldModeEnabled
1233 **
1234 ** Description wrapper function to get the FW download flag
1235 **
1236 ** Parameters None
1237 **
1238 ** Returns True/False status of FW download flag
1239 **
1240 *******************************************************************************/
phTmlNfc_IsFwDnldModeEnabled(void)1241 bool phTmlNfc_IsFwDnldModeEnabled(void) {
1242 return gpTransportObj->IsFwDnldModeEnabled();
1243 }
1244
1245 /*******************************************************************************
1246 **
1247 ** Function phTmlNfc_Shutdown_CleanUp
1248 **
1249 ** Description wrapper function for shutdown and cleanup of resources
1250 **
1251 ** Parameters None
1252 **
1253 ** Returns NFCSTATUS
1254 **
1255 *******************************************************************************/
phTmlNfc_Shutdown_CleanUp()1256 NFCSTATUS phTmlNfc_Shutdown_CleanUp() {
1257 NFCSTATUS wShutdownStatus = phTmlNfc_Shutdown();
1258 phTmlNfc_CleanUp();
1259 return wShutdownStatus;
1260 }
1261
1262 /*******************************************************************************
1263 **
1264 ** Function phTmlNfc_WaitForIRQLow()
1265 **
1266 ** Description Function to be called after keeping first read pending and
1267 ** before issuing first write, to wait if IRQ line is high.
1268 ** SUCCESS if wait for IRQ line to be low is performed.
1269 ** FAILED if timeout happened and still IRQ_GPIO is high
1270 ** or ioctl failure case.
1271 **
1272 ** Parameters None
1273 **
1274 ** Returns void
1275 **
1276 *******************************************************************************/
phTmlNfc_WaitForIRQLow()1277 void phTmlNfc_WaitForIRQLow() {
1278 int irq_state = -1;
1279 int retry_cnt = 0;
1280
1281 if (NULL != gpphTmlNfc_Context) {
1282 do {
1283 irq_state = gpTransportObj->GetIrqState(gpphTmlNfc_Context->pDevHandle);
1284 if (!irq_state) {
1285 NXPLOG_NCIHAL_D("%s: No pending data", __func__);
1286 break;
1287 } else {
1288 if (irq_state > 0) {
1289 NXPLOG_NCIHAL_D("%s: waiting for IRQ to be Low", __func__);
1290 usleep(1000 * 3); /* 3ms delay to Read data on I2C bus */
1291 } else {
1292 NXPLOG_NCIHAL_E("%s: IOCTL error returned %d", __func__, irq_state);
1293 }
1294 retry_cnt++;
1295 }
1296 /* PH_TMLNFC_WAIT_FOR_IRQ_LOW_MAX_RETRY_CNT=5 --> 5*3=15ms timeout */
1297 } while (retry_cnt < PH_TMLNFC_WAIT_FOR_IRQ_LOW_MAX_RETRY_CNT);
1298 }
1299 return;
1300 }
1301