• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
refresh_low_level_traces()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  -----------------------------------------------------------------------------*/
phDal4Nfc_Register(phNfcIF_sReference_t * psRefer,phNfcIF_sCallBack_t if_cb,void * psIFConf)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  -----------------------------------------------------------------------------*/
phDal4Nfc_Unregister(void * pContext,void * pHwRef)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  -----------------------------------------------------------------------------*/
phDal4Nfc_Init(void * pContext,void * pHwRef)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  
phDal4Nfc_Shutdown(void * pContext,void * pHwRef)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  
phDal4Nfc_ConfigRelease(void * pHwRef)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  
phDal4Nfc_Write(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)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  
phDal4Nfc_Read(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)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  
phDal4Nfc_ReadWait(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)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  
phDal4Nfc_ReadWaitCancel(void * pContext,void * pHwRef)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  -----------------------------------------------------------------------------*/
phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void ** phwref)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  -----------------------------------------------------------------------------*/
phDal4Nfc_Reset(long level)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  -----------------------------------------------------------------------------*/
phDal4Nfc_Download()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  
phDal4Nfc_ReaderThread(void * pArg)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   */
phDal4Nfc_StartThreads(void)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   */
phDal4Nfc_FillMsg(phDal4Nfc_Message_t * pDalMsg,phOsalNfc_Message_t * pOsalMsg)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   */
phDal4Nfc_DeferredCb(void * params)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   */
phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func,void * param)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