2 * Copyright (C) 2010 NXP Semiconductors
3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * \brief DAL Implementation for linux
22 * Project: Trusted NFC Linux Lignt
25 * $Author: Jonathan roux
36 #include <linux/ipc.h>
37 #include <cutils/log.h>
\r
38 #include <cutils/properties.h> // for property_get
\r
42 #include <semaphore.h>
43 #include <phDal4Nfc.h>
44 #include <phOsalNfc.h>
45 #include <phNfcStatus.h>
46 #include <phDal4Nfc_DeferredCall.h>
47 #include <phDal4Nfc_debug.h>
48 #include <phDal4Nfc_uart.h>
49 #include <phDal4Nfc_i2c.h>
50 #include <phDal4Nfc_link.h>
51 #include <phDal4Nfc_messageQueueLib.h>
52 #include <phDal4Nfc_message_glib.h>
58 /*-----------------------------------------------------------------------------------
60 ------------------------------------------------------------------------------------*/
61 #define DEFAULT_LINK_TYPE PN544_LINK_TYPE_I2C
63 /*-----------------------------------------------------------------------------------
65 ------------------------------------------------------------------------------------*/
66 /*structure holds members related for both read and write operations*/
67 typedef struct Dal_RdWr_st
70 pthread_t nReadThread; /* Read thread Hanlde */
71 uint8_t * pReadBuffer; /* Read local buffer */
72 uint8_t * pReadBufferTmp; /* Read local buffer (to read on I2C in once)*/
73 int nNbOfBytesToRead; /* Number of bytes to read */
74 int nNbOfBytesRead; /* Number of read bytes */
75 int nNbOfBytesReadTmp; /* Number of read bytes (to read on I2C in once)*/
76 char nReadBusy; /* Read state machine */
77 char nReadThreadAlive; /* Read state machine */
78 char nWaitingOnRead; /* Read state machine */
80 /* Read wait members */
81 uint8_t * pReadWaitBuffer; /* Read wait local Buffer */
82 int nNbOfBytesToReadWait; /* Number of bytes to read */
83 int nNbOfBytesReadWait; /* Number of read bytes */
84 char nReadWaitBusy; /* Read state machine */
85 char nWaitingOnReadWait; /* Read state machine */
86 char nCancelReadWait; /* Read state machine */
89 pthread_t nWriteThread; /* Write thread Hanlde */
90 uint8_t * pWriteBuffer; /* Write local buffer */
91 uint8_t * pTempWriteBuffer; /* Temp Write local buffer */
92 int nNbOfBytesToWrite; /* Number of bytes to write */
93 int nNbOfBytesWritten; /* Number of bytes written */
94 char nWaitingOnWrite; /* Write state machine */
95 char nWriteThreadAlive; /* Write state machine */
96 char nWriteBusy; /* Write state machine */
99 typedef void (*pphDal4Nfc_DeferFuncPointer_t) (void * );
100 typedef void * (*pphDal4Nfc_thread_handler_t) (void * pParam);
103 /*-----------------------------------------------------------------------------------
105 ------------------------------------------------------------------------------------*/
106 static phDal4Nfc_RdWr_t gReadWriteContext;
107 static phDal4Nfc_SContext_t gDalContext;
108 static pphDal4Nfc_SContext_t pgDalContext;
109 static phHal_sHwReference_t * pgDalHwContext;
110 static sem_t nfc_read_sem;
111 static int low_level_traces;
112 #ifdef USE_MQ_MESSAGE_QUEUE
113 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessage;
114 static mqd_t nDeferedCallMessageQueueId;
117 int nDeferedCallMessageQueueId = 0;
119 static phDal4Nfc_link_cbk_interface_t gLinkFunc;
120 /*-----------------------------------------------------------------------------------
122 ------------------------------------------------------------------------------------*/
123 static void phDal4Nfc_DeferredCb (void *params);
124 static NFCSTATUS phDal4Nfc_StartThreads (void);
125 static void phDal4Nfc_FillMsg (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
127 /*-----------------------------------------------------------------------------------
128 DAL API IMPLEMENTATION
129 ------------------------------------------------------------------------------------*/
131 static void refresh_low_level_traces() {
132 #ifdef LOW_LEVEL_TRACES
133 low_level_traces = 1;
138 char value[PROPERTY_VALUE_MAX];
140 property_get("ro.debuggable", value, "");
141 if (!value[0] || !atoi(value)) {
142 low_level_traces = 0; // user build, do not allow debug
146 property_get("debug.nfc.LOW_LEVEL_TRACES", value, "0");
148 low_level_traces = atoi(value);
152 low_level_traces = 0;
156 /*-----------------------------------------------------------------------------
158 FUNCTION: phDal4Nfc_Register
160 PURPOSE: DAL register function.
162 -----------------------------------------------------------------------------*/
163 NFCSTATUS phDal4Nfc_Register( phNfcIF_sReference_t *psRefer,
164 phNfcIF_sCallBack_t if_cb, void *psIFConf )
166 NFCSTATUS result = NFCSTATUS_SUCCESS;
168 if ((NULL != psRefer) &&
169 (NULL != psRefer->plower_if) &&
170 (NULL != if_cb.receive_complete) &&
171 (NULL != if_cb.send_complete)
174 /* Register the LLC functions to the upper layer */
175 psRefer->plower_if->init = phDal4Nfc_Init;
176 psRefer->plower_if->release = phDal4Nfc_Shutdown;
177 psRefer->plower_if->send = phDal4Nfc_Write;
178 psRefer->plower_if->receive = phDal4Nfc_Read;
179 psRefer->plower_if->receive_wait = phDal4Nfc_ReadWait;
180 psRefer->plower_if->transact_abort = phDal4Nfc_ReadWaitCancel;
181 psRefer->plower_if->unregister = phDal4Nfc_Unregister;
184 if (NULL != pgDalContext)
186 /* Copy the DAL context to the upper layer */
187 psRefer->plower_if->pcontext = pgDalContext;
188 /* Register the callback function from the upper layer */
189 pgDalContext->cb_if.receive_complete = if_cb.receive_complete;
190 pgDalContext->cb_if.send_complete = if_cb.send_complete;
191 pgDalContext->cb_if.notify = if_cb.notify;
192 /* Get the upper layer context */
193 pgDalContext->cb_if.pif_ctxt = if_cb.pif_ctxt;
194 /* Update the error state */
195 result = NFCSTATUS_SUCCESS;
199 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
202 else /*Input parameters invalid*/
204 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
209 /*-----------------------------------------------------------------------------
211 FUNCTION: phDal4Nfc_Unregister
213 PURPOSE: DAL unregister function.
215 -----------------------------------------------------------------------------*/
216 NFCSTATUS phDal4Nfc_Unregister(void *pContext, void *pHwRef )
218 NFCSTATUS result = NFCSTATUS_SUCCESS;
220 if ((NULL == pContext) && (NULL == pHwRef))
222 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
226 if (NULL != pgDalContext)
228 /* Register the callback function from the upper layer */
229 pgDalContext->cb_if.receive_complete = NULL;
230 pgDalContext->cb_if.send_complete = NULL ;
231 pgDalContext->cb_if.notify = NULL ;
232 /* Get the upper layer context */
233 pgDalContext->cb_if.pif_ctxt = NULL ;
238 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
244 /*-----------------------------------------------------------------------------
246 FUNCTION: phDal4Nfc_Init
248 PURPOSE: DAL Init function.
250 -----------------------------------------------------------------------------*/
251 NFCSTATUS phDal4Nfc_Init(void *pContext, void *pHwRef )
253 NFCSTATUS result = NFCSTATUS_SUCCESS;
255 // refresh_low_level_traces();
257 if ((NULL != pContext) && (NULL != pHwRef))
259 pContext = pgDalContext;
260 pgDalHwContext = (phHal_sHwReference_t *)pHwRef;
262 if ( gDalContext.hw_valid == TRUE )
264 /* The link has been opened from the application interface */
265 gLinkFunc.open_from_handle(pgDalHwContext);
267 if (!gLinkFunc.is_opened())
269 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
273 /* Clear link buffers */
279 static phDal4Nfc_sConfig_t hw_config;
280 hw_config.deviceNode = NULL;
281 result = phDal4Nfc_Config(&hw_config, pHwRef );
284 else /*Input parametrs invalid*/
286 result = NFCSTATUS_INVALID_PARAMETER;
292 /*-----------------------------------------------------------------------------
294 FUNCTION: phDal4Nfc_Shutdown
296 PURPOSE: DAL Shutdown function.
298 -----------------------------------------------------------------------------*/
300 NFCSTATUS phDal4Nfc_Shutdown( void *pContext, void *pHwRef)
302 NFCSTATUS result = NFCSTATUS_SUCCESS;
303 // void * pThreadReturn;
305 // if (pContext == NULL)
306 // return NFCSTATUS_INVALID_PARAMETER;
308 if (gDalContext.hw_valid == TRUE)
313 /* Close the message queue */
314 #ifdef USE_MQ_MESSAGE_QUEUE
315 mq_close(nDeferedCallMessageQueueId);
323 NFCSTATUS phDal4Nfc_ConfigRelease(void *pHwRef)
326 NFCSTATUS result = NFCSTATUS_SUCCESS;
327 void * pThreadReturn;
329 DAL_PRINT("phDal4Nfc_ConfigRelease ");
331 if (gDalContext.hw_valid == TRUE)
333 /* Kill the read and write threads */
334 gReadWriteContext.nReadThreadAlive = 0;
335 gReadWriteContext.nWriteThreadAlive = 0;
337 DAL_PRINT("Release Read Semaphore");
338 sem_post(&nfc_read_sem);
343 // hyogil.kim :: lock issue is found
344 pthread_kill(gReadWriteContext.nReadThread, SIGTERM);
346 if (pthread_join(gReadWriteContext.nReadThread, &pThreadReturn) != 0)
348 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
349 DAL_PRINT("phDal4Nfc_ConfigRelease KO");
352 /* Close the message queue */
353 #ifdef USE_MQ_MESSAGE_QUEUE
354 mq_close(nDeferedCallMessageQueueId);
357 /* Shutdown NFC Chip */
361 // gLinkFunc.close();
363 /* Reset the Read Writer context to NULL */
364 memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
365 /* Reset the DAL context values to NULL */
366 memset((void *)&gDalContext,0,sizeof(gDalContext));
369 sem_destroy(&nfc_read_sem);
372 gDalContext.hw_valid = FALSE;
374 DAL_DEBUG("phDal4Nfc_ConfigRelease(): %04x\n", result);
380 /*-----------------------------------------------------------------------------
382 FUNCTION: phDal4Nfc_Write
384 PURPOSE: DAL Write function.
386 -----------------------------------------------------------------------------*/
388 NFCSTATUS phDal4Nfc_Write( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
390 NFCSTATUS result = NFCSTATUS_SUCCESS;
391 static int MsgType= PHDAL4NFC_WRITE_MESSAGE;
392 int * pmsgType=&MsgType;
393 phDal4Nfc_Message_t sMsg;
394 phOsalNfc_Message_t OsalMsg;
396 if ((NULL != pContext) && (NULL != pHwRef)&&
397 (NULL != pBuffer) && (0 != length))
399 if( gDalContext.hw_valid== TRUE)
401 if((!gReadWriteContext.nWriteBusy)&&
402 (!gReadWriteContext.nWaitingOnWrite))
404 DAL_PRINT("phDal4Nfc_Write() : Temporary buffer !! \n");
405 gReadWriteContext.pTempWriteBuffer = (uint8_t*)malloc(length * sizeof(uint8_t));
406 /* Make a copy of the passed arguments */
407 memcpy(gReadWriteContext.pTempWriteBuffer,pBuffer,length);
408 DAL_DEBUG("phDal4Nfc_Write(): %d\n", length);
409 gReadWriteContext.pWriteBuffer = gReadWriteContext.pTempWriteBuffer;
410 gReadWriteContext.nNbOfBytesToWrite = length;
411 /* Change the write state so that thread can take over the write */
412 gReadWriteContext.nWriteBusy = TRUE;
413 /* Just set variable here. This is the trigger for the Write thread */
414 gReadWriteContext.nWaitingOnWrite = TRUE;
415 /* Update the error state */
416 result = NFCSTATUS_PENDING;
417 /* Send Message and perform physical write in the DefferedCallback */
418 /* read completed immediately */
419 sMsg.eMsgType= PHDAL4NFC_WRITE_MESSAGE;
420 /* Update the state */
421 phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
422 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
423 memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
424 memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
428 /* Driver is BUSY with previous Write */
429 DAL_PRINT("phDal4Nfc_Write() : Busy \n");
430 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BUSY) ;
435 /* TBD :Additional error code : NOT_INITIALISED */
436 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
439 }/*end if-Input parametrs valid-check*/
442 result = NFCSTATUS_INVALID_PARAMETER;
447 /*-----------------------------------------------------------------------------
449 FUNCTION: phDal4Nfc_Read
451 PURPOSE: DAL Read function.
453 -----------------------------------------------------------------------------*/
455 NFCSTATUS phDal4Nfc_Read( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
457 NFCSTATUS result = NFCSTATUS_SUCCESS;
459 if ((NULL != pContext) && (NULL != pHwRef)&&
460 (NULL != pBuffer) && (0 != length))
462 if ( gDalContext.hw_valid== TRUE)
464 if((!gReadWriteContext.nReadBusy)&&
465 (!gReadWriteContext.nWaitingOnRead))
467 DAL_DEBUG("*****DAl Read called length : %d\n", length);
469 /* Make a copy of the passed arguments */
470 gReadWriteContext.pReadBuffer = pBuffer;
471 gReadWriteContext.nNbOfBytesToRead = length;
472 /* Change the Read state so that thread can take over the read */
473 gReadWriteContext.nReadBusy = TRUE;
474 /* Just set variable here. This is the trigger for the Reader thread */
475 gReadWriteContext.nWaitingOnRead = TRUE;
476 /* Update the return state */
477 result = NFCSTATUS_PENDING;
478 /* unlock reader thread */
479 sem_post(&nfc_read_sem);
483 /* Driver is BUSY with prev Read */
484 DAL_PRINT("DAL BUSY\n");
485 /* Make a copy of the passed arguments */
486 gReadWriteContext.pReadBuffer = pBuffer;
487 gReadWriteContext.nNbOfBytesToRead = length;
488 result = NFCSTATUS_PENDING;
493 /* TBD :Additional error code : NOT_INITIALISED */
494 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
496 }/*end if-Input parametrs valid-check*/
499 result = NFCSTATUS_INVALID_PARAMETER;
501 DAL_DEBUG("*****DAl Read called result : %x\n", result);
506 /*-----------------------------------------------------------------------------
508 FUNCTION: phDal4Nfc_ReadWait
510 PURPOSE: DAL Read wait function.
512 -----------------------------------------------------------------------------*/
514 NFCSTATUS phDal4Nfc_ReadWait(void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
517 DAL_PRINT("phDal4Nfc_ReadWait");
520 /*-----------------------------------------------------------------------------
522 FUNCTION: phDal4Nfc_ReadWaitCancel
524 PURPOSE: Cancel the Read wait function.
526 -----------------------------------------------------------------------------*/
528 NFCSTATUS phDal4Nfc_ReadWaitCancel( void *pContext, void *pHwRef)
530 DAL_PRINT("phDal4Nfc_ReadWaitCancel");
532 /* unlock read semaphore */
533 sem_post(&nfc_read_sem);
538 /*-----------------------------------------------------------------------------
540 FUNCTION: phDal4Nfc_Config
542 PURPOSE: Configure the serial port.
544 -----------------------------------------------------------------------------*/
545 NFCSTATUS phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void **phwref)
547 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
548 // const hw_module_t* hw_module;
549 // nfc_pn544_device_t* pn544_dev;
550 uint8_t num_eeprom_settings;
551 uint8_t* eeprom_settings;
555 config->deviceNode = "/dev/pn544";
558 /* Retrieve the hw module from the Android NFC HAL */
559 ret = hw_get_module(NFC_HARDWARE_MODULE_ID, &hw_module);
561 LOGE("hw_get_module() failed");
562 return NFCSTATUS_FAILED;
564 ret = nfc_pn544_open(hw_module, &pn544_dev);
566 LOGE("Could not open pn544 hw_module");
567 return NFCSTATUS_FAILED;
569 config->deviceNode = pn544_dev->device_node;
570 if (config->deviceNode == NULL) {
571 LOGE("deviceNode NULL");
572 return NFCSTATUS_FAILED;
575 DAL_PRINT("phDal4Nfc_Config");
577 if ((config == NULL) || (phwref == NULL) || (config->nClientId == -1))
578 return NFCSTATUS_INVALID_PARAMETER;
581 /* Register the link callbacks */
582 memset(&gLinkFunc, 0, sizeof(phDal4Nfc_link_cbk_interface_t));
584 switch(PN544_LINK_TYPE_I2C)
586 case PN544_LINK_TYPE_UART:
587 case PN544_LINK_TYPE_USB:
589 DAL_PRINT("UART link Config");
590 /* Uart link interface */
591 gLinkFunc.init = phDal4Nfc_uart_initialize;
592 gLinkFunc.open_from_handle = phDal4Nfc_uart_set_open_from_handle;
593 gLinkFunc.is_opened = phDal4Nfc_uart_is_opened;
594 gLinkFunc.flush = phDal4Nfc_uart_flush;
595 gLinkFunc.close = phDal4Nfc_uart_close;
596 gLinkFunc.open_and_configure = phDal4Nfc_uart_open_and_configure;
597 gLinkFunc.read = phDal4Nfc_uart_read;
598 gLinkFunc.write = phDal4Nfc_uart_write;
599 gLinkFunc.reset = phDal4Nfc_uart_reset;
603 case PN544_LINK_TYPE_I2C:
607 DAL_PRINT("I2C link Config");
608 /* i2c link interface */
609 gLinkFunc.init = phDal4Nfc_i2c_initialize;
610 gLinkFunc.open_from_handle = phDal4Nfc_i2c_set_open_from_handle;
611 gLinkFunc.is_opened = phDal4Nfc_i2c_is_opened;
612 gLinkFunc.flush = phDal4Nfc_i2c_flush;
613 gLinkFunc.close = phDal4Nfc_i2c_close;
614 gLinkFunc.open_and_configure = phDal4Nfc_i2c_open_and_configure;
615 gLinkFunc.read = phDal4Nfc_i2c_read;
616 gLinkFunc.write = phDal4Nfc_i2c_write;
617 gLinkFunc.reset = phDal4Nfc_i2c_reset;
623 /* Shound not happen : Bad parameter */
624 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
629 gLinkFunc.init(); /* So that link interface can initialize its internal state */
630 retstatus = gLinkFunc.open_and_configure(config, phwref);
631 if (retstatus != NFCSTATUS_SUCCESS)
634 /* Iniatilize the DAL context */
635 (void)memset(&gDalContext,0,sizeof(phDal4Nfc_SContext_t));
636 pgDalContext = &gDalContext;
638 /* Reset the Reader Thread values to NULL */
639 memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
640 gReadWriteContext.nReadThreadAlive = TRUE;
641 gReadWriteContext.nWriteBusy = FALSE;
642 gReadWriteContext.nWaitingOnWrite = FALSE;
644 /* Prepare the message queue for the defered calls */
645 #ifdef USE_MQ_MESSAGE_QUEUE
646 nDeferedCallMessageQueueId = mq_open(MQ_NAME_IDENTIFIER, O_CREAT|O_RDWR, 0666, &MQ_QUEUE_ATTRIBUTES);
648 nDeferedCallMessageQueueId = config->nClientId;
651 // gDalContext.pDev = pn544_dev;
653 /* Start Read and Write Threads */
654 if(NFCSTATUS_SUCCESS != phDal4Nfc_StartThreads())
656 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
659 gDalContext.hw_valid = TRUE;
664 return NFCSTATUS_SUCCESS;
667 /*-----------------------------------------------------------------------------
669 FUNCTION: phDal4Nfc_Reset
671 PURPOSE: Reset the PN544, using the VEN pin
673 -----------------------------------------------------------------------------*/
674 NFCSTATUS phDal4Nfc_Reset(long level)
676 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
678 DAL_DEBUG("phDal4Nfc_Reset: VEN to %ld",level);
680 retstatus = gLinkFunc.reset(level);
685 /*-----------------------------------------------------------------------------
687 FUNCTION: phDal4Nfc_Download
689 PURPOSE: Put the PN544 in download mode, using the GPIO4 pin
691 -----------------------------------------------------------------------------*/
692 NFCSTATUS phDal4Nfc_Download()
694 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
696 DAL_DEBUG("phDal4Nfc_Download: GPIO4 to %d",1);
699 retstatus = phDal4Nfc_Reset(2);
706 /*-----------------------------------------------------------------------------------
707 DAL INTERNAL IMPLEMENTATION
708 ------------------------------------------------------------------------------------*/
713 * \ingroup grp_nfc_dal
715 * \brief DAL Reader thread handler
716 * This function manages the reads from the link interface. The reads are done from
717 * this thread to create the asynchronous mecanism. When calling the synchronous
718 * function phDal4Nfc_Read, the nWaitingOnRead mutex is unlocked and the read
719 * can be done. Then a client callback is called to send the result.
721 * \param[in] pArg A custom argument that can be passed to the thread (not used)
723 * \retval TRUE Thread exiting.
727 static void thread_sig_handler(int signo)
729 DAL_PRINT("Read Thread got signal for exit!!\n");
730 pthread_exit((void *)NULL);
731 DAL_PRINT("exit the read thread!!\n");
734 int phDal4Nfc_ReaderThread(void * pArg)
737 // NFCSTATUS result = NFCSTATUS_SUCCESS;
738 // uint8_t retry_cnt=0;
741 static int MsgType = PHDAL4NFC_READ_MESSAGE;
742 int *pmsgType = &MsgType;
744 phDal4Nfc_Message_t sMsg;
745 phOsalNfc_Message_t OsalMsg;
748 // pthread_setname_np(pthread_self(), "reader"); // our compiler does not support this
750 /* Create the overlapped event. Must be closed before exiting
751 to avoid a handle leak. This event is used READ API and the Reader thread*/
753 DAL_PRINT("RX Thread \n");
754 DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive);
755 DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead);
757 struct sigaction act;
758 act.sa_handler = thread_sig_handler;
759 sigaction(SIGTERM, &act, NULL);
762 sigemptyset(&newmask);
763 sigaddset(&newmask, SIGTERM);
764 pthread_sigmask(SIG_UNBLOCK, &newmask, NULL);
766 while (gReadWriteContext.nReadThreadAlive) /* Thread Loop */
768 /* Check for the read request from user */
769 DAL_PRINT("RX Thread Sem Lock\n");
771 sem_wait(&nfc_read_sem);
772 DAL_PRINT("RX Thread Sem UnLock\n");
774 /* Issue read operation.*/
775 gReadWriteContext.nNbOfBytesRead = 0;
776 DAL_DEBUG("\n*New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
777 memsetRet = memset(gReadWriteContext.pReadBuffer, 0, gReadWriteContext.nNbOfBytesToRead);
779 if (gReadWriteContext.nReadThreadAlive == 0)
781 DAL_DEBUG("Break Point 1 gReadWriteContext.nReadThreadAlive [%d]\n" , gReadWriteContext.nReadThreadAlive);
785 gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
787 DAL_DEBUG("Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
788 DAL_DEBUG("NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
789 DAL_PRINT("ReadBuff[]={ ");
791 for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
793 if(gReadWriteContext.pReadBuffer != NULL)
795 DAL_DEBUG("0x%x ", gReadWriteContext.pReadBuffer[i]);
802 /* read completed immediately */
803 sMsg.eMsgType = PHDAL4NFC_READ_MESSAGE;
804 /* Update the state */
805 phDal4Nfc_FillMsg(&sMsg, &OsalMsg);
807 if (gReadWriteContext.nReadThreadAlive == 0)
809 DAL_DEBUG("Break Point 2 gReadWriteContext.nReadThreadAlive [%d]\n" , gReadWriteContext.nReadThreadAlive);
813 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb, (void *)pmsgType);
814 memsetRet = memset(&sMsg, 0, sizeof(phDal4Nfc_Message_t));
815 memsetRet = memset(&OsalMsg, 0, sizeof(phOsalNfc_Message_t));
816 } /* End of thread Loop*/
817 DAL_PRINT("Read Thread pthread_exit!!!!\n");
818 pthread_exit((void *)NULL);
826 * \ingroup grp_nfc_dal
828 * \brief DAL Start threads function
829 * This function is called from phDal4Nfc_Config and is responsible of creating the
832 * \retval NFCSTATUS_SUCCESS If success.
833 * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes
835 NFCSTATUS phDal4Nfc_StartThreads(void)
837 // pthread_attr_t nReadThreadAttributes;
838 // pthread_attr_t nWriteThreadAttributes;
841 if(sem_init(&nfc_read_sem, 0, 0) == -1)
843 DAL_PRINT("NFC Init Semaphore creation Error");
847 ret = pthread_create(&gReadWriteContext.nReadThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread, (void*) "dal_read_thread");
849 return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
851 return NFCSTATUS_SUCCESS;
855 * \ingroup grp_nfc_dal
857 * \brief DAL fill message function
858 * Internal messages management. This function fills message structure
859 * depending on message types.
861 * \param[in, out] pDalMsg DAL message to fill
862 * \param[in, out] pOsalMsg OSAL message to fill
865 void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg)
867 if(NULL != pgDalHwContext)
869 if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE)
871 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesWritten;
872 pDalMsg->transactInfo.buffer = NULL;
873 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS;
874 pDalMsg->pHwRef = pgDalHwContext;
875 pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete;
876 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
877 pOsalMsg->pMsgData = pDalMsg;
880 else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE)
882 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesRead;
883 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer;
884 pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt;
888 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesReadWait;
889 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer;
890 pDalMsg->pContext= pgDalContext;
892 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS;
893 pDalMsg->pHwRef = pgDalHwContext;
894 pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete;
895 /*map to OSAL msg format*/
896 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
897 pOsalMsg->pMsgData = pDalMsg;
903 * \ingroup grp_nfc_dal
905 * \brief DAL deferred callback function
906 * Generic handler function called by a client thread when reading a message from the queue.
907 * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall
909 * \param[in] params Parameter that will be passed to the client function.
912 void phDal4Nfc_DeferredCb (void *params)
916 phNfc_sTransactionInfo_t TransactionInfo;
922 case PHDAL4NFC_READ_MESSAGE:
923 DAL_PRINT(" Dal deferred read called \n");
924 TransactionInfo.buffer=gReadWriteContext.pReadBuffer;
925 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead;
926 TransactionInfo.status=NFCSTATUS_SUCCESS;
927 gReadWriteContext.nReadBusy = FALSE;
930 /* Reset flag so that another opertion can be issued.*/
931 gReadWriteContext.nWaitingOnRead = FALSE;
932 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete))
934 pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt,
935 pgDalHwContext,&TransactionInfo);
939 case PHDAL4NFC_WRITE_MESSAGE:
940 DAL_PRINT(" Dal deferred write called \n");
944 phOsalNfc_PrintData("SEND", (uint16_t)gReadWriteContext.nNbOfBytesToWrite,
945 gReadWriteContext.pWriteBuffer, low_level_traces);
948 /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
949 /* Make a Physical WRITE */
950 /* NOTE: need to usleep(3000) here if the write is for SWP */
951 usleep(500); /* NXP advise 500us sleep required between I2C writes */
952 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
953 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
955 /* controller may be in standby. do it again! */
956 usleep(10000); /* wait 10 ms */
957 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
959 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
961 /* Report write failure or timeout */
962 DAL_PRINT(" Physical Write Error !!! \n");
963 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
964 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR);
968 DAL_PRINT(" Physical Write Success \n");
969 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
970 TransactionInfo.status=NFCSTATUS_SUCCESS;
971 DAL_PRINT("WriteBuff[]={ ");
972 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
974 DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
978 // Free TempWriteBuffer
979 if(gReadWriteContext.pTempWriteBuffer != NULL)
981 free(gReadWriteContext.pTempWriteBuffer);
984 /* Reset Write context */
985 gReadWriteContext.nWriteBusy = FALSE;
986 gReadWriteContext.nWaitingOnWrite = FALSE;
988 /* call LLC callback */
989 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete))
991 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt,
992 pgDalHwContext,&TransactionInfo);
1001 * \ingroup grp_nfc_dal
1003 * \brief DAL deferred call function
1004 * This function will enable to call the callback client asyncronously and in the client context.
1005 * It will post a message in a queue that will be processed by a client thread.
1007 * \param[in] func The function to call when message is read from the queue
1008 * \param[in] param Parameter that will be passed to the 'func' function.
1011 void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param)
1014 phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper;
1015 phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage;
1016 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead;
1017 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite;
1019 #ifdef USE_MQ_MESSAGE_QUEUE
1020 nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
1021 nDeferedMessage.def_call = func;
1022 nDeferedMessage.params = param;
1023 retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0);
1025 if(PHDAL4NFC_READ_MESSAGE==(* (int*)param))
1027 pDeferedMessage = &nDeferedMessageRead;
1031 pDeferedMessage = &nDeferedMessageWrite;
1033 nDeferedMessageWrapper.mtype = 1;
1034 nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
1035 pDeferedMessage->pCallback = func;
1036 pDeferedMessage->pParameter = param;
1037 nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage;
1038 nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t);
1039 #ifndef G_IDLE_ADD_MSGQ
1040 phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);
1042 PostMessage((struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);