Home | History | Annotate | Download | only in Linux_x86
      1 /*
      2  * Copyright (C) 2010 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  * \file phDalNfc.c
     19  * \brief DAL Implementation for linux
     20  *
     21  * Project: Trusted NFC Linux Lignt
     22  *
     23  * $Date: 07 aug 2009
     24  * $Author: Jonathan roux
     25  * $Revision: 1.0 $
     26  *
     27  */
     28 
     29 #define _DAL_4_NFC_C
     30 
     31 #include <unistd.h>
     32 #include <pthread.h>
     33 #include <stdlib.h>
     34 #ifdef ANDROID
     35 #include <linux/ipc.h>
     36 #else
     37 #include <sys/msg.h>
     38 #endif
     39 #include <semaphore.h>
     40 #include <phDal4Nfc.h>
     41 #include <phOsalNfc.h>
     42 #include <phNfcStatus.h>
     43 #include <phDal4Nfc_DeferredCall.h>
     44 #include <phDal4Nfc_debug.h>
     45 #include <phDal4Nfc_uart.h>
     46 #include <phDal4Nfc_i2c.h>
     47 #include <phDal4Nfc_link.h>
     48 #include <phDal4Nfc_messageQueueLib.h>
     49 
     50 /*-----------------------------------------------------------------------------------
     51                                   MISC DEFINITIONS
     52 ------------------------------------------------------------------------------------*/
     53 #define DEFAULT_LINK_TYPE             ENUM_DAL_LINK_TYPE_COM1
     54 
     55 /*-----------------------------------------------------------------------------------
     56                                        TYPES
     57 ------------------------------------------------------------------------------------*/
     58 /*structure holds members related for both read and write operations*/
     59 typedef struct Dal_RdWr_st
     60 {
     61     /* Read members */
     62     pthread_t             nReadThread;             /* Read thread Hanlde */
     63     uint8_t *             pReadBuffer;             /* Read local buffer */
     64     int                   nNbOfBytesToRead;        /* Number of bytes to read */
     65     int                   nNbOfBytesRead;          /* Number of read bytes */
     66     char                  nReadBusy;               /* Read state machine */
     67     char                  nReadThreadAlive;        /* Read state machine */
     68     char                  nWaitingOnRead;          /* Read state machine */
     69 
     70     /* Read wait members */
     71     uint8_t *             pReadWaitBuffer;         /* Read wait local Buffer */
     72     int                   nNbOfBytesToReadWait;    /* Number of bytes to read */
     73     int                   nNbOfBytesReadWait;      /* Number of read bytes */
     74     char                  nReadWaitBusy;           /* Read state machine */
     75     char                  nWaitingOnReadWait;      /* Read state machine */
     76     char                  nCancelReadWait;         /* Read state machine */
     77 
     78     /* Write members */
     79     pthread_t             nWriteThread;            /* Write thread Hanlde */
     80     uint8_t *             pWriteBuffer;            /* Write local buffer */
     81     uint8_t *             pTempWriteBuffer;        /* Temp Write local buffer */
     82     int                   nNbOfBytesToWrite;       /* Number of bytes to write */
     83     int                   nNbOfBytesWritten;       /* Number of bytes written */
     84     char                  nWaitingOnWrite;         /* Write state machine */
     85     char                  nWriteThreadAlive;       /* Write state machine */
     86     char                  nWriteBusy;              /* Write state machine */
     87 } phDal4Nfc_RdWr_t;
     88 
     89 typedef void   (*pphDal4Nfc_DeferFuncPointer_t) (void * );
     90 typedef void * (*pphDal4Nfc_thread_handler_t)   (void * pParam);
     91 
     92 
     93 /*-----------------------------------------------------------------------------------
     94                                       VARIABLES
     95 ------------------------------------------------------------------------------------*/
     96 static phDal4Nfc_RdWr_t               gReadWriteContext;
     97 static phDal4Nfc_SContext_t           gDalContext;
     98 static pphDal4Nfc_SContext_t          pgDalContext;
     99 static phHal_sHwReference_t   *       pgDalHwContext;
    100 static sem_t                          nfc_read_sem;
    101 #ifdef USE_MQ_MESSAGE_QUEUE
    102 static phDal4Nfc_DeferredCall_Msg_t   nDeferedMessage;
    103 static mqd_t                          nDeferedCallMessageQueueId;
    104 
    105 #else
    106 int                            nDeferedCallMessageQueueId = 0;
    107 #endif
    108 static phDal4Nfc_link_cbk_interface_t gLinkFunc;
    109 /*-----------------------------------------------------------------------------------
    110                                      PROTOTYPES
    111 ------------------------------------------------------------------------------------*/
    112 static void      phDal4Nfc_DeferredCb     (void  *params);
    113 static NFCSTATUS phDal4Nfc_StartThreads   (void);
    114 static void      phDal4Nfc_FillMsg        (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
    115 
    116 /*-----------------------------------------------------------------------------------
    117                                 DAL API IMPLEMENTATION
    118 ------------------------------------------------------------------------------------*/
    119 
    120 /*-----------------------------------------------------------------------------
    121 
    122 FUNCTION: phDal4Nfc_Register
    123 
    124 PURPOSE:  DAL register function.
    125 
    126 -----------------------------------------------------------------------------*/
    127 NFCSTATUS phDal4Nfc_Register( phNfcIF_sReference_t  *psRefer,
    128                               phNfcIF_sCallBack_t if_cb, void *psIFConf )
    129 {
    130     NFCSTATUS               result = NFCSTATUS_SUCCESS;
    131 
    132     if ((NULL != psRefer) &&
    133         (NULL != psRefer->plower_if) &&
    134         (NULL != if_cb.receive_complete) &&
    135         (NULL != if_cb.send_complete)
    136         )
    137     {
    138         /* Register the LLC functions to the upper layer */
    139         psRefer->plower_if->init           = phDal4Nfc_Init;
    140         psRefer->plower_if->release        = phDal4Nfc_Shutdown;
    141         psRefer->plower_if->send           = phDal4Nfc_Write;
    142         psRefer->plower_if->receive        = phDal4Nfc_Read;
    143         psRefer->plower_if->receive_wait   = phDal4Nfc_ReadWait;
    144         psRefer->plower_if->transact_abort = phDal4Nfc_ReadWaitCancel;
    145         psRefer->plower_if->unregister     = phDal4Nfc_Unregister;
    146 
    147 
    148         if (NULL != pgDalContext)
    149         {
    150             /* Copy the DAL context to the upper layer */
    151             psRefer->plower_if->pcontext = pgDalContext;
    152             /* Register the callback function from the upper layer */
    153             pgDalContext->cb_if.receive_complete = if_cb.receive_complete;
    154             pgDalContext->cb_if.send_complete = if_cb.send_complete;
    155             pgDalContext->cb_if.notify = if_cb.notify;
    156             /* Get the upper layer context */
    157             pgDalContext->cb_if.pif_ctxt = if_cb.pif_ctxt;
    158             /* Update the error state */
    159             result = NFCSTATUS_SUCCESS;
    160         }
    161         else
    162         {
    163             result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
    164         }
    165     }
    166     else /*Input parameters invalid*/
    167     {
    168         result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
    169     }
    170     return result;
    171 }
    172 
    173 /*-----------------------------------------------------------------------------
    174 
    175 FUNCTION: phDal4Nfc_Unregister
    176 
    177 PURPOSE:  DAL unregister function.
    178 
    179 -----------------------------------------------------------------------------*/
    180 NFCSTATUS phDal4Nfc_Unregister(void *pContext, void *pHwRef )
    181 {
    182     NFCSTATUS               result = NFCSTATUS_SUCCESS;
    183 
    184     if ((NULL == pContext) && (NULL == pHwRef))
    185     {
    186         result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
    187     }
    188     else
    189     {
    190         if (NULL != pgDalContext)
    191         {
    192             /* Register the callback function from the upper layer */
    193             pgDalContext->cb_if.receive_complete = NULL;
    194             pgDalContext->cb_if.send_complete = NULL ;
    195             pgDalContext->cb_if.notify = NULL ;
    196             /* Get the upper layer context */
    197             pgDalContext->cb_if.pif_ctxt =  NULL ;
    198 
    199         }
    200         else
    201         {
    202             result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
    203         }
    204     }
    205     return result;
    206 }
    207 
    208 /*-----------------------------------------------------------------------------
    209 
    210 FUNCTION: phDal4Nfc_Init
    211 
    212 PURPOSE:  DAL Init function.
    213 
    214 -----------------------------------------------------------------------------*/
    215 NFCSTATUS phDal4Nfc_Init(void *pContext, void *pHwRef )
    216 {
    217     NFCSTATUS        result = NFCSTATUS_SUCCESS;
    218 
    219     if ((NULL != pContext) && (NULL != pHwRef))
    220     {
    221         pContext  = pgDalContext;
    222         pgDalHwContext = (phHal_sHwReference_t *)pHwRef;
    223 
    224         if ( gDalContext.hw_valid == TRUE )
    225         {
    226             /* The link has been opened from the application interface */
    227             gLinkFunc.open_from_handle(pgDalHwContext);
    228 
    229             if (!gLinkFunc.is_opened())
    230             {
    231                 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
    232             }
    233             else
    234             {
    235                 /* Clear link buffers */
    236                 gLinkFunc.flush();
    237             }
    238         }
    239         else
    240         {
    241             static phDal4Nfc_sConfig_t hw_config;
    242             hw_config.nLinkType = DEFAULT_LINK_TYPE;
    243             result = phDal4Nfc_Config(&hw_config, pHwRef );
    244         }
    245     }
    246     else /*Input parametrs invalid*/
    247     {
    248         result = NFCSTATUS_INVALID_PARAMETER;
    249     }
    250 
    251     return result;
    252 }
    253 
    254 /*-----------------------------------------------------------------------------
    255 
    256 FUNCTION: phDal4Nfc_Shutdown
    257 
    258 PURPOSE:  DAL Shutdown function.
    259 
    260 -----------------------------------------------------------------------------*/
    261 
    262 NFCSTATUS phDal4Nfc_Shutdown( void *pContext, void *pHwRef)
    263 {
    264    NFCSTATUS result = NFCSTATUS_SUCCESS;
    265    void * pThreadReturn;
    266 
    267 //   if (pContext == NULL)
    268 //      return NFCSTATUS_INVALID_PARAMETER;
    269 
    270    if (gDalContext.hw_valid == TRUE)
    271    {
    272       /* Flush the link */
    273       gLinkFunc.flush();
    274 
    275       /* Close the message queue */
    276 #ifdef USE_MQ_MESSAGE_QUEUE
    277        mq_close(nDeferedCallMessageQueueId);
    278 #endif
    279 
    280    }
    281 
    282    return result;
    283 }
    284 
    285 NFCSTATUS phDal4Nfc_ConfigRelease(void *pHwRef)
    286 {
    287 
    288    NFCSTATUS result = NFCSTATUS_SUCCESS;
    289    void * pThreadReturn;
    290 
    291    DAL_PRINT("phDal4Nfc_ConfigRelease ");
    292 
    293    if (gDalContext.hw_valid == TRUE)
    294    {
    295        /* Signal the read and write threads to exit.  NOTE: there
    296           actually is no write thread!  :)  */
    297        DAL_PRINT("Stop Reader Thread");
    298        gReadWriteContext.nReadThreadAlive = 0;
    299        gReadWriteContext.nWriteThreadAlive = 0;
    300 
    301        /* Wake up the read thread so it can exit */
    302        DAL_PRINT("Release Read Semaphore");
    303        sem_post(&nfc_read_sem);
    304 
    305        DAL_DEBUG("phDal4Nfc_ConfigRelease - doing pthread_join(%d)",
    306                  gReadWriteContext.nReadThread);
    307        if (pthread_join(gReadWriteContext.nReadThread,  &pThreadReturn) != 0)
    308        {
    309            result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
    310            DAL_PRINT("phDal4Nfc_ConfigRelease  KO");
    311        }
    312 
    313       /* Close the message queue */
    314 #ifdef USE_MQ_MESSAGE_QUEUE
    315        mq_close(nDeferedCallMessageQueueId);
    316 #endif
    317 
    318        /* Shutdown NFC Chip */
    319        phDal4Nfc_Reset(0);
    320 
    321       /* Close the link */
    322       gLinkFunc.close();
    323 
    324       /* Reset the Read Writer context to NULL */
    325       memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
    326       /* Reset the DAL context values to NULL */
    327       memset((void *)&gDalContext,0,sizeof(gDalContext));
    328    }
    329 
    330    gDalContext.hw_valid = FALSE;
    331 
    332    DAL_DEBUG("phDal4Nfc_ConfigRelease(): %04x\n", result);
    333 
    334 
    335    return result;
    336 }
    337 
    338 /*-----------------------------------------------------------------------------
    339 
    340 FUNCTION: phDal4Nfc_Write
    341 
    342 PURPOSE:  DAL Write function.
    343 
    344 -----------------------------------------------------------------------------*/
    345 
    346 NFCSTATUS phDal4Nfc_Write( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
    347 {
    348     NFCSTATUS result = NFCSTATUS_SUCCESS;
    349     static int       MsgType= PHDAL4NFC_WRITE_MESSAGE;
    350     int *            pmsgType=&MsgType;
    351     phDal4Nfc_Message_t      sMsg;
    352     phOsalNfc_Message_t      OsalMsg;
    353 
    354     if ((NULL != pContext) && (NULL != pHwRef)&&
    355         (NULL != pBuffer) && (0 != length))
    356     {
    357         if( gDalContext.hw_valid== TRUE)
    358         {
    359             if((!gReadWriteContext.nWriteBusy)&&
    360                 (!gReadWriteContext.nWaitingOnWrite))
    361             {
    362 		DAL_PRINT("phDal4Nfc_Write() : Temporary buffer !! \n");
    363 		gReadWriteContext.pTempWriteBuffer = (uint8_t*)malloc(length * sizeof(uint8_t));
    364 		/* Make a copy of the passed arguments */
    365 		memcpy(gReadWriteContext.pTempWriteBuffer,pBuffer,length);
    366                 DAL_DEBUG("phDal4Nfc_Write(): %d\n", length);
    367                 gReadWriteContext.pWriteBuffer = gReadWriteContext.pTempWriteBuffer;
    368                 gReadWriteContext.nNbOfBytesToWrite  = length;
    369                 /* Change the write state so that thread can take over the write */
    370                 gReadWriteContext.nWriteBusy = TRUE;
    371                 /* Just set variable here. This is the trigger for the Write thread */
    372                 gReadWriteContext.nWaitingOnWrite = TRUE;
    373                 /* Update the error state */
    374                 result = NFCSTATUS_PENDING;
    375                 /* Send Message and perform physical write in the DefferedCallback */
    376                 /* read completed immediately */
    377 		sMsg.eMsgType= PHDAL4NFC_WRITE_MESSAGE;
    378 		/* Update the state */
    379 		phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
    380 		phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
    381 		memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
    382 		memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
    383             }
    384             else
    385             {
    386                 /* Driver is BUSY with previous Write */
    387                 DAL_PRINT("phDal4Nfc_Write() : Busy \n");
    388                 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BUSY) ;
    389             }
    390         }
    391         else
    392         {
    393             /* TBD :Additional error code : NOT_INITIALISED */
    394             result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
    395         }
    396 
    397     }/*end if-Input parametrs valid-check*/
    398     else
    399     {
    400         result = NFCSTATUS_INVALID_PARAMETER;
    401     }
    402     return result;
    403 }
    404 
    405 /*-----------------------------------------------------------------------------
    406 
    407 FUNCTION: phDal4Nfc_Read
    408 
    409 PURPOSE:  DAL Read  function.
    410 
    411 -----------------------------------------------------------------------------*/
    412 
    413 NFCSTATUS phDal4Nfc_Read( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
    414 {
    415     NFCSTATUS result = NFCSTATUS_SUCCESS;
    416 
    417     if ((NULL != pContext) && (NULL != pHwRef)&&
    418         (NULL != pBuffer) && (0 != length))
    419     {
    420         if ( gDalContext.hw_valid== TRUE)
    421         {
    422             if((!gReadWriteContext.nReadBusy)&&
    423                 (!gReadWriteContext.nWaitingOnRead))
    424             {
    425                 DAL_DEBUG("*****DAl Read called  length : %d\n", length);
    426 
    427                 /* Make a copy of the passed arguments */
    428                 gReadWriteContext.pReadBuffer = pBuffer;
    429                 gReadWriteContext.nNbOfBytesToRead  = length;
    430                 /* Change the Read state so that thread can take over the read */
    431                 gReadWriteContext.nReadBusy = TRUE;
    432                 /* Just set variable here. This is the trigger for the Reader thread */
    433                 gReadWriteContext.nWaitingOnRead = TRUE;
    434                 /* Update the return state */
    435                 result = NFCSTATUS_PENDING;
    436                 /* unlock reader thread */
    437                 sem_post(&nfc_read_sem);
    438             }
    439             else
    440             {
    441                 /* Driver is BUSY with prev Read */
    442                 DAL_PRINT("DAL BUSY\n");
    443                 /* Make a copy of the passed arguments */
    444                 gReadWriteContext.pReadBuffer = pBuffer;
    445                 gReadWriteContext.nNbOfBytesToRead  = length;
    446                 result = NFCSTATUS_PENDING;
    447             }
    448         }
    449         else
    450         {
    451             /* TBD :Additional error code : NOT_INITIALISED */
    452             result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
    453         }
    454     }/*end if-Input parametrs valid-check*/
    455     else
    456     {
    457         result = NFCSTATUS_INVALID_PARAMETER;
    458     }
    459     DAL_DEBUG("*****DAl Read called  result : %x\n", result);
    460     return result;
    461 }
    462 
    463 
    464 /*-----------------------------------------------------------------------------
    465 
    466 FUNCTION: phDal4Nfc_ReadWait
    467 
    468 PURPOSE:  DAL Read wait function.
    469 
    470 -----------------------------------------------------------------------------*/
    471 
    472 NFCSTATUS phDal4Nfc_ReadWait(void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
    473 {
    474    /* not used */
    475    DAL_PRINT("phDal4Nfc_ReadWait");
    476    return 0;
    477 }
    478 /*-----------------------------------------------------------------------------
    479 
    480 FUNCTION: phDal4Nfc_ReadWaitCancel
    481 
    482 PURPOSE: Cancel the Read wait function.
    483 
    484 -----------------------------------------------------------------------------*/
    485 
    486 NFCSTATUS phDal4Nfc_ReadWaitCancel( void *pContext, void *pHwRef)
    487 {
    488    DAL_PRINT("phDal4Nfc_ReadWaitCancel");
    489 
    490    /* unlock read semaphore */
    491    sem_post(&nfc_read_sem);
    492 
    493    return 0;
    494 }
    495 
    496 /*-----------------------------------------------------------------------------
    497 
    498 FUNCTION: phDal4Nfc_Config
    499 
    500 PURPOSE: Configure the serial port.
    501 
    502 -----------------------------------------------------------------------------*/
    503 NFCSTATUS phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void **phwref)
    504 {
    505    NFCSTATUS                       retstatus = NFCSTATUS_SUCCESS;
    506 
    507    DAL_PRINT("phDal4Nfc_Config");
    508 
    509    if ((config == NULL) || (phwref == NULL) || (config->nClientId == -1))
    510       return NFCSTATUS_INVALID_PARAMETER;
    511 
    512    /* Register the link callbacks */
    513    memset(&gLinkFunc, 0, sizeof(phDal4Nfc_link_cbk_interface_t));
    514    switch(config->nLinkType)
    515    {
    516       case ENUM_DAL_LINK_TYPE_COM1:
    517       case ENUM_DAL_LINK_TYPE_COM2:
    518       case ENUM_DAL_LINK_TYPE_COM3:
    519       case ENUM_DAL_LINK_TYPE_COM4:
    520       case ENUM_DAL_LINK_TYPE_COM5:
    521       case ENUM_DAL_LINK_TYPE_USB:
    522       {
    523 	 DAL_PRINT("UART link Config");
    524          /* Uart link interface */
    525          gLinkFunc.init               = phDal4Nfc_uart_initialize;
    526          gLinkFunc.open_from_handle   = phDal4Nfc_uart_set_open_from_handle;
    527          gLinkFunc.is_opened          = phDal4Nfc_uart_is_opened;
    528          gLinkFunc.flush              = phDal4Nfc_uart_flush;
    529          gLinkFunc.close              = phDal4Nfc_uart_close;
    530          gLinkFunc.open_and_configure = phDal4Nfc_uart_open_and_configure;
    531          gLinkFunc.read               = phDal4Nfc_uart_read;
    532          gLinkFunc.write              = phDal4Nfc_uart_write;
    533          gLinkFunc.download           = phDal4Nfc_uart_download;
    534          gLinkFunc.reset              = phDal4Nfc_uart_reset;
    535       }
    536       break;
    537 
    538       case ENUM_DAL_LINK_TYPE_I2C:
    539       {
    540 	 DAL_PRINT("I2C link Config");
    541          /* i2c link interface */
    542          gLinkFunc.init               = phDal4Nfc_i2c_initialize;
    543          gLinkFunc.open_from_handle   = phDal4Nfc_i2c_set_open_from_handle;
    544          gLinkFunc.is_opened          = phDal4Nfc_i2c_is_opened;
    545          gLinkFunc.flush              = phDal4Nfc_i2c_flush;
    546          gLinkFunc.close              = phDal4Nfc_i2c_close;
    547          gLinkFunc.open_and_configure = phDal4Nfc_i2c_open_and_configure;
    548          gLinkFunc.read               = phDal4Nfc_i2c_read;
    549          gLinkFunc.write              = phDal4Nfc_i2c_write;
    550          gLinkFunc.reset              = phDal4Nfc_i2c_reset;
    551          break;
    552       }
    553 
    554       default:
    555       {
    556          /* Shound not happen : Bad parameter */
    557          return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER);
    558       }
    559    }
    560 
    561    gLinkFunc.init(); /* So that link interface can initialize its internal state */
    562    retstatus = gLinkFunc.open_and_configure(config, phwref);
    563    if (retstatus != NFCSTATUS_SUCCESS)
    564       return retstatus;
    565 
    566    /* Iniatilize the DAL context */
    567    (void)memset(&gDalContext,0,sizeof(phDal4Nfc_SContext_t));
    568    pgDalContext = &gDalContext;
    569 
    570    /* Reset the Reader Thread values to NULL */
    571    memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
    572    gReadWriteContext.nReadThreadAlive     = TRUE;
    573    gReadWriteContext.nWriteBusy = FALSE;
    574    gReadWriteContext.nWaitingOnWrite = FALSE;
    575 
    576    /* Prepare the message queue for the defered calls */
    577 #ifdef USE_MQ_MESSAGE_QUEUE
    578    nDeferedCallMessageQueueId = mq_open(MQ_NAME_IDENTIFIER, O_CREAT|O_RDWR, 0666, &MQ_QUEUE_ATTRIBUTES);
    579 #else
    580    nDeferedCallMessageQueueId = config->nClientId;
    581 #endif
    582    /* Start Read and Write Threads */
    583    if(NFCSTATUS_SUCCESS != phDal4Nfc_StartThreads())
    584    {
    585       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED);
    586    }
    587 
    588    gDalContext.hw_valid = TRUE;
    589 
    590    phDal4Nfc_Reset(1);
    591    phDal4Nfc_Reset(0);
    592    phDal4Nfc_Reset(1);
    593 
    594    return NFCSTATUS_SUCCESS;
    595 }
    596 
    597 /*-----------------------------------------------------------------------------
    598 
    599 FUNCTION: phDal4Nfc_Reset
    600 
    601 PURPOSE: Reset the PN544, using the VEN pin
    602 
    603 -----------------------------------------------------------------------------*/
    604 NFCSTATUS phDal4Nfc_Reset(long level)
    605 {
    606    NFCSTATUS	retstatus = NFCSTATUS_SUCCESS;
    607 
    608    DAL_DEBUG("phDal4Nfc_Reset: VEN to %d",level);
    609 
    610    retstatus = gLinkFunc.reset(level);
    611 
    612    return retstatus;
    613 }
    614 
    615 /*-----------------------------------------------------------------------------
    616 
    617 FUNCTION: phDal4Nfc_Download
    618 
    619 PURPOSE: Put the PN544 in download mode, using the GPIO4 pin
    620 
    621 -----------------------------------------------------------------------------*/
    622 NFCSTATUS phDal4Nfc_Download()
    623 {
    624    NFCSTATUS	retstatus = NFCSTATUS_SUCCESS;
    625 
    626    DAL_DEBUG("phDal4Nfc_Download: GPIO4 to %d",1);
    627 
    628    usleep(10000);
    629    retstatus = phDal4Nfc_Reset(2);
    630 
    631    return retstatus;
    632 }
    633 
    634 
    635 
    636 /*-----------------------------------------------------------------------------------
    637                                 DAL INTERNAL IMPLEMENTATION
    638 ------------------------------------------------------------------------------------*/
    639 
    640 
    641 
    642 /**
    643  * \ingroup grp_nfc_dal
    644  *
    645  * \brief DAL Reader thread handler
    646  * This function manages the reads from the link interface. The reads are done from
    647  * this thread to create the asynchronous mecanism. When calling the synchronous
    648  * function phDal4Nfc_Read, the nWaitingOnRead mutex is unlocked and the read
    649  * can be done. Then a client callback is called to send the result.
    650  *
    651  * \param[in]       pArg     A custom argument that can be passed to the thread (not used)
    652  *
    653  * \retval TRUE                                 Thread exiting.
    654  */
    655 
    656 int phDal4Nfc_ReaderThread(void * pArg)
    657 {
    658     char      retvalue;
    659     NFCSTATUS result = NFCSTATUS_SUCCESS;
    660     uint8_t   retry_cnt=0;
    661     void *    memsetRet;
    662 
    663     static int       MsgType= PHDAL4NFC_READ_MESSAGE;
    664     int *     pmsgType=&MsgType;
    665 
    666     phDal4Nfc_Message_t      sMsg;
    667     phOsalNfc_Message_t      OsalMsg ;
    668     int i;
    669     int i2c_error_count;
    670 
    671     pthread_setname_np(pthread_self(), "reader");
    672 
    673     /* Create the overlapped event. Must be closed before exiting
    674     to avoid a handle leak. This event is used READ API and the Reader thread*/
    675 
    676     DAL_PRINT("RX Thread \n");
    677     DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive);
    678     DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead);
    679     while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */
    680     {
    681         /* Check for the read request from user */
    682 	DAL_PRINT("RX Thread Sem Lock\n");
    683         sem_wait(&nfc_read_sem);
    684         DAL_PRINT("RX Thread Sem UnLock\n");
    685 
    686         if (!gReadWriteContext.nReadThreadAlive)
    687         {
    688             /* got the signal that we should exit.  NOTE: we don't
    689                attempt to read below, since the read may block */
    690             break;
    691         }
    692 
    693         /* Issue read operation.*/
    694 
    695     i2c_error_count = 0;
    696 retry:
    697 	gReadWriteContext.nNbOfBytesRead=0;
    698 	DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
    699 	memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);
    700 
    701 	/* Wait for IRQ !!!  */
    702     gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
    703 
    704     /* TODO: Remove this hack
    705      * Reading the value 0x57 indicates a HW I2C error at I2C address 0x57
    706      * (pn544). There should not be false positives because a read of length 1
    707      * must be a HCI length read, and a length of 0x57 is impossible (max is 33).
    708      */
    709     if(gReadWriteContext.nNbOfBytesToRead == 1 && gReadWriteContext.pReadBuffer[0] == 0x57)
    710     {
    711         i2c_error_count++;
    712         DAL_DEBUG("RX Thread Read 0x57 %d times\n", i2c_error_count);
    713         if (i2c_error_count < 5) {
    714             usleep(2000);
    715             goto retry;
    716         }
    717         DAL_PRINT("RX Thread NOTHING TO READ, RECOVER");
    718         phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
    719     }
    720     else
    721     {
    722         i2c_error_count = 0;
    723 #ifdef LOW_LEVEL_TRACES
    724         phOsalNfc_PrintData("Received buffer", (uint16_t)gReadWriteContext.nNbOfBytesRead, gReadWriteContext.pReadBuffer);
    725 #endif
    726         DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
    727         DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
    728         DAL_PRINT("RX Thread ReadBuff[]={ ");
    729         for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
    730         {
    731           DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]);
    732         }
    733         DAL_PRINT("RX Thread }\n");
    734 
    735         /* read completed immediately */
    736         sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE;
    737         /* Update the state */
    738         phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
    739         phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
    740         memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
    741         memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
    742     }
    743 
    744     } /* End of thread Loop*/
    745 
    746     DAL_PRINT("RX Thread  exiting");
    747 
    748     return TRUE;
    749 }
    750 
    751 
    752 
    753 /**
    754  * \ingroup grp_nfc_dal
    755  *
    756  * \brief DAL Start threads function
    757  * This function is called from phDal4Nfc_Config and is responsible of creating the
    758  * reader thread.
    759  *
    760  * \retval NFCSTATUS_SUCCESS                    If success.
    761  * \retval NFCSTATUS_FAILED                     Can not create thread or retreive its attributes
    762  */
    763 NFCSTATUS phDal4Nfc_StartThreads(void)
    764 {
    765     pthread_attr_t nReadThreadAttributes;
    766     pthread_attr_t nWriteThreadAttributes;
    767     int ret;
    768 
    769     if(sem_init(&nfc_read_sem, 0, 0) == -1)
    770     {
    771       DAL_PRINT("NFC Init Semaphore creation Error");
    772       return -1;
    773     }
    774 
    775     ret = pthread_create(&gReadWriteContext.nReadThread, NULL,  (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread,  (void*) "dal_read_thread");
    776     if(ret != 0)
    777         return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
    778 
    779     return NFCSTATUS_SUCCESS;
    780 }
    781 
    782 /**
    783  * \ingroup grp_nfc_dal
    784  *
    785  * \brief DAL fill message function
    786  * Internal messages management. This function fills message structure
    787  * depending on message types.
    788  *
    789  * \param[in, out]       pDalMsg     DAL message to fill
    790  * \param[in, out]       pOsalMsg    OSAL message to fill
    791  *
    792  */
    793 void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg)
    794 {
    795   if(NULL != pgDalHwContext)
    796   {
    797     if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE)
    798     {
    799         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesWritten;
    800         pDalMsg->transactInfo.buffer = NULL;
    801         pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
    802         pDalMsg->pHwRef  = pgDalHwContext;
    803         pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete;
    804         pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
    805         pOsalMsg->pMsgData = pDalMsg;
    806         return;
    807     }
    808     else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE)
    809     {
    810         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesRead;
    811         pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer;
    812         pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt;
    813     }
    814     else
    815     {
    816         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesReadWait;
    817         pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer;
    818         pDalMsg->pContext= pgDalContext;
    819     }
    820     pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
    821     pDalMsg->pHwRef  = pgDalHwContext;
    822     pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete;
    823     /*map to OSAL msg format*/
    824     pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
    825     pOsalMsg->pMsgData = pDalMsg;
    826   }
    827 
    828 }
    829 
    830 /**
    831  * \ingroup grp_nfc_dal
    832  *
    833  * \brief DAL deferred callback function
    834  * Generic handler function called by a client thread when reading a message from the queue.
    835  * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall
    836  *
    837   * \param[in]       params    Parameter that will be passed to the client function.
    838  *
    839  */
    840 void phDal4Nfc_DeferredCb (void  *params)
    841 {
    842     int*    pParam=NULL;
    843     int     i;
    844     phNfc_sTransactionInfo_t TransactionInfo;
    845 
    846     pParam=(int*)params;
    847 
    848     switch(*pParam)
    849     {
    850         case PHDAL4NFC_READ_MESSAGE:
    851             DAL_PRINT(" Dal deferred read called \n");
    852             TransactionInfo.buffer=gReadWriteContext.pReadBuffer;
    853             TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead;
    854             TransactionInfo.status=NFCSTATUS_SUCCESS;
    855             gReadWriteContext.nReadBusy = FALSE;
    856 
    857 
    858             /*  Reset flag so that another opertion can be issued.*/
    859             gReadWriteContext.nWaitingOnRead = FALSE;
    860             if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete))
    861             {
    862                 pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt,
    863                                                         pgDalHwContext,&TransactionInfo);
    864             }
    865 
    866             break;
    867         case PHDAL4NFC_WRITE_MESSAGE:
    868             DAL_PRINT(" Dal deferred write called \n");
    869 
    870 #ifdef LOW_LEVEL_TRACES
    871             phOsalNfc_PrintData("Send buffer", (uint16_t)gReadWriteContext.nNbOfBytesToWrite, gReadWriteContext.pWriteBuffer);
    872 #endif
    873 
    874             /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
    875             /* Make a Physical WRITE */
    876             /* NOTE: need to usleep(3000) here if the write is for SWP */
    877             usleep(500);  /* NXP advise 500us sleep required between I2C writes */
    878             gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
    879             if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
    880             {
    881                 /* controller may be in standby. do it again! */
    882                 usleep(10000); /* wait 10 ms */
    883                 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
    884             }
    885             if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
    886             {
    887                 /* Report write failure or timeout */
    888                 DAL_PRINT(" Physical Write Error !!! \n");
    889                 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
    890                 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR);
    891             }
    892             else
    893             {
    894                 DAL_PRINT(" Physical Write Success \n");
    895 	        TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
    896 	        TransactionInfo.status=NFCSTATUS_SUCCESS;
    897                 DAL_PRINT("WriteBuff[]={ ");
    898                 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
    899                 {
    900                   DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
    901                 }
    902                 DAL_PRINT("}\n");
    903 
    904 		// Free TempWriteBuffer
    905 		if(gReadWriteContext.pTempWriteBuffer != NULL)
    906 		{
    907 		    free(gReadWriteContext.pTempWriteBuffer);
    908 		}
    909             }
    910             /* Reset Write context */
    911             gReadWriteContext.nWriteBusy = FALSE;
    912             gReadWriteContext.nWaitingOnWrite = FALSE;
    913 
    914             /* call LLC callback */
    915             if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete))
    916             {
    917                 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt,
    918                                                     pgDalHwContext,&TransactionInfo);
    919             }
    920             break;
    921         default:
    922             break;
    923     }
    924 }
    925 
    926 /**
    927  * \ingroup grp_nfc_dal
    928  *
    929  * \brief DAL deferred call function
    930  * This function will enable to call the callback client asyncronously and in the client context.
    931  * It will post a message in a queue that will be processed by a client thread.
    932  *
    933  * \param[in]       func     The function to call when message is read from the queue
    934  * \param[in]       param    Parameter that will be passed to the 'func' function.
    935  *
    936  */
    937 void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param)
    938 {
    939     int                retvalue = 0;
    940     phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper;
    941     phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage;
    942     static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead;
    943     static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite;
    944 
    945 #ifdef USE_MQ_MESSAGE_QUEUE
    946     nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
    947     nDeferedMessage.def_call = func;
    948     nDeferedMessage.params   = param;
    949     retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0);
    950 #else
    951     if(PHDAL4NFC_READ_MESSAGE==(* (int*)param))
    952     {
    953         pDeferedMessage = &nDeferedMessageRead;
    954     }
    955     else
    956     {
    957         pDeferedMessage = &nDeferedMessageWrite;
    958     }
    959     nDeferedMessageWrapper.mtype = 1;
    960     nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
    961     pDeferedMessage->pCallback = func;
    962     pDeferedMessage->pParameter = param;
    963     nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage;
    964     nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t);
    965     retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);
    966 #endif
    967 
    968 }
    969 
    970 #undef _DAL_4_NFC_C
    971