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