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