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