summaryrefslogtreecommitdiffstats
path: root/Linux_x86/phDal4Nfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Linux_x86/phDal4Nfc.c')
-rw-r--r--Linux_x86/phDal4Nfc.c1116
1 files changed, 1116 insertions, 0 deletions
diff --git a/Linux_x86/phDal4Nfc.c b/Linux_x86/phDal4Nfc.c
new file mode 100644
index 0000000..7683c39
--- /dev/null
+++ b/Linux_x86/phDal4Nfc.c
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file phDalNfc.c
+ * \brief DAL Implementation for linux
+ *
+ * Project: Trusted NFC Linux Lignt
+ *
+ * $Date: 07 aug 2009
+ * $Author: Jonathan roux
+ * $Revision: 1.0 $
+ *
+ */
+
+#define _DAL_4_NFC_C
+
+#include <unistd.h>
+#include <pthread.h>
+#ifdef ANDROID
+#include <linux/ipc.h>
+#else
+#include <sys/msg.h>
+#endif
+
+#include <phDal4Nfc.h>
+#include <phOsalNfc.h>
+#include <phNfcStatus.h>
+#include <phDal4Nfc_DeferredCall.h>
+#include <phDal4Nfc_debug.h>
+#include <phDal4Nfc_uart.h>
+#include <phDal4Nfc_i2c.h>
+#include <phDal4Nfc_link.h>
+#include <phDal4Nfc_messageQueueLib.h>
+
+/*-----------------------------------------------------------------------------------
+ MISC DEFINITIONS
+------------------------------------------------------------------------------------*/
+#define DEFAULT_LINK_TYPE ENUM_DAL_LINK_TYPE_COM1
+
+/*-----------------------------------------------------------------------------------
+ TYPES
+------------------------------------------------------------------------------------*/
+/*structure holds members related for both read and write operations*/
+typedef struct Dal_RdWr_st
+{
+ /* Read members */
+ pthread_t nReadThread; /* Read thread Hanlde */
+ pthread_mutex_t nReadEventMutex; /* Mutex to signal a read has been requested */
+ uint8_t * pReadBuffer; /* Read local buffer */
+ int nNbOfBytesToRead; /* Number of bytes to read */
+ int nNbOfBytesRead; /* Number of read bytes */
+ char nReadBusy; /* Read state machine */
+ char nReadThreadAlive; /* Read state machine */
+ char nWaitingOnRead; /* Read state machine */
+
+ /* Read wait members */
+ pthread_mutex_t nReadCancelEventMutex; /* Mutex to signal a read cancel has been requested */
+ uint8_t * pReadWaitBuffer; /* Read wait local Buffer */
+ int nNbOfBytesToReadWait; /* Number of bytes to read */
+ int nNbOfBytesReadWait; /* Number of read bytes */
+ char nReadWaitBusy; /* Read state machine */
+ char nWaitingOnReadWait; /* Read state machine */
+ char nCancelReadWait; /* Read state machine */
+
+ /* Write members */
+ pthread_t nWriteThread; /* Write thread Hanlde */
+ pthread_mutex_t nWriteEventMutex; /* Mutex to signal a write has been requested */
+ uint8_t * pWriteBuffer; /* Write local buffer */
+ int nNbOfBytesToWrite; /* Number of bytes to write */
+ int nNbOfBytesWritten; /* Number of bytes written */
+ char nWaitingOnWrite; /* Write state machine */
+ char nWriteThreadAlive; /* Write state machine */
+ char nWriteBusy; /* Write state machine */
+} phDal4Nfc_RdWr_t;
+
+typedef void (*pphDal4Nfc_DeferFuncPointer_t) (void * );
+typedef void * (*pphDal4Nfc_thread_handler_t) (void * pParam);
+
+
+/*-----------------------------------------------------------------------------------
+ VARIABLES
+------------------------------------------------------------------------------------*/
+static phDal4Nfc_RdWr_t gReadWriteContext;
+static phDal4Nfc_SContext_t gDalContext;
+static pphDal4Nfc_SContext_t pgDalContext;
+static phHal_sHwReference_t * pgDalHwContext;
+static pthread_mutex_t nCriticalSectionMutex;
+static pthread_mutex_t nThreadsEventMutex;
+#ifdef USE_MQ_MESSAGE_QUEUE
+static phDal4Nfc_DeferredCall_Msg_t nDeferedMessage;
+static mqd_t nDeferedCallMessageQueueId;
+
+#else
+int nDeferedCallMessageQueueId = 0;
+#endif
+static phDal4Nfc_link_cbk_interface_t gLinkFunc;
+/*-----------------------------------------------------------------------------------
+ PROTOTYPES
+------------------------------------------------------------------------------------*/
+static void phDal4Nfc_DeferredCb (void *params);
+static NFCSTATUS phDal4Nfc_StartThreads (void);
+static void phDal4Nfc_FillMsg (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
+
+/*-----------------------------------------------------------------------------------
+ DAL API IMPLEMENTATION
+------------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Register
+
+PURPOSE: DAL register function.
+
+-----------------------------------------------------------------------------*/
+NFCSTATUS phDal4Nfc_Register( phNfcIF_sReference_t *psRefer,
+ phNfcIF_sCallBack_t if_cb, void *psIFConf )
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+
+ if ((NULL != psRefer) &&
+ (NULL != psRefer->plower_if) &&
+ (NULL != if_cb.receive_complete) &&
+ (NULL != if_cb.send_complete)
+ )
+ {
+ /* Register the LLC functions to the upper layer */
+ psRefer->plower_if->init = phDal4Nfc_Init;
+ psRefer->plower_if->release = phDal4Nfc_Shutdown;
+ psRefer->plower_if->send = phDal4Nfc_Write;
+ psRefer->plower_if->receive = phDal4Nfc_Read;
+ psRefer->plower_if->receive_wait = phDal4Nfc_ReadWait;
+ psRefer->plower_if->transact_abort = phDal4Nfc_ReadWaitCancel;
+ psRefer->plower_if->unregister = phDal4Nfc_Unregister;
+
+
+ if (NULL != pgDalContext)
+ {
+ /* Copy the DAL context to the upper layer */
+ psRefer->plower_if->pcontext = pgDalContext;
+ /* Register the callback function from the upper layer */
+ pgDalContext->cb_if.receive_complete = if_cb.receive_complete;
+ pgDalContext->cb_if.send_complete = if_cb.send_complete;
+ pgDalContext->cb_if.notify = if_cb.notify;
+ /* Get the upper layer context */
+ pgDalContext->cb_if.pif_ctxt = if_cb.pif_ctxt;
+ /* Update the error state */
+ result = NFCSTATUS_SUCCESS;
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
+ }
+ }
+ else /*Input parameters invalid*/
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Unregister
+
+PURPOSE: DAL unregister function.
+
+-----------------------------------------------------------------------------*/
+NFCSTATUS phDal4Nfc_Unregister(void *pContext, void *pHwRef )
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+
+ if ((NULL == pContext) && (NULL == pHwRef))
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+ else
+ {
+ if (NULL != pgDalContext)
+ {
+ /* Register the callback function from the upper layer */
+ pgDalContext->cb_if.receive_complete = NULL;
+ pgDalContext->cb_if.send_complete = NULL ;
+ pgDalContext->cb_if.notify = NULL ;
+ /* Get the upper layer context */
+ pgDalContext->cb_if.pif_ctxt = NULL ;
+// pgDalContext = NULL;
+
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
+ }
+ }
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Init
+
+PURPOSE: DAL Init function.
+
+-----------------------------------------------------------------------------*/
+NFCSTATUS phDal4Nfc_Init(void *pContext, void *pHwRef )
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+
+ if ((NULL != pContext) && (NULL != pHwRef))
+ {
+ pContext = pgDalContext;
+ pgDalHwContext = (phHal_sHwReference_t *)pHwRef;
+
+ if ( gDalContext.hw_valid == TRUE )
+ {
+ /* The link has been opened from the application interface */
+ gLinkFunc.open_from_handle(pgDalHwContext);
+
+ if (!gLinkFunc.is_opened())
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
+ }
+ else
+ {
+ /* Clear link buffers */
+ gLinkFunc.flush();
+ }
+ }
+ else
+ {
+ static phDal4Nfc_sConfig_t hw_config;
+ hw_config.nLinkType = DEFAULT_LINK_TYPE;
+ result = phDal4Nfc_Config(&hw_config, pHwRef );
+ }
+ }
+ else /*Input parametrs invalid*/
+ {
+ result = NFCSTATUS_INVALID_PARAMETER;
+ }
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Shutdown
+
+PURPOSE: DAL Shutdown function.
+
+-----------------------------------------------------------------------------*/
+
+NFCSTATUS phDal4Nfc_Shutdown( void *pContext, void *pHwRef)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ void * pThreadReturn;
+
+// if (pContext == NULL)
+// return NFCSTATUS_INVALID_PARAMETER;
+
+ if (gDalContext.hw_valid == TRUE)
+ {
+ /* Flush the link */
+ gLinkFunc.flush();
+
+ /* Kill the read and write threads */
+// gReadWriteContext.nReadThreadAlive = 0;
+// gReadWriteContext.nWriteThreadAlive = 0;
+// pthread_mutex_unlock(&gReadWriteContext.nReadEventMutex);
+// pthread_mutex_unlock(&gReadWriteContext.nWriteEventMutex);
+// if (pthread_join(gReadWriteContext.nReadThread, &pThreadReturn) != 0)
+// {
+// result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
+// }
+// if (pthread_join(gReadWriteContext.nWriteThread, &pThreadReturn) != 0)
+// {
+// result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
+// }
+
+ /* Close the message queue */
+#ifdef USE_MQ_MESSAGE_QUEUE
+ mq_close(nDeferedCallMessageQueueId);
+#endif
+
+ /* Destroy the mutexes */
+// pthread_mutex_destroy(&gReadWriteContext.nReadEventMutex);
+// pthread_mutex_destroy(&gReadWriteContext.nReadCancelEventMutex);
+// pthread_mutex_destroy(&gReadWriteContext.nWriteEventMutex);
+// pthread_mutex_destroy(&nCriticalSectionMutex);
+// pthread_mutex_destroy(&nThreadsEventMutex);
+
+ /* Close the link */
+// gLinkFunc.close();
+
+ /* Reset the Writer Thread values to NULL */
+// memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
+ /* Reset the DAL context values to NULL */
+// memset((void *)&gDalContext,0,sizeof(gDalContext));
+ }
+
+// gDalContext.hw_valid = FALSE;
+
+ return result;
+}
+
+NFCSTATUS phDal4Nfc_ConfigRelease( void *pHwRef)
+{
+
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ void * pThreadReturn;
+
+ if (gDalContext.hw_valid == TRUE)
+ {
+ /* Flush the link */
+ gLinkFunc.flush();
+
+ /* Kill the read and write threads */
+ gReadWriteContext.nReadThreadAlive = 0;
+ gReadWriteContext.nWriteThreadAlive = 0;
+ pthread_mutex_unlock(&gReadWriteContext.nReadEventMutex);
+ pthread_mutex_unlock(&gReadWriteContext.nWriteEventMutex);
+ if (pthread_join(gReadWriteContext.nReadThread, &pThreadReturn) != 0)
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
+ DAL_PRINT("phDal4Nfc_ConfigRelease KO");
+ }
+ if (pthread_join(gReadWriteContext.nWriteThread, &pThreadReturn) != 0)
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
+ DAL_PRINT("phDal4Nfc_ConfigRelease KO");
+ }
+
+ /* Close the message queue */
+#ifdef USE_MQ_MESSAGE_QUEUE
+ mq_close(nDeferedCallMessageQueueId);
+#endif
+
+ /* Destroy the mutexes */
+ pthread_mutex_destroy(&gReadWriteContext.nReadEventMutex);
+ pthread_mutex_destroy(&gReadWriteContext.nReadCancelEventMutex);
+ pthread_mutex_destroy(&gReadWriteContext.nWriteEventMutex);
+ pthread_mutex_destroy(&nCriticalSectionMutex);
+ pthread_mutex_destroy(&nThreadsEventMutex);
+
+ /* Close the link */
+ gLinkFunc.close();
+
+ /* Reset the Writer Thread values to NULL */
+ memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
+ /* Reset the DAL context values to NULL */
+ memset((void *)&gDalContext,0,sizeof(gDalContext));
+ }
+
+ gDalContext.hw_valid = FALSE;
+
+ DAL_DEBUG("phDal4Nfc_ConfigRelease(): %04x\n", result);
+
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Write
+
+PURPOSE: DAL Write function.
+
+-----------------------------------------------------------------------------*/
+NFCSTATUS phDal4Nfc_Write( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ if ((NULL != pContext) && (NULL != pHwRef)&&
+ (NULL != pBuffer) && (0 != length))
+ {
+ if( gDalContext.hw_valid== TRUE)
+ {
+ if((!gReadWriteContext.nWriteBusy)&&
+ (!gReadWriteContext.nWaitingOnWrite))
+ {
+ DAL_DEBUG("phDal4Nfc_Write(): %d\n", length);
+ /* Make a copy of the passed arguments */
+ gReadWriteContext.pWriteBuffer = pBuffer;
+ gReadWriteContext.nNbOfBytesToWrite = length;
+ /* Change the write state so that thread can take over the write */
+ gReadWriteContext.nWriteBusy = TRUE;
+ /* Just set variable here. This is the trigger for the Write thread */
+ gReadWriteContext.nWaitingOnWrite = TRUE;
+ /* Update the error state */
+ result = NFCSTATUS_PENDING;
+ pthread_mutex_unlock(&gReadWriteContext.nWriteEventMutex);
+ }
+ else
+ {
+ /* Driver is BUSY with previous Write */
+ DAL_PRINT("phDal4Nfc_Write() : Busy \n");
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BUSY) ;
+ }
+ }
+ else
+ {
+ /* TBD :Additional error code : NOT_INITIALISED */
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
+ }
+
+ }/*end if-Input parametrs valid-check*/
+ else
+ {
+ result = NFCSTATUS_INVALID_PARAMETER;
+ }
+ return result;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Read
+
+PURPOSE: DAL Read function.
+
+-----------------------------------------------------------------------------*/
+
+NFCSTATUS phDal4Nfc_Read( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+
+ if ((NULL != pContext) && (NULL != pHwRef)&&
+ (NULL != pBuffer) && (0 != length))
+ {
+ if ( gDalContext.hw_valid== TRUE)
+ {
+ if((!gReadWriteContext.nReadBusy)&&
+ (!gReadWriteContext.nWaitingOnRead))
+ {
+ DAL_DEBUG("*****DAl Read called length : %d\n", length);
+ /* Make a copy of the passed arguments */
+ gReadWriteContext.pReadBuffer = pBuffer;
+ gReadWriteContext.nNbOfBytesToRead = length;
+ /* Change the Read state so that thread can take over the read */
+ gReadWriteContext.nReadBusy = TRUE;
+ /* Just set variable here. This is the trigger for the Reader thread */
+ gReadWriteContext.nWaitingOnRead = TRUE;
+ // retval = ResetEvent(gReadWriteContext.nReadCancelEventMutex); /* TO DO */
+ /* Update the erro state */
+ result = NFCSTATUS_PENDING;
+ pthread_mutex_unlock(&gReadWriteContext.nReadEventMutex);
+ }
+ else
+ {
+ /* Driver is BUSY with prev Read */
+ DAL_PRINT("DAL BUSY\n");
+ /* Make a copy of the passed arguments */
+ gReadWriteContext.pReadBuffer = pBuffer;
+ gReadWriteContext.nNbOfBytesToRead = length;
+ result = NFCSTATUS_PENDING;
+ pthread_mutex_unlock(&gReadWriteContext.nReadEventMutex);
+ }
+ }
+ else
+ {
+ /* TBD :Additional error code : NOT_INITIALISED */
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
+ }
+ }/*end if-Input parametrs valid-check*/
+ else
+ {
+ result = NFCSTATUS_INVALID_PARAMETER;
+ }
+ DAL_DEBUG("*****DAl Read called result : %x\n", result);
+ return result;
+}
+
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_ReadWait
+
+PURPOSE: DAL Read wait function.
+
+-----------------------------------------------------------------------------*/
+
+NFCSTATUS phDal4Nfc_ReadWait(void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ if ((NULL != pContext) && (NULL != pHwRef)&&
+ (NULL != pBuffer) && (0 != length))
+ {
+ if ( gDalContext.hw_valid== TRUE)
+ {
+ if((!gReadWriteContext.nReadBusy)&&
+ (!gReadWriteContext.nReadWaitBusy)&&
+ (!gReadWriteContext.nWaitingOnRead))
+ {
+ /* Save the copy of passed arguments */
+ gReadWriteContext.pReadWaitBuffer = pBuffer;
+ gReadWriteContext.nNbOfBytesToReadWait = length;
+ /* Change the Read state so that thread can take over the read */
+ gReadWriteContext.nReadWaitBusy = TRUE;
+ /* Just set variable here. This is the trigger for the Reader thread */
+ gReadWriteContext.nWaitingOnReadWait = TRUE;
+ /* Update the error state */
+ result = NFCSTATUS_SUCCESS;
+ }
+ else
+ {
+ /* Driver is BUSY with prev Read */
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BUSY);
+ }
+ }
+ else
+ {
+ /* TBD :Additional error code : NOT_INITIALISED */
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
+ }
+ }/*end if -Input parametrs valid-check*/
+ else
+ {
+ result = NFCSTATUS_INVALID_PARAMETER;
+ }
+ return result;
+}
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_ReadWaitCancel
+
+PURPOSE: Cancel the Read wait function.
+
+-----------------------------------------------------------------------------*/
+
+NFCSTATUS phDal4Nfc_ReadWaitCancel( void *pContext, void *pHwRef)
+{
+#if 0
+ char retval;
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ DAL_PRINT("DAl Read cancel called \n");
+ if ((NULL != pContext) && (NULL != pHwRef))
+ {
+ if ( gDalContext.hw_valid== TRUE)
+ {
+ /* Clear The Comm Port Event */
+ if (!SetCommMask(h_serial_port, 0x0000))
+ {
+ /* Windows Error */
+ result = NFCSTATUS_BOARD_COMMUNICATION_ERROR;
+ }
+ /* Cancel the Wait read */
+ retval = SetEvent(gReadWriteContext.nReadCancelEventMutex);
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
+ }
+ }
+ else
+ {
+ result = NFCSTATUS_INVALID_PARAMETER;
+ }
+ return result;
+#endif
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+
+FUNCTION: phDal4Nfc_Config
+
+PURPOSE: Configure the serial port.
+
+-----------------------------------------------------------------------------*/
+NFCSTATUS phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void **phwref)
+{
+ NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
+
+ DAL_PRINT("phDal4Nfc_Config");
+
+ if ((config == NULL) || (phwref == NULL) || (config->nClientId == -1))
+ return NFCSTATUS_INVALID_PARAMETER;
+
+ /* Register the link callbacks */
+ memset(&gLinkFunc, 0, sizeof(phDal4Nfc_link_cbk_interface_t));
+ switch(config->nLinkType)
+ {
+ case ENUM_DAL_LINK_TYPE_COM1:
+ case ENUM_DAL_LINK_TYPE_COM2:
+ case ENUM_DAL_LINK_TYPE_COM3:
+ case ENUM_DAL_LINK_TYPE_COM4:
+ case ENUM_DAL_LINK_TYPE_COM5:
+ case ENUM_DAL_LINK_TYPE_USB:
+ {
+ /* Uart link interface */
+ gLinkFunc.init = phDal4Nfc_uart_initialize;
+ gLinkFunc.open_from_handle = phDal4Nfc_uart_set_open_from_handle;
+ gLinkFunc.is_opened = phDal4Nfc_uart_is_opened;
+ gLinkFunc.flush = phDal4Nfc_uart_flush;
+ gLinkFunc.close = phDal4Nfc_uart_close;
+ gLinkFunc.open_and_configure = phDal4Nfc_uart_open_and_configure;
+ gLinkFunc.read = phDal4Nfc_uart_read;
+ gLinkFunc.write = phDal4Nfc_uart_write;
+ }
+ break;
+
+ case ENUM_DAL_LINK_TYPE_I2C:
+ {
+ /* Uart link interface */
+ gLinkFunc.init = phDal4Nfc_i2c_initialize;
+ gLinkFunc.open_from_handle = phDal4Nfc_i2c_set_open_from_handle;
+ gLinkFunc.is_opened = phDal4Nfc_i2c_is_opened;
+ gLinkFunc.flush = phDal4Nfc_i2c_flush;
+ gLinkFunc.close = phDal4Nfc_i2c_close;
+ gLinkFunc.open_and_configure = phDal4Nfc_i2c_open_and_configure;
+ gLinkFunc.read = phDal4Nfc_i2c_read;
+ gLinkFunc.write = phDal4Nfc_i2c_write;
+ break;
+ }
+
+ default:
+ {
+ /* Shound not happen : Bad parameter */
+ return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
+ }
+ }
+
+ gLinkFunc.init(); /* So that link interface can initialize its internal state */
+ retstatus = gLinkFunc.open_and_configure(config, phwref);
+ if (retstatus != NFCSTATUS_SUCCESS)
+ return retstatus;
+
+ /* Iniatilize the DAL context */
+ (void)memset(&gDalContext,0,sizeof(phDal4Nfc_SContext_t));
+ pgDalContext = &gDalContext;
+
+ /* Reset the Writer Thread values to NULL */
+ memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
+ gReadWriteContext.nReadThreadAlive = TRUE;
+ gReadWriteContext.nWriteThreadAlive = TRUE;
+
+ /* Reset the Reader Thread values to NULL */
+ memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
+ gReadWriteContext.nReadThreadAlive = TRUE;
+ gReadWriteContext.nWriteThreadAlive = TRUE;
+
+ pthread_mutex_init (&gReadWriteContext.nReadEventMutex, NULL);
+ pthread_mutex_init (&gReadWriteContext.nReadCancelEventMutex, NULL);
+ pthread_mutex_init (&gReadWriteContext.nWriteEventMutex, NULL);
+
+ /* Prepare the message queue for the defered calls */
+#ifdef USE_MQ_MESSAGE_QUEUE
+ nDeferedCallMessageQueueId = mq_open(MQ_NAME_IDENTIFIER, O_CREAT|O_RDWR, 0666, &MQ_QUEUE_ATTRIBUTES);
+#else
+ nDeferedCallMessageQueueId = config->nClientId;
+#endif
+ /* Start Read and Write Threads */
+ if(NFCSTATUS_SUCCESS != phDal4Nfc_StartThreads())
+ {
+ return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
+ }
+
+ gDalContext.hw_valid = TRUE;
+
+ return NFCSTATUS_SUCCESS;
+}
+
+
+
+
+/*-----------------------------------------------------------------------------------
+ DAL INTERNAL IMPLEMENTATION
+------------------------------------------------------------------------------------*/
+
+
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL Reader thread handler
+ * This function manages the reads from the link interface. The reads are done from
+ * this thread to create the asynchronous mecanism. When calling the synchronous
+ * function phDal4Nfc_Read, the nWaitingOnRead mutex is unlocked and the read
+ * can be done. Then a client callback is called to send the result.
+ *
+ * \param[in] pArg A custom argument that can be passed to the thread (not used)
+ *
+ * \retval TRUE Thread exiting.
+ */
+int phDal4Nfc_ReaderThread(void * pArg)
+{
+ char retvalue;
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ uint8_t retry_cnt=0;
+ void * memsetRet;
+
+ static int MsgType= PHDAL4NFC_READ_MESSAGE;
+ int * pmsgType=&MsgType;
+
+ phDal4Nfc_Message_t sMsg;
+ phOsalNfc_Message_t OsalMsg ;
+ int i;
+
+ /* Create the overlapped event. Must be closed before exiting
+ to avoid a handle leak. This event is used READ API and the Reader thread*/
+ pthread_mutex_unlock(&nThreadsEventMutex); /* To indicate thread is ready */
+
+ DAL_PRINT("RX Thread \n");
+ while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */
+ {
+ retvalue = 1;
+ gReadWriteContext.nWaitingOnRead = ((gReadWriteContext.nWaitingOnRead == 1)?1:0);
+ gReadWriteContext.nCancelReadWait = 0;
+ gReadWriteContext.nWaitingOnReadWait = 0;
+
+ pthread_mutex_lock(&gReadWriteContext.nReadEventMutex); /* Remains locked till we get a read request */
+
+ /* Check for the read request from user */
+ if (gReadWriteContext.nWaitingOnRead)
+ {
+ /* Issue read operation.*/
+ gReadWriteContext.nNbOfBytesRead=0;
+ DAL_DEBUG("\n*New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
+ memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);
+
+ /* Wait for Write Completion */
+ usleep(2500);
+ gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
+ if (gReadWriteContext.nNbOfBytesRead == -1)
+ {
+ DAL_DEBUG("Read failed\n", 0);
+ /* TBD : Error, report it.*/
+ result = PHNFCSTVAL(CID_NFC_DAL,
+ NFCSTATUS_BOARD_COMMUNICATION_ERROR);
+ } /* End of File Read if */
+ else if (gReadWriteContext.nNbOfBytesRead == 0)
+ {
+ /* In case of timeout, keep polling */
+ pthread_mutex_unlock(&gReadWriteContext.nReadEventMutex);
+ continue;
+ }
+ else
+ {
+ DAL_DEBUG("Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
+ DAL_DEBUG("NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
+ DAL_PRINT("ReadBuff[]={ ");
+ for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
+ {
+ DAL_DEBUG("0x%x ", gReadWriteContext.pReadBuffer[i]);
+ }
+ DAL_PRINT("}\n");
+
+ /* read completed immediately */
+ sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE;
+ /* Update the state */
+ phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
+ phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
+ memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
+ memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
+ }
+ }
+ else if (gReadWriteContext.nWaitingOnReadWait) /* Wait Read Loop */
+ {
+
+ gReadWriteContext.nNbOfBytesReadWait = gLinkFunc.read(gReadWriteContext.pReadWaitBuffer, gReadWriteContext.nNbOfBytesToReadWait);
+ if (gReadWriteContext.nNbOfBytesReadWait == -1)
+ {
+ /* Error; report it.*/
+ result = PHNFCSTVAL(CID_NFC_DAL,
+ NFCSTATUS_BOARD_COMMUNICATION_ERROR);
+ }
+ else
+ {
+ sMsg.eMsgType= PHDAL4NFC_READWAIT_MESSAGE;
+ phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
+ retry_cnt=0;
+ /* Update the state */
+ gReadWriteContext.nReadBusy = FALSE;
+ /* Reset flag so that another opertion can be issued.*/
+ gReadWriteContext.nWaitingOnRead = FALSE;
+ gReadWriteContext.nNbOfBytesRead=0;
+ gReadWriteContext.nNbOfBytesToRead=0;
+ phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)
+ phDal4Nfc_DeferredCb,(void *)pmsgType);
+
+ /* Update the state */
+ gReadWriteContext.nReadWaitBusy = FALSE;
+ /* Reset flag so that another opertion can be issued.*/
+ gReadWriteContext.nWaitingOnReadWait = FALSE;
+ }/*end-else*/
+
+ }
+ else if (gReadWriteContext.nCancelReadWait)
+ {
+ DAL_PRINT("Read Wait is Canceled\n");
+ }
+ else if ( result != NFCSTATUS_SUCCESS )
+ {
+ /* Report it to user */
+ sMsg.transactInfo.status = result;
+ /*map to OSAL msg format*/
+ OsalMsg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ OsalMsg.pMsgData = (void*)&sMsg;
+ /* Update the state */
+ gReadWriteContext.nNbOfBytesRead=0;
+ gReadWriteContext.nNbOfBytesToRead=0;
+ phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)
+ phDal4Nfc_DeferredCb,(void *)pmsgType);
+
+ } /*end-else if ( result != NFCSTATUS_SUCCESS )*/
+ else
+ {
+ continue;
+ }
+
+ } /* End of thread Loop*/
+ return TRUE;
+}
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL Writer thread handler
+ * This function manages the writes to the link interface. The writes are done from
+ * this thread to create the asynchronous mecanism. When calling the synchronous
+ * function phDal4Nfc_Write, the nWaitingOnWrite mutex is unlocked and the write
+ * can be done. Then a client callback is called to signal the operation as complete.
+ *
+ * \param[in] pArg A custom argument that can be passed to the thread (not used)
+ *
+ * \retval TRUE Thread exiting.
+ */
+int phDal4Nfc_WriterThread(void * pArg)
+{
+ char retvalue = 1;
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phDal4Nfc_Message_t sMsg;
+ phOsalNfc_Message_t OsalMsg ;
+ static int MsgType=PHDAL4NFC_WRITE_MESSAGE;
+ int * pmsgType=&MsgType;
+ int i;
+
+ /* Create the overlapped event. Must be closed before exiting
+ to avoid a handle leak. This event is used READ API and the Reader thread*/
+ pthread_mutex_unlock(&nThreadsEventMutex); /* To indicate thread is ready */
+
+ /* Set the thread started Event, to make sure that both threads are ready
+ in the initialization state*/
+ while(gReadWriteContext.nWriteThreadAlive) /* Thread Loop */
+ {
+
+ retvalue = 1;
+ DAL_PRINT("TX Started\n");
+ pthread_mutex_lock(&gReadWriteContext.nWriteEventMutex); /* Remains locked till we get a write request */
+ /* Check for the write request from user */
+ if(gReadWriteContext.nWaitingOnWrite)
+ {
+ /* Issue a write after a 8ms pause */
+ usleep(8000);
+ gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
+ if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
+ {
+ /* Report write failure or timeout */
+ DAL_DEBUG("Write error in write thread\n", 0);
+ result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR);
+ }/*end writeFile*/
+ else /* Results ready */
+ {
+ /* Write operation completed successfully.*/
+ sMsg.eMsgType = PHDAL4NFC_WRITE_MESSAGE;
+ //sMsg.pContext = pgDalContext;
+ sMsg.pContext= pgDalContext->cb_if.pif_ctxt;
+ phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
+ /* Post a message to the HAL Thread */
+ /* Update the state */
+ gReadWriteContext.nWriteBusy = FALSE;
+ /* Reset flag so that another opertion can be issued.*/
+ gReadWriteContext.nWaitingOnWrite = FALSE;
+
+ gReadWriteContext.nNbOfBytesWritten=gReadWriteContext.nNbOfBytesToWrite;
+
+ DAL_DEBUG("NON Overlapped Write :DAl Writer thread called length : %d\n",
+ gReadWriteContext.nNbOfBytesWritten);
+
+ DAL_PRINT("WriteBuff[]={ ");
+ for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
+ {
+ DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
+ }
+ DAL_PRINT("}\n");
+
+ phDal4Nfc_DeferredCall(phDal4Nfc_DeferredCb,pmsgType);
+
+ }/*end else Results ready */
+ }
+ else if ( result != NFCSTATUS_SUCCESS )
+ {
+
+ /* Report it to user */
+ sMsg.transactInfo.status = result;
+ /*map to OSAL msg format*/
+ OsalMsg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ OsalMsg.pMsgData = (void*)&sMsg;
+ /* Update the state */
+ gReadWriteContext.nWriteBusy = FALSE;
+ /* Reset flag so that another opertion can be issued.*/
+ gReadWriteContext.nWaitingOnWrite = FALSE;
+ gReadWriteContext.nNbOfBytesWritten = 0;
+
+ DAL_DEBUG("DAl Writer thread error called length : %d\n",
+ gReadWriteContext.nNbOfBytesWritten);
+
+ }/*end elseif*/
+ else
+ {
+ continue;
+ }
+ }/* End of thread Loop*/
+ return TRUE;
+}
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL Start threads function
+ * This function is called from phDal4Nfc_Config and is responsible of creating the
+ * reader and writer threads. Also it will init necessary mutexes.
+ *
+ * \retval NFCSTATUS_SUCCESS If success.
+ * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes
+ */
+NFCSTATUS phDal4Nfc_StartThreads(void)
+{
+ pthread_attr_t nReadThreadAttributes;
+ pthread_attr_t nWriteThreadAttributes;
+ int ret;
+
+ /* Mutex init */
+ pthread_mutex_init (&nCriticalSectionMutex, NULL);
+ pthread_mutex_init (&nThreadsEventMutex, NULL);
+
+ /* Lock the request mutexes */
+ pthread_mutex_lock(&gReadWriteContext.nWriteEventMutex);
+ pthread_mutex_lock(&gReadWriteContext.nReadEventMutex);
+
+ pthread_mutex_lock(&nThreadsEventMutex); /* First thread ready lock */
+ ret = pthread_create(&gReadWriteContext.nReadThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread, (void*) "dal_read_thread");
+ if(ret != 0)
+ return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
+ pthread_mutex_lock(&nThreadsEventMutex); /* Blocking lock */
+ // Here we have been unblocked by the thread handler. (so the thread is ready)
+ ret = pthread_create(&gReadWriteContext.nWriteThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_WriterThread, (void*) "dal_write_thread");
+ if(ret != 0)
+ return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
+ pthread_mutex_lock(&nThreadsEventMutex); /* Blocking lock */
+ // Here we have been unblocked by the thread handler. (so the thread is ready)
+ pthread_mutex_unlock(&nThreadsEventMutex);
+ return NFCSTATUS_SUCCESS;
+}
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL fill message function
+ * Internal messages management. This function fills message structure
+ * depending on message types.
+ *
+ * \param[in, out] pDalMsg DAL message to fill
+ * \param[in, out] pOsalMsg OSAL message to fill
+ *
+ */
+void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg)
+{
+ if(NULL != pgDalHwContext)
+ {
+ if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE)
+ {
+ pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesWritten;
+ pDalMsg->transactInfo.buffer = NULL;
+ pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS;
+ pDalMsg->pHwRef = pgDalHwContext;
+ pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete;
+ pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ pOsalMsg->pMsgData = pDalMsg;
+ return;
+ }
+ else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE)
+ {
+ pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesRead;
+ pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer;
+ pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt;
+ }
+ else
+ {
+ pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesReadWait;
+ pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer;
+ pDalMsg->pContext= pgDalContext;
+ }
+ pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS;
+ pDalMsg->pHwRef = pgDalHwContext;
+ pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete;
+ /*map to OSAL msg format*/
+ pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ pOsalMsg->pMsgData = pDalMsg;
+ }
+
+}
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL deferred callback function
+ * Generic handler function called by a client thread when reading a message from the queue.
+ * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall
+ *
+ * \param[in] params Parameter that will be passed to the client function.
+ *
+ */
+void phDal4Nfc_DeferredCb (void *params)
+{
+ int* pParam=NULL;
+ phNfc_sTransactionInfo_t TransactionInfo;
+
+ pParam=(int*)params;
+
+ switch(*pParam)
+ {
+ case PHDAL4NFC_READ_MESSAGE:
+ DAL_PRINT(" Dal deferred read called \n");
+ TransactionInfo.buffer=gReadWriteContext.pReadBuffer;
+ TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead;
+ TransactionInfo.status=NFCSTATUS_SUCCESS;
+ gReadWriteContext.nReadBusy = FALSE;
+ /* Reset flag so that another opertion can be issued.*/
+ gReadWriteContext.nWaitingOnRead = FALSE;
+ if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete))
+ {
+ pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt,
+ pgDalHwContext,&TransactionInfo);
+ }
+
+ break;
+ case PHDAL4NFC_READWAIT_MESSAGE:
+ /*dalMsg->readCbPtr(dalMsg->pContext, dalMsg->pHwRef, &dalMsg->transactInfo);*/
+ break;
+ case PHDAL4NFC_WRITE_MESSAGE:
+ DAL_PRINT(" Dal deferred write called \n");
+ /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
+
+ TransactionInfo.buffer=NULL;
+ TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
+ TransactionInfo.status=NFCSTATUS_SUCCESS;
+ if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete))
+ {
+ pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt,
+ pgDalHwContext,&TransactionInfo);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * \ingroup grp_nfc_dal
+ *
+ * \brief DAL deferred call function
+ * This function will enable to call the callback client asyncronously and in the client context.
+ * It will post a message in a queue that will be processed by a client thread.
+ *
+ * \param[in] func The function to call when message is read from the queue
+ * \param[in] param Parameter that will be passed to the 'func' function.
+ *
+ */
+void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param)
+{
+ int retvalue = 0;
+ phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper;
+ phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage;
+ static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead;
+ static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite;
+
+ pthread_mutex_lock(&nCriticalSectionMutex);
+
+#ifdef USE_MQ_MESSAGE_QUEUE
+ nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ nDeferedMessage.def_call = func;
+ nDeferedMessage.params = param;
+ retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0);
+#else
+ if(PHDAL4NFC_READ_MESSAGE==(* (int*)param))
+ {
+ pDeferedMessage = &nDeferedMessageRead;
+ }
+ else
+ {
+ pDeferedMessage = &nDeferedMessageWrite;
+ }
+ nDeferedMessageWrapper.mtype = 1;
+ nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
+ pDeferedMessage->pCallback = func;
+ pDeferedMessage->pParameter = param;
+ nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage;
+ nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t);
+ retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);
+#endif
+
+ pthread_mutex_unlock(&nCriticalSectionMutex);
+}
+
+#undef _DAL_4_NFC_C
+