From 5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a Mon Sep 17 00:00:00 2001 From: Nick Pelly Date: Thu, 23 Sep 2010 12:47:58 -0700 Subject: Initial libnfc checkin Source: Trusted_NFC_Device_Host_AA03.01e02_google.zip code drop (23-Sep-2010) Change-Id: Ie47f18423f949a8d3e0815d13f55c814312add24 Signed-off-by: Nick Pelly --- Linux_x86/phDal4Nfc.c | 1116 +++++++++++++++++++++++++++++++++ Linux_x86/phDal4Nfc_debug.h | 42 ++ Linux_x86/phDal4Nfc_i2c.c | 226 +++++++ Linux_x86/phDal4Nfc_i2c.h | 39 ++ Linux_x86/phDal4Nfc_link.h | 56 ++ Linux_x86/phDal4Nfc_messageQueueLib.c | 218 +++++++ Linux_x86/phDal4Nfc_uart.c | 326 ++++++++++ Linux_x86/phDal4Nfc_uart.h | 43 ++ Linux_x86/phOsalNfc.c | 165 +++++ Linux_x86/phOsalNfc_Common.h | 78 +++ Linux_x86/phOsalNfc_Timer.c | 273 ++++++++ Linux_x86/phOsalNfc_Utils.c | 57 ++ 12 files changed, 2639 insertions(+) create mode 100644 Linux_x86/phDal4Nfc.c create mode 100644 Linux_x86/phDal4Nfc_debug.h create mode 100644 Linux_x86/phDal4Nfc_i2c.c create mode 100644 Linux_x86/phDal4Nfc_i2c.h create mode 100644 Linux_x86/phDal4Nfc_link.h create mode 100644 Linux_x86/phDal4Nfc_messageQueueLib.c create mode 100644 Linux_x86/phDal4Nfc_uart.c create mode 100644 Linux_x86/phDal4Nfc_uart.h create mode 100644 Linux_x86/phOsalNfc.c create mode 100644 Linux_x86/phOsalNfc_Common.h create mode 100644 Linux_x86/phOsalNfc_Timer.c create mode 100644 Linux_x86/phOsalNfc_Utils.c (limited to 'Linux_x86') 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 +#include +#ifdef ANDROID +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*----------------------------------------------------------------------------------- + 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 + diff --git a/Linux_x86/phDal4Nfc_debug.h b/Linux_x86/phDal4Nfc_debug.h new file mode 100644 index 0000000..bd6ae91 --- /dev/null +++ b/Linux_x86/phDal4Nfc_debug.h @@ -0,0 +1,42 @@ + + + +/*----------------------------------------------------------------------------------- + DEBUG CORNER +------------------------------------------------------------------------------------*/ +/* Activate for debug */ +//#define DAL_TRACE + +#ifdef DAL_TRACE +#include + +#define MAX_TRACE_BUFFER 150 + +#define DAL_PRINT( str ) phOsalNfc_DbgString(str) +#define DAL_DEBUG(str, arg) \ +{ \ + char trace[MAX_TRACE_BUFFER]; \ + snprintf(trace,MAX_TRACE_BUFFER,str,arg); \ + phOsalNfc_DbgString(trace); \ +} + +#define DAL_PRINT_BUFFER(msg,buf,len) \ +{ \ + uint16_t i = 0; \ + char trace[MAX_TRACE_BUFFER]; \ + snprintf(trace,MAX_TRACE_BUFFER,"\n\t %s:",msg); \ + phOsalNfc_DbgString(trace); \ + phOsalNfc_DbgTrace(buf,len); \ + phOsalNfc_DbgString("\r"); \ +} + +#define DAL_ASSERT_STR(x, str) { if (!(x)) { phOsalNfc_DbgString(str); while(1); } } + +#else +#define DAL_PRINT( str ) +#define DAL_DEBUG(str, arg) +#define DAL_PRINT_BUFFER(msg,buf,len) +#define DAL_ASSERT_STR(x, str) + +#endif + diff --git a/Linux_x86/phDal4Nfc_i2c.c b/Linux_x86/phDal4Nfc_i2c.c new file mode 100644 index 0000000..8a54bee --- /dev/null +++ b/Linux_x86/phDal4Nfc_i2c.c @@ -0,0 +1,226 @@ +/* + * 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_i2c.c + * \brief DAL I2C port implementation for linux + * + * Project: Trusted NFC Linux + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(ANDROID) +#include +#endif + +typedef struct +{ + int nHandle; + char nOpened; + +} phDal4Nfc_I2cPortContext_t; + + +/*----------------------------------------------------------------------------------- + VARIABLES +------------------------------------------------------------------------------------*/ +static phDal4Nfc_I2cPortContext_t gI2cPortContext; + + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_set_open_from_handle + +PURPOSE: Initialize internal variables + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_i2c_initialize(void) +{ + memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t)); +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_set_open_from_handle + +PURPOSE: The application could have opened the link itself. So we just need + to get the handle and consider that the open operation has already + been done. + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext) +{ + gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver; + DAL_ASSERT_STR(gComPortContext.nHandle >= 0, "Bad passed com port handle"); + gI2cPortContext.nOpened = 1; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_is_opened + +PURPOSE: Returns if the link is opened or not. (0 = not opened; 1 = opened) + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_i2c_is_opened(void) +{ + return gI2cPortContext.nOpened; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_flush + +PURPOSE: Flushes the link ; clears the link buffers + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_i2c_flush(void) +{ + /* Nothing to do (driver has no internal buffers) */ +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_close + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_i2c_close(void) +{ + DAL_PRINT("Closing port\n"); + if (gI2cPortContext.nOpened == 1) + { + close(gI2cPortContext.nHandle); + gI2cPortContext.nHandle = 0; + gI2cPortContext.nOpened = 0; + } +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_open_and_configure + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle) +{ + char * pComPort; + + DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!"); + + switch(pConfig->nLinkType) + { + case ENUM_DAL_LINK_TYPE_I2C: + pComPort = "/dev/pn544"; + break; + default: + DAL_DEBUG("Open failed: unknown type %d\n", pConfig->nLinkType); + return NFCSTATUS_INVALID_PARAMETER; + } + + DAL_DEBUG("Opening port=%s\n", pComPort); + + /* open port */ + gI2cPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY); + if (gI2cPortContext.nHandle < 0) + { + DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle); + *pLinkHandle = NULL; + return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); + } + + gI2cPortContext.nOpened = 1; + *pLinkHandle = (void*)gI2cPortContext.nHandle; + + DAL_PRINT("Open succeed\n"); + + return NFCSTATUS_SUCCESS; +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_read + +PURPOSE: Reads nNbBytesToRead bytes and writes them in pBuffer. + Returns the number of bytes really read or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead) +{ + int ret; + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "read called but not opened!"); + + DAL_DEBUG("Reading %d bytes\n", nNbBytesToRead); + ret = read(gI2cPortContext.nHandle, pBuffer, nNbBytesToRead); + if (ret < 0) + { + DAL_DEBUG("Read failed: read() returned %d\n", ret); + } + else + { + DAL_DEBUG("Read succeed (%d bytes)\n", ret); + } + return ret; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_i2c_write + +PURPOSE: Writes nNbBytesToWrite bytes from pBuffer to the link + Returns the number of bytes that have been wrote to the interface or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite) +{ + int ret; + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "write called but not opened!"); + + DAL_DEBUG("Writing %d bytes\n", nNbBytesToWrite); + ret = write(gI2cPortContext.nHandle, pBuffer, nNbBytesToWrite); + if (ret < 0) + { + DAL_DEBUG("Write failed: write() returned %d \n", ret); + } + else + { + DAL_DEBUG("Write succeed (%d bytes)\n", ret); + } + return ret; +} diff --git a/Linux_x86/phDal4Nfc_i2c.h b/Linux_x86/phDal4Nfc_i2c.h new file mode 100644 index 0000000..fe391aa --- /dev/null +++ b/Linux_x86/phDal4Nfc_i2c.h @@ -0,0 +1,39 @@ +/* + * 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_i2c.h + * \brief DAL I2C port implementation for linux + * + * Project: Trusted NFC Linux + * + */ + +/**< Basic type definitions */ +#include +/**< Generic Interface Layer Function Definitions */ +#include +#include + +void phDal4Nfc_i2c_initialize(void); +void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext); +int phDal4Nfc_i2c_is_opened(void); +void phDal4Nfc_i2c_flush(void); +void phDal4Nfc_i2c_close(void); +NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle); +int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead); +int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite); + diff --git a/Linux_x86/phDal4Nfc_link.h b/Linux_x86/phDal4Nfc_link.h new file mode 100644 index 0000000..e26ab11 --- /dev/null +++ b/Linux_x86/phDal4Nfc_link.h @@ -0,0 +1,56 @@ +/* + * 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_link.h + * \brief DAL generic link interface for linux + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 10 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ + +/**< Basic type definitions */ +#include +/**< Generic Interface Layer Function Definitions */ +#include +#include + +typedef void (*phDal4Nfc_link_initialize_CB_t) (void); +typedef void (*phDal4Nfc_link_set_open_from_handle_CB_t) (phHal_sHwReference_t * pDalHwContext); +typedef int (*phDal4Nfc_link_is_opened_CB_t) (void); +typedef void (*phDal4Nfc_link_flush_CB_t) (void); +typedef void (*phDal4Nfc_link_close_CB_t) (void); +typedef NFCSTATUS (*phDal4Nfc_link_open_and_configure_CB_t) (pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle); +typedef int (*phDal4Nfc_link_read_CB_t) (uint8_t * pBuffer, int nNbBytesToRead); +typedef int (*phDal4Nfc_link_write_CB_t) (uint8_t * pBuffer, int nNbBytesToWrite); + +typedef struct +{ + phDal4Nfc_link_initialize_CB_t init; + phDal4Nfc_link_set_open_from_handle_CB_t open_from_handle; + phDal4Nfc_link_is_opened_CB_t is_opened; + phDal4Nfc_link_flush_CB_t flush; + phDal4Nfc_link_close_CB_t close; + phDal4Nfc_link_open_and_configure_CB_t open_and_configure; + phDal4Nfc_link_read_CB_t read; + phDal4Nfc_link_write_CB_t write; +} phDal4Nfc_link_cbk_interface_t; + + diff --git a/Linux_x86/phDal4Nfc_messageQueueLib.c b/Linux_x86/phDal4Nfc_messageQueueLib.c new file mode 100644 index 0000000..30d389b --- /dev/null +++ b/Linux_x86/phDal4Nfc_messageQueueLib.c @@ -0,0 +1,218 @@ +/* + * 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_messageQueueLib.c + * \brief DAL independant message queue implementation for android (can be used under linux too) + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 13 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ + +#include +#ifdef ANDROID +#include +#else +#include +#endif + +#include + +#include +#include +#include +#include + +typedef struct phDal4Nfc_message_queue_item +{ + phLibNfc_Message_t nMsg; + struct phDal4Nfc_message_queue_item * pPrev; + struct phDal4Nfc_message_queue_item * pNext; +} phDal4Nfc_message_queue_item_t; + + +typedef struct phDal4Nfc_message_queue +{ + phDal4Nfc_message_queue_item_t * pItems; + pthread_mutex_t nCriticalSectionMutex; + sem_t nProcessSemaphore; + +} phDal4Nfc_message_queue_t; + + +/** + * \ingroup grp_nfc_dal + * + * \brief DAL message get function + * This function allocates the message queue. The parameters are ignored, this is + * just to keep the same api as Linux queue. + * + * \retval -1 Can not allocate memory or can not init mutex. +* \retval handle The handle on the message queue. + */ +int phDal4Nfc_msgget ( key_t key, int msgflg ) +{ + phDal4Nfc_message_queue_t * pQueue; + pQueue = (phDal4Nfc_message_queue_t *) phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_t)); + if (pQueue == NULL) + return -1; + memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t)); + if (pthread_mutex_init (&pQueue->nCriticalSectionMutex, NULL) == -1) + return -1; + if (sem_init (&pQueue->nProcessSemaphore, 0, 0) == -1) + return -1; + return ((int)pQueue); +} + +/** + * \ingroup grp_nfc_dal + * + * \brief DAL message control function + * This function destroys the message queue. The cmd and buf parameters are ignored, + * this is just to keep the same api as Linux queue. + * + * \param[in] msqid The handle of the message queue. + * + * \retval 0 If success. + * \retval -1 Bad passed parameter + */ +int phDal4Nfc_msgctl ( int msqid, int cmd, void *buf ) +{ + phDal4Nfc_message_queue_t * pQueue; + phDal4Nfc_message_queue_item_t * p; + + if (msqid == 0) + return -1; + + pQueue = (phDal4Nfc_message_queue_t *)msqid; + pthread_mutex_lock(&pQueue->nCriticalSectionMutex); + if (pQueue->pItems != NULL) + { + p = pQueue->pItems; + while(p->pNext != NULL) { p = p->pNext; } + while(p->pPrev != NULL) + { + p = p->pPrev; + phOsalNfc_FreeMemory(p->pNext); + p->pNext = NULL; + } + phOsalNfc_FreeMemory(p); + } + pQueue->pItems = NULL; + pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); + pthread_mutex_destroy(&pQueue->nCriticalSectionMutex); + phOsalNfc_FreeMemory(pQueue); + return 0; +} + +/** + * \ingroup grp_nfc_dal + * + * \brief DAL message send function + * Use this function to send a message to the queue. The message will be added at the end of + * the queue with respect to FIFO policy. The msgflg parameter is ignored. + * + * \param[in] msqid The handle of the message queue. + * \param[in] msgp The message to send. + * \param[in] msgsz The message size. + * + * \retval 0 If success. + * \retval -1 Bad passed parameter, or can not allocate memory + */ +int phDal4Nfc_msgsnd (int msqid, void * msgp, size_t msgsz, int msgflg) +{ + phDal4Nfc_message_queue_t * pQueue; + phDal4Nfc_message_queue_item_t * p; + phDal4Nfc_message_queue_item_t * pNew; + + if ((msqid == 0) || (msgp == NULL) || (msgsz == 0)) + return -1; + + if (msgsz != sizeof(phLibNfc_Message_t)) + return -1; + + pQueue = (phDal4Nfc_message_queue_t *)msqid; + pNew = (phDal4Nfc_message_queue_item_t *)phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_item_t)); + if (pNew == NULL) + return -1; + memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t)); + memcpy(&pNew->nMsg, &((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, sizeof(phLibNfc_Message_t)); + pthread_mutex_lock(&pQueue->nCriticalSectionMutex); + if (pQueue->pItems != NULL) + { + p = pQueue->pItems; + while(p->pNext != NULL) { p = p->pNext; } + p->pNext = pNew; + pNew->pPrev = p; + } + else + { + pQueue->pItems = pNew; + } + pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); + + sem_post(&pQueue->nProcessSemaphore); + return 0; +} + +/** + * \ingroup grp_nfc_dal + * + * \brief DAL message receive function + * The call to this function will get the older message from the queue. If the queue is empty the function waits + * (blocks on a mutex) until a message is posted to the queue with phDal4Nfc_msgsnd. + * The msgtyp and msgflg parameters are ignored. + * + * \param[in] msqid The handle of the message queue. + * \param[out] msgp The received message. + * \param[in] msgsz The message size. + * + * \retval 0 If success. + * \retval -1 Bad passed parameter. + */ +int phDal4Nfc_msgrcv (int msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg) +{ + phDal4Nfc_message_queue_t * pQueue; + phDal4Nfc_message_queue_item_t * p; + + if ((msqid == 0) || (msgp == NULL)) + return -1; + + if (msgsz != sizeof(phLibNfc_Message_t)) + return -1; + + pQueue = (phDal4Nfc_message_queue_t *)msqid; + sem_wait(&pQueue->nProcessSemaphore); + pthread_mutex_lock(&pQueue->nCriticalSectionMutex); + if (pQueue->pItems != NULL) + { + memcpy(&((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t)); + p = pQueue->pItems->pNext; + phOsalNfc_FreeMemory(pQueue->pItems); + pQueue->pItems = p; + } + pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); + return 0; +} + + + + + diff --git a/Linux_x86/phDal4Nfc_uart.c b/Linux_x86/phDal4Nfc_uart.c new file mode 100644 index 0000000..9d230f1 --- /dev/null +++ b/Linux_x86/phDal4Nfc_uart.c @@ -0,0 +1,326 @@ +/* + * 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_uart.c + * \brief DAL com port implementation for linux + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 07 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#if defined(ANDROID) +#include +#endif + +typedef struct +{ + int nHandle; + char nOpened; + struct termios nIoConfigBackup; + struct termios nIoConfig; + +} phDal4Nfc_ComPortContext_t; + +/*----------------------------------------------------------------------------------- + COM PORT CONFIGURATION +------------------------------------------------------------------------------------*/ +#define DAL_BAUD_RATE B115200 + + + +/*----------------------------------------------------------------------------------- + VARIABLES +------------------------------------------------------------------------------------*/ +static phDal4Nfc_ComPortContext_t gComPortContext; + + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_set_open_from_handle + +PURPOSE: Initialize internal variables + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_initialize(void) +{ + memset(&gComPortContext, 0, sizeof(phDal4Nfc_ComPortContext_t)); +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_set_open_from_handle + +PURPOSE: The application could have opened the link itself. So we just need + to get the handle and consider that the open operation has already + been done. + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_set_open_from_handle(phHal_sHwReference_t * pDalHwContext) +{ + gComPortContext.nHandle = (int) pDalHwContext->p_board_driver; + DAL_ASSERT_STR(gComPortContext.nHandle >= 0, "Bad passed com port handle"); + gComPortContext.nOpened = 1; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_is_opened + +PURPOSE: Returns if the link is opened or not. (0 = not opened; 1 = opened) + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_is_opened(void) +{ + return gComPortContext.nOpened; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_flush + +PURPOSE: Flushes the link ; clears the link buffers + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_flush(void) +{ + int ret; + /* flushes the com port */ + ret = tcflush(gComPortContext.nHandle, TCIFLUSH); + DAL_ASSERT_STR(ret!=-1, "tcflush failed"); +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_close + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_close(void) +{ + if (gComPortContext.nOpened == 1) + { + close(gComPortContext.nHandle); + gComPortContext.nHandle = 0; + gComPortContext.nOpened = 0; + } +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_close + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +NFCSTATUS phDal4Nfc_uart_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle) +{ + char * pComPort; + int nComStatus; + NFCSTATUS nfcret = NFCSTATUS_SUCCESS; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened==0, "Trying to open but already done!"); + + switch(pConfig->nLinkType) + { + case ENUM_DAL_LINK_TYPE_COM1: + pComPort = "/dev/ttyS0"; + break; + case ENUM_DAL_LINK_TYPE_COM2: + pComPort = "/dev/ttyS1"; + break; + case ENUM_DAL_LINK_TYPE_COM3: + pComPort = "/dev/ttyS2"; + break; + case ENUM_DAL_LINK_TYPE_COM4: + pComPort = "/dev/ttyS3"; + break; + case ENUM_DAL_LINK_TYPE_COM5: + pComPort = "/dev/ttyS4"; + break; + case ENUM_DAL_LINK_TYPE_COM6: + pComPort = "/dev/ttyS5"; + break; + case ENUM_DAL_LINK_TYPE_COM7: + pComPort = "/dev/ttyS6"; + break; + case ENUM_DAL_LINK_TYPE_COM8: + pComPort = "/dev/ttyS7"; + break; + case ENUM_DAL_LINK_TYPE_USB: + pComPort = "/dev/ttyUSB0"; + break; + default: + return NFCSTATUS_INVALID_PARAMETER; + } + + /* open communication port handle */ + gComPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY); + if (gComPortContext.nHandle < 0) + { + *pLinkHandle = NULL; + return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); + } + + gComPortContext.nOpened = 1; + *pLinkHandle = (void*)gComPortContext.nHandle; + + /* + * Now configure the com port + */ + ret = tcgetattr(gComPortContext.nHandle, &gComPortContext.nIoConfigBackup); /* save the old io config */ + if (ret == -1) + { + /* tcgetattr failed -- it is likely that the provided port is invalid */ + *pLinkHandle = NULL; + return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); + } + ret = fcntl(gComPortContext.nHandle, F_SETFL, 0); /* Makes the read blocking (default). */ + DAL_ASSERT_STR(ret != -1, "fcntl failed"); + /* Configures the io */ + memset((void *)&gComPortContext.nIoConfig, (int)0, (size_t)sizeof(struct termios)); + /* + BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. + CRTSCTS : output hardware flow control (only used if the cable has + all necessary lines. See sect. 7 of Serial-HOWTO) + CS8 : 8n1 (8bit,no parity,1 stopbit) + CLOCAL : local connection, no modem contol + CREAD : enable receiving characters + */ + gComPortContext.nIoConfig.c_cflag = DAL_BAUD_RATE | CS8 | CLOCAL | CREAD; /* Control mode flags */ + gComPortContext.nIoConfig.c_iflag = IGNPAR; /* Input mode flags : IGNPAR Ignore parity errors */ + gComPortContext.nIoConfig.c_oflag = 0; /* Output mode flags */ + gComPortContext.nIoConfig.c_lflag = 0; /* Local mode flags. Read mode : non canonical, no echo */ + gComPortContext.nIoConfig.c_cc[VTIME] = 0; /* Control characters. No inter-character timer */ + gComPortContext.nIoConfig.c_cc[VMIN] = 1; /* Control characters. Read is blocking until X characters are read */ + + /* + TCSANOW Make changes now without waiting for data to complete + TCSADRAIN Wait until everything has been transmitted + TCSAFLUSH Flush input and output buffers and make the change + */ + ret = tcsetattr(gComPortContext.nHandle, TCSANOW, &gComPortContext.nIoConfig); + DAL_ASSERT_STR(ret != -1, "tcsetattr failed"); + + /* + On linux the DTR signal is set by default. That causes a problem for pn544 chip + because this signal is connected to "reset". So we clear it. (on windows it is cleared by default). + */ + ret = ioctl(gComPortContext.nHandle, TIOCMGET, &nComStatus); + DAL_ASSERT_STR(ret != -1, "ioctl TIOCMGET failed"); + nComStatus &= ~TIOCM_DTR; + ret = ioctl(gComPortContext.nHandle, TIOCMSET, &nComStatus); + DAL_ASSERT_STR(ret != -1, "ioctl TIOCMSET failed"); + DAL_DEBUG("Com port status=%d\n", nComStatus); + usleep(10000); /* Mandatory sleep so that the DTR line is ready before continuing */ + + return nfcret; +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_read + +PURPOSE: Reads nNbBytesToRead bytes and writes them in pBuffer. + Returns the number of bytes really read or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_read(uint8_t * pBuffer, int nNbBytesToRead) +{ + fd_set rfds; + struct timeval tv; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "read called but not opened!"); + + FD_ZERO(&rfds); + FD_SET(gComPortContext.nHandle, &rfds); + + /* select will block for 10 sec */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + ret = select(gComPortContext.nHandle + 1, &rfds, NULL, NULL, &tv); + + if (ret == -1) + return -1; + + if (ret) + return read(gComPortContext.nHandle, pBuffer, nNbBytesToRead); + + return 0; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_link_write + +PURPOSE: Writes nNbBytesToWrite bytes from pBuffer to the link + Returns the number of bytes that have been wrote to the interface or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_write(uint8_t * pBuffer, int nNbBytesToWrite) +{ + fd_set wfds; + struct timeval tv; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "write called but not opened!"); + + FD_ZERO(&wfds); + FD_SET(gComPortContext.nHandle, &wfds); + + /* select will block for 10 sec */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + ret = select(gComPortContext.nHandle + 1, NULL, &wfds, NULL, &tv); + + if (ret == -1) + return -1; + + if (ret) + return write(gComPortContext.nHandle, pBuffer, nNbBytesToWrite); + + return 0; +} diff --git a/Linux_x86/phDal4Nfc_uart.h b/Linux_x86/phDal4Nfc_uart.h new file mode 100644 index 0000000..329f626 --- /dev/null +++ b/Linux_x86/phDal4Nfc_uart.h @@ -0,0 +1,43 @@ +/* + * 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_uart.h + * \brief DAL com port implementation for linux + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 07 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ + +/**< Basic type definitions */ +#include +/**< Generic Interface Layer Function Definitions */ +#include +#include + +void phDal4Nfc_uart_initialize(void); +void phDal4Nfc_uart_set_open_from_handle(phHal_sHwReference_t * pDalHwContext); +int phDal4Nfc_uart_is_opened(void); +void phDal4Nfc_uart_flush(void); +void phDal4Nfc_uart_close(void); +NFCSTATUS phDal4Nfc_uart_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle); +int phDal4Nfc_uart_read(uint8_t * pBuffer, int nNbBytesToRead); +int phDal4Nfc_uart_write(uint8_t * pBuffer, int nNbBytesToWrite); + diff --git a/Linux_x86/phOsalNfc.c b/Linux_x86/phOsalNfc.c new file mode 100644 index 0000000..ce01d26 --- /dev/null +++ b/Linux_x86/phOsalNfc.c @@ -0,0 +1,165 @@ +/* + * 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 phOsalNfc.c + * \brief OSAL Implementation for linux + * + * Project: Trusted NFC Linux Light + * + * $Date: 03 aug 2009 + * $Author: Jérémie Corbier + * $Revision: 1.0 + * + */ + +#include +#include +#include +#include +#include + +#include + +#ifdef ANDROID +#define LOG_TAG "NFC-HCI" + +#include + +phOsalNfc_Exception_t phOsalNfc_Exception; +#endif + +#ifdef DEBUG +#define MAX_PRINT_BUFSIZE (0x450U) +char phOsalNfc_DbgTraceBuffer[MAX_PRINT_BUFSIZE]; +#endif + +/*! + * \brief Allocates memory. + * This function attempts to allocate \a size bytes on the heap and + * returns a pointer to the allocated block. + * + * \param size size of the memory block to be allocated on the heap. + * + * \return pointer to allocated memory block or NULL in case of error. + */ +void *phOsalNfc_GetMemory(uint32_t size) +{ + void *pMem = (void *)malloc(size); + return pMem; +} + +/*! + * \brief Frees allocated memory block. + * This function deallocates memory region pointed to by \a pMem. + * + * \param pMem pointer to memory block to be freed. + */ +void phOsalNfc_FreeMemory(void *pMem) +{ + if(NULL != pMem) + free(pMem); +} + +void phOsalNfc_DbgString(const char *pString) +{ +#ifdef DEBUG + if(pString != NULL) +#ifndef ANDROID + printf(pString); +#else + LOGD(pString); +#endif +#endif +} + +void phOsalNfc_DbgTrace(uint8_t data[], uint32_t size) +{ +#ifdef DEBUG + uint32_t i; +#ifdef ANDROID + char buf[10]; +#endif + + if(size == 0) + return; + +#ifndef ANDROID + for(i = 0; i < size; i++) + { + if((i % 10) == 0) + printf("\n\t\t\t"); + printf("%02X ", data[i]); + } + printf("\n\tBlock size is: %d\n", size); +#else + phOsalNfc_DbgTraceBuffer[0] = '\0'; + for(i = 0; i < size; i++) + { + if((i % 10) == 0) + { + LOGD(phOsalNfc_DbgTraceBuffer); + phOsalNfc_DbgTraceBuffer[0] = '\0'; + } + + snprintf(buf, 10, "%02X ", data[i]); + strncat(phOsalNfc_DbgTraceBuffer, buf, 10); + } + LOGD(phOsalNfc_DbgTraceBuffer); + LOGD("Block size is: %d", size); +#endif +#endif +} + +/*! + * \brief Raises exception. + * This function raises an exception of type \a eExceptionType with + * reason \a reason to stack clients. + * + * \param eExceptionType exception type. + * \param reason reason for this exception. + * + * \note Clients willing to catch exceptions are to handle the SIGABRT signal. + * On Linux, exception type and reason are passed to the signal handler as + * a pointer to a phOsalNfc_Exception_t structure. + * As sigqueue is not available in Android, exception information are + * stored in the phOsalNfc_Exception global. + */ +void phOsalNfc_RaiseException(phOsalNfc_ExceptionType_t eExceptionType, uint16_t reason) +{ + pid_t pid; +#ifndef ANDROID + static phOsalNfc_Exception_t phOsalNfc_Exception; + union sigval sv; +#endif + + phOsalNfc_Exception.eExceptionType = eExceptionType; + phOsalNfc_Exception.reason = reason; + + pid = getpid(); + + /* + * JCO: Bionic does not provide, among other things, sigqueue... + */ +#ifdef ANDROID + kill(pid, SIGABRT); +#else + sv.sival_ptr = &phOsalNfc_Exception; + + sigqueue(pid, SIGABRT, sv); +#endif +} + diff --git a/Linux_x86/phOsalNfc_Common.h b/Linux_x86/phOsalNfc_Common.h new file mode 100644 index 0000000..8ca7674 --- /dev/null +++ b/Linux_x86/phOsalNfc_Common.h @@ -0,0 +1,78 @@ +/* + * 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 phOsalNfc_Common.h + * + * Project: NFC FRI / OSAL + * + * $Workfile:: phOsalNfc_Common.h $ + * $Modtime:: $ + * $Author: frq09147 $ + * $Revision: 1.1 $ + * + */ + +#ifndef PHOSALNFC_COMMON_H +#define PHOSALNFC_COMMON_H +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MESSAGE_SIZE 256 + +typedef enum phOsalNfc_eHandleType +{ + phOsalNfc_eHandleTypeInvalid = 0, + phOsalNfc_eHandleTypeThread = 1, + phOsalNfc_eHandleTypeSemaphore = 2, + +}phOsalNfc_eHandleType_t; + +typedef struct phOsalNfc_sMsg +{ + phOsalNfc_Message_t Msg; + uint32_t sourceID; /* pthread_t = unsigned long int */ + struct phOsalNfc_sMsg *nextMsg; +} phOsalNfc_sMsg_t; + +typedef struct phOsalNfc_sOsalHandle +{ + phOsalNfc_eHandleType_t HandleType; + pthread_t *pThread; + pphOsalNfc_ThreadFunction_t pThreadFunction; + void *pParams; + + sem_t *pSemaphore; + sem_t handleSem; + int32_t semValue; + uint32_t semMax; + + struct sembuf semBuf; + int32_t semId; + + phOsalNfc_sMsg_t *pMsg; + sem_t msgSem; + struct phOsalNfc_sOsalHandle *nextThread; +} phOsalNfc_sOsalHandle_t; + + +#endif /* PHOSALNFC_COMMON_H */ diff --git a/Linux_x86/phOsalNfc_Timer.c b/Linux_x86/phOsalNfc_Timer.c new file mode 100644 index 0000000..e448f20 --- /dev/null +++ b/Linux_x86/phOsalNfc_Timer.c @@ -0,0 +1,273 @@ +/* + * 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 phOsalNfc_Timer.c + * \brief OSAL Timer Implementation for linux + * + * Project: Trusted NFC Linux Light + * + * $Date: 03 aug 2009 + * $Author: Jérémie Corbier + * $Revision: 1.0 + * + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#define NSECS 1000000 +#define MAX_NO_TIMERS 16 + +/*! + * \struct phOsalNfc_Timer + * Internal OSAL timer structure + */ +struct phOsalNfc_Timer +{ + timer_t handle; /*!< System timer handle. */ + ppCallBck_t callback; /*!< Callback to be called when timer expires. */ + void* pContext; /*!< Callback context. */ +#ifdef NXP_MESSAGING + void *ptr; +#endif + int nIsStopped; +}; + +static struct phOsalNfc_Timer timers[MAX_NO_TIMERS] = +{ + {0, NULL, NULL +#ifdef NXP_MESSAGING + , NULL +#endif + , 0 + }, +}; + +#ifdef NXP_MESSAGING +extern int nDeferedCallMessageQueueId; + +void phOsalNfc_Timer_DeferredCall(void *params) +{ + phOsalNfc_Timer_Msg_t *timer_msg; + + if(params == NULL) + return; + + timer_msg = (phOsalNfc_Timer_Msg_t *)params; + + if((timer_msg != NULL) && (timer_msg->pCallBck != NULL)) + timer_msg->pCallBck(timer_msg->TimerId, timer_msg->pContext); + + if ((timer_msg->TimerId >= MAX_NO_TIMERS) || (timer_msg->TimerId < 0)) + { + printf("Bad TimerId=%d, should be <= to %d\n", timer_msg->TimerId, MAX_NO_TIMERS); + } + else + { + if(timers[timer_msg->TimerId].ptr != NULL) + { + phOsalNfc_FreeMemory(timers[timer_msg->TimerId].ptr); + timers[timer_msg->TimerId].ptr = NULL; + } + } + phOsalNfc_FreeMemory(timer_msg); +} +#endif + +/*! + * \brief System timer callback. + * This callback is called by Linux whenever one the timers expires. It + * calls the corresponding registered callback. + * + * \param sv structure storing the expired timer ID. + */ +static void phOsalNfc_Timer_Expired(union sigval sv) +{ + uint32_t timerid = (uint32_t)(sv.sival_int); + + if((timerid < MAX_NO_TIMERS)&&(timers[timerid].nIsStopped == 1)) + { + //printf("phOsalNfc_Timer_Expired : Expired but already stopped TimerId=%d\n", timerid); + return; + } + + if(timerid < MAX_NO_TIMERS) + { +#ifndef CYCLIC_TIMER + phOsalNfc_Timer_Stop(timerid); +#else + +#endif +#ifdef NXP_MESSAGING + phOsalNfc_Timer_Msg_t *timer_msg; + phOsalNfc_DeferedCalldInfo_t *osal_defer_msg; + phDal4Nfc_Message_Wrapper_t wrapper; + + timer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_Timer_Msg_t)); + if(timer_msg == NULL) + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0); + + osal_defer_msg = phOsalNfc_GetMemory(sizeof(phOsalNfc_DeferedCalldInfo_t)); + if(osal_defer_msg == NULL) + { + phOsalNfc_FreeMemory(timer_msg); + phOsalNfc_RaiseException(phOsalNfc_e_NoMemory, 0); + } + + timer_msg->TimerId = timerid; + timer_msg->pCallBck = timers[timerid].callback; + timer_msg->pContext = timers[timerid].pContext; + + osal_defer_msg->pCallback = phOsalNfc_Timer_DeferredCall; + osal_defer_msg->pParameter = timer_msg; + + wrapper.mtype = 1; + wrapper.msg.eMsgType = PH_OSALNFC_TIMER_MSG; + wrapper.msg.pMsgData = osal_defer_msg; + wrapper.msg.Size = sizeof(phOsalNfc_DeferedCalldInfo_t); + + timers[timerid].ptr = osal_defer_msg; + + phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (void *)&wrapper, + sizeof(phOsalNfc_Message_t), 0); +#else + (timers[timerid].callback)(timerid, timers[timerid].pContext); +#endif + } +} + +static void phOsalNfc_Timer_Dummy_Cb(uint32_t timerid, void *pContext) {} + +/*! + * \brief Creates a new timer. + * This function checks whether there is an available timer slot. If + * this is the case, then it reserves it for future usage and returns its + * ID. + * + * \return a valid timer ID or PH_OSALNFC_INVALID_TIMER_ID if an error occured. + */ +uint32_t phOsalNfc_Timer_Create(void) +{ + uint32_t timerid; + struct sigevent se; + + se.sigev_notify = SIGEV_THREAD; + se.sigev_notify_function = phOsalNfc_Timer_Expired; + se.sigev_notify_attributes = NULL; + + /* Look for available timer slot */ + for(timerid = 0; timerid < MAX_NO_TIMERS; timerid++) + if(timers[timerid].callback == NULL) + break; + if(timerid == MAX_NO_TIMERS) + return PH_OSALNFC_INVALID_TIMER_ID; + + se.sigev_value.sival_int = (int)timerid; + + /* Create POSIX timer */ + if(timer_create(CLOCK_REALTIME, &se, &(timers[timerid].handle)) == -1) + return PH_OSALNFC_INVALID_TIMER_ID; + timers[timerid].callback = phOsalNfc_Timer_Dummy_Cb; +#ifdef NXP_MESSAGING + timers[timerid].ptr = NULL; +#endif + + return timerid; +} + +/*! + * \brief Starts a timer. + * This function starts the timer \a TimerId with an expiration time of + * \a RegTimeCnt milliseconds. Each time it expires, \a + * Application_callback is called. + * + * \param TimerId a valid timer ID. + * \param RegTimeCnt expiration time in milliseconds. + * \param Application_callback callback to be called when timer expires. + */ +void phOsalNfc_Timer_Start(uint32_t TimerId, + uint32_t RegTimeCnt, + ppCallBck_t Application_callback, + void *pContext) +{ + struct itimerspec its; + + if(TimerId >= MAX_NO_TIMERS) + return; + if(Application_callback == NULL) + return; + if(timers[TimerId].callback == NULL) + return; + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = (RegTimeCnt * NSECS) / 1000000000; + its.it_value.tv_nsec = ((long)RegTimeCnt * NSECS) % 1000000000; + + timers[TimerId].callback = Application_callback; + timers[TimerId].pContext = pContext; + timers[TimerId].nIsStopped = 0; + + timer_settime(timers[TimerId].handle, 0, &its, NULL); +} + +/*! + * \brief Stops a timer. + * This function stops an already started timer. + * + * \param TimerId a valid timer ID. + */ +void phOsalNfc_Timer_Stop(uint32_t TimerId) +{ + struct itimerspec its = {{0, 0}, {0, 0}}; + + if(TimerId >= MAX_NO_TIMERS) + return; + if(timers[TimerId].callback == NULL) + return; + if(timers[TimerId].nIsStopped == 1) + return; + + timers[TimerId].nIsStopped = 1; + timer_settime(timers[TimerId].handle, 0, &its, NULL); +} + +/*! + * \brief Deletes a timer. + * This function deletes a timer. + * + * \param TimerId a valid timer ID. + */ +void phOsalNfc_Timer_Delete(uint32_t TimerId) +{ + if(TimerId >= MAX_NO_TIMERS) + return; + if(timers[TimerId].callback == NULL) + return; + + timer_delete(timers[TimerId].handle); + + timers[TimerId].callback = NULL; + timers[TimerId].pContext = NULL; +} diff --git a/Linux_x86/phOsalNfc_Utils.c b/Linux_x86/phOsalNfc_Utils.c new file mode 100644 index 0000000..26a28c0 --- /dev/null +++ b/Linux_x86/phOsalNfc_Utils.c @@ -0,0 +1,57 @@ +/* + * 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 phOsalNfc_Utils.c + * \brief OSAL Implementation. + * + * Project: NFC-FRI 1.1 + * + * $Date: Wed Jun 24 10:35:10 2009 $ + * $Author: ravindrau $ + * $Revision: 1.1 $ + * $Aliases: NFC_FRI1.1_WK926_R28_1,NFC_FRI1.1_WK928_R29_1,NFC_FRI1.1_WK930_R30_1,NFC_FRI1.1_WK934_PREP_1,NFC_FRI1.1_WK934_R31_1,NFC_FRI1.1_WK941_PREP1,NFC_FRI1.1_WK941_PREP2,NFC_FRI1.1_WK941_1,NFC_FRI1.1_WK943_R32_1,NFC_FRI1.1_WK949_PREP1,NFC_FRI1.1_WK943_R32_10,NFC_FRI1.1_WK943_R32_13,NFC_FRI1.1_WK943_R32_14,NFC_FRI1.1_WK1007_R33_1,NFC_FRI1.1_WK1007_R33_4,NFC_FRI1.1_WK1017_PREP1,NFC_FRI1.1_WK1017_R34_1,NFC_FRI1.1_WK1017_R34_2,NFC_FRI1.1_WK1023_R35_1 $ + * + */ + +#include +#include +#include +#include + + +/*The function does a comparison of two strings and returns a non zero value +if two strings are unequal*/ +int phOsalNfc_MemCompare ( void *src, void *dest, unsigned int n ) +{ + int8_t *b1 =(int8_t *)src; + int8_t *b2 =(int8_t *)dest; + int8_t diff = 0; +#ifdef VERIFY_MEMORY + if((NULL != src) && (NULL != dest)) +#endif + { + for(;((n>0)&&(diff==0));n--,b1++,b2++) + { + diff = *b1 - *b2; + } + } + return (int)diff; +} + + + + -- cgit v1.1