diff options
Diffstat (limited to 'Linux_x86/phDal4Nfc.c')
-rw-r--r-- | Linux_x86/phDal4Nfc.c | 1116 |
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 + |