phDal4Nfc.c revision a12acb119fa8cda91ca23d191b41b9438402e4d1
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*/
59typedef 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
89typedef void   (*pphDal4Nfc_DeferFuncPointer_t) (void * );
90typedef void * (*pphDal4Nfc_thread_handler_t)   (void * pParam);
91
92
93/*-----------------------------------------------------------------------------------
94                                      VARIABLES
95------------------------------------------------------------------------------------*/
96static phDal4Nfc_RdWr_t               gReadWriteContext;
97static phDal4Nfc_SContext_t           gDalContext;
98static pphDal4Nfc_SContext_t          pgDalContext;
99static phHal_sHwReference_t   *       pgDalHwContext;
100static sem_t                          nfc_read_sem;
101static int                            low_level_traces;
102#ifdef USE_MQ_MESSAGE_QUEUE
103static phDal4Nfc_DeferredCall_Msg_t   nDeferedMessage;
104static mqd_t                          nDeferedCallMessageQueueId;
105
106#else
107int                            nDeferedCallMessageQueueId = 0;
108#endif
109static phDal4Nfc_link_cbk_interface_t gLinkFunc;
110/*-----------------------------------------------------------------------------------
111                                     PROTOTYPES
112------------------------------------------------------------------------------------*/
113static void      phDal4Nfc_DeferredCb     (void  *params);
114static NFCSTATUS phDal4Nfc_StartThreads   (void);
115static void      phDal4Nfc_FillMsg        (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
116
117/*-----------------------------------------------------------------------------------
118                                DAL API IMPLEMENTATION
119------------------------------------------------------------------------------------*/
120
121static 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
148FUNCTION: phDal4Nfc_Register
149
150PURPOSE:  DAL register function.
151
152-----------------------------------------------------------------------------*/
153NFCSTATUS 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
201FUNCTION: phDal4Nfc_Unregister
202
203PURPOSE:  DAL unregister function.
204
205-----------------------------------------------------------------------------*/
206NFCSTATUS 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
236FUNCTION: phDal4Nfc_Init
237
238PURPOSE:  DAL Init function.
239
240-----------------------------------------------------------------------------*/
241NFCSTATUS 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
284FUNCTION: phDal4Nfc_Shutdown
285
286PURPOSE:  DAL Shutdown function.
287
288-----------------------------------------------------------------------------*/
289
290NFCSTATUS 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
313NFCSTATUS 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
371FUNCTION: phDal4Nfc_Write
372
373PURPOSE:  DAL Write function.
374
375-----------------------------------------------------------------------------*/
376
377NFCSTATUS 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
438FUNCTION: phDal4Nfc_Read
439
440PURPOSE:  DAL Read  function.
441
442-----------------------------------------------------------------------------*/
443
444NFCSTATUS 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
497FUNCTION: phDal4Nfc_ReadWait
498
499PURPOSE:  DAL Read wait function.
500
501-----------------------------------------------------------------------------*/
502
503NFCSTATUS 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
511FUNCTION: phDal4Nfc_ReadWaitCancel
512
513PURPOSE: Cancel the Read wait function.
514
515-----------------------------------------------------------------------------*/
516
517NFCSTATUS 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
529FUNCTION: phDal4Nfc_Config
530
531PURPOSE: Configure the serial port.
532
533-----------------------------------------------------------------------------*/
534NFCSTATUS 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
649FUNCTION: phDal4Nfc_Reset
650
651PURPOSE: Reset the PN544, using the VEN pin
652
653-----------------------------------------------------------------------------*/
654NFCSTATUS 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
667FUNCTION: phDal4Nfc_Download
668
669PURPOSE: Put the PN544 in download mode, using the GPIO4 pin
670
671-----------------------------------------------------------------------------*/
672NFCSTATUS 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
706int 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    if (gDalContext.pDev != NULL) {
722        i2c_workaround = gDalContext.pDev->enable_i2c_workaround;
723    } else {
724        ALOGE("gDalContext.pDev is not set");
725        return NFCSTATUS_FAILED;
726    }
727
728    pthread_setname_np(pthread_self(), "reader");
729
730    /* Create the overlapped event. Must be closed before exiting
731    to avoid a handle leak. This event is used READ API and the Reader thread*/
732
733    DAL_PRINT("RX Thread \n");
734    DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive);
735    DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead);
736    while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */
737    {
738        /* Check for the read request from user */
739	DAL_PRINT("RX Thread Sem Lock\n");
740        sem_wait(&nfc_read_sem);
741        DAL_PRINT("RX Thread Sem UnLock\n");
742
743        if (!gReadWriteContext.nReadThreadAlive)
744        {
745            /* got the signal that we should exit.  NOTE: we don't
746               attempt to read below, since the read may block */
747            break;
748        }
749
750        /* Issue read operation.*/
751
752    i2c_error_count = 0;
753retry:
754	gReadWriteContext.nNbOfBytesRead=0;
755	DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
756	memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);
757
758	/* Wait for IRQ !!!  */
759    gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
760
761    /* Reading the value 0x57 indicates a HW I2C error at I2C address 0x57
762     * (pn544). There should not be false positives because a read of length 1
763     * must be a HCI length read, and a length of 0x57 is impossible (max is 33).
764     */
765    if(i2c_workaround && gReadWriteContext.nNbOfBytesToRead == 1 &&
766            gReadWriteContext.pReadBuffer[0] == 0x57)
767    {
768        i2c_error_count++;
769        DAL_DEBUG("RX Thread Read 0x57 %d times\n", i2c_error_count);
770        if (i2c_error_count < 5) {
771            usleep(2000);
772            goto retry;
773        }
774        DAL_PRINT("RX Thread NOTHING TO READ, RECOVER");
775        phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
776    }
777    else
778    {
779        i2c_error_count = 0;
780
781        if (low_level_traces)
782        {
783             phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead,
784                    gReadWriteContext.pReadBuffer, low_level_traces);
785        }
786        DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
787        DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
788/*      DAL_PRINT("RX Thread ReadBuff[]={ ");
789        for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
790        {
791          DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]);
792        }
793        DAL_PRINT("RX Thread }\n"); */
794
795        /* read completed immediately */
796        sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE;
797        /* Update the state */
798        phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
799        phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
800        memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
801        memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
802    }
803
804    } /* End of thread Loop*/
805
806    DAL_PRINT("RX Thread  exiting");
807
808    return TRUE;
809}
810
811
812
813/**
814 * \ingroup grp_nfc_dal
815 *
816 * \brief DAL Start threads function
817 * This function is called from phDal4Nfc_Config and is responsible of creating the
818 * reader thread.
819 *
820 * \retval NFCSTATUS_SUCCESS                    If success.
821 * \retval NFCSTATUS_FAILED                     Can not create thread or retreive its attributes
822 */
823NFCSTATUS phDal4Nfc_StartThreads(void)
824{
825    pthread_attr_t nReadThreadAttributes;
826    pthread_attr_t nWriteThreadAttributes;
827    int ret;
828
829    if(sem_init(&nfc_read_sem, 0, 0) == -1)
830    {
831      DAL_PRINT("NFC Init Semaphore creation Error");
832      return -1;
833    }
834
835    ret = pthread_create(&gReadWriteContext.nReadThread, NULL,  (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread,  (void*) "dal_read_thread");
836    if(ret != 0)
837        return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
838
839    return NFCSTATUS_SUCCESS;
840}
841
842/**
843 * \ingroup grp_nfc_dal
844 *
845 * \brief DAL fill message function
846 * Internal messages management. This function fills message structure
847 * depending on message types.
848 *
849 * \param[in, out]       pDalMsg     DAL message to fill
850 * \param[in, out]       pOsalMsg    OSAL message to fill
851 *
852 */
853void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg)
854{
855  if(NULL != pgDalHwContext)
856  {
857    if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE)
858    {
859        pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesWritten;
860        pDalMsg->transactInfo.buffer = NULL;
861        pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
862        pDalMsg->pHwRef  = pgDalHwContext;
863        pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete;
864        pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
865        pOsalMsg->pMsgData = pDalMsg;
866        return;
867    }
868    else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE)
869    {
870        pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesRead;
871        pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer;
872        pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt;
873    }
874    else
875    {
876        pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesReadWait;
877        pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer;
878        pDalMsg->pContext= pgDalContext;
879    }
880    pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
881    pDalMsg->pHwRef  = pgDalHwContext;
882    pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete;
883    /*map to OSAL msg format*/
884    pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
885    pOsalMsg->pMsgData = pDalMsg;
886  }
887
888}
889
890/**
891 * \ingroup grp_nfc_dal
892 *
893 * \brief DAL deferred callback function
894 * Generic handler function called by a client thread when reading a message from the queue.
895 * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall
896 *
897  * \param[in]       params    Parameter that will be passed to the client function.
898 *
899 */
900void phDal4Nfc_DeferredCb (void  *params)
901{
902    int*    pParam=NULL;
903    int     i;
904    phNfc_sTransactionInfo_t TransactionInfo;
905
906    pParam=(int*)params;
907
908    switch(*pParam)
909    {
910        case PHDAL4NFC_READ_MESSAGE:
911            DAL_PRINT(" Dal deferred read called \n");
912            TransactionInfo.buffer=gReadWriteContext.pReadBuffer;
913            TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead;
914            if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) {
915                TransactionInfo.status=NFCSTATUS_SUCCESS;
916            } else {
917                TransactionInfo.status=NFCSTATUS_READ_FAILED;
918            }
919            gReadWriteContext.nReadBusy = FALSE;
920
921
922            /*  Reset flag so that another opertion can be issued.*/
923            gReadWriteContext.nWaitingOnRead = FALSE;
924            if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete))
925            {
926                pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt,
927                                                        pgDalHwContext,&TransactionInfo);
928            }
929
930            break;
931        case PHDAL4NFC_WRITE_MESSAGE:
932            DAL_PRINT(" Dal deferred write called \n");
933
934            if(low_level_traces)
935            {
936                phOsalNfc_PrintData("SEND", (uint16_t)gReadWriteContext.nNbOfBytesToWrite,
937                        gReadWriteContext.pWriteBuffer, low_level_traces);
938            }
939
940            /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
941            /* Make a Physical WRITE */
942            /* NOTE: need to usleep(3000) here if the write is for SWP */
943            usleep(500);  /* NXP advise 500us sleep required between I2C writes */
944            gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
945            if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
946            {
947                /* controller may be in standby. do it again! */
948                usleep(10000); /* wait 10 ms */
949                gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
950            }
951            if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
952            {
953                /* Report write failure or timeout */
954                DAL_PRINT(" Physical Write Error !!! \n");
955                TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
956                TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR);
957            }
958            else
959            {
960                DAL_PRINT(" Physical Write Success \n");
961	        TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
962	        TransactionInfo.status=NFCSTATUS_SUCCESS;
963/*              DAL_PRINT("WriteBuff[]={ ");
964                for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
965                {
966                  DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
967                }
968                DAL_PRINT("}\n"); */
969
970		// Free TempWriteBuffer
971		if(gReadWriteContext.pTempWriteBuffer != NULL)
972		{
973		    free(gReadWriteContext.pTempWriteBuffer);
974		}
975            }
976            /* Reset Write context */
977            gReadWriteContext.nWriteBusy = FALSE;
978            gReadWriteContext.nWaitingOnWrite = FALSE;
979
980            /* call LLC callback */
981            if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete))
982            {
983                pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt,
984                                                    pgDalHwContext,&TransactionInfo);
985            }
986            break;
987        default:
988            break;
989    }
990}
991
992/**
993 * \ingroup grp_nfc_dal
994 *
995 * \brief DAL deferred call function
996 * This function will enable to call the callback client asyncronously and in the client context.
997 * It will post a message in a queue that will be processed by a client thread.
998 *
999 * \param[in]       func     The function to call when message is read from the queue
1000 * \param[in]       param    Parameter that will be passed to the 'func' function.
1001 *
1002 */
1003void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param)
1004{
1005    int                retvalue = 0;
1006    phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper;
1007    phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage;
1008    static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead;
1009    static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite;
1010
1011#ifdef USE_MQ_MESSAGE_QUEUE
1012    nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
1013    nDeferedMessage.def_call = func;
1014    nDeferedMessage.params   = param;
1015    retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0);
1016#else
1017    if(PHDAL4NFC_READ_MESSAGE==(* (int*)param))
1018    {
1019        pDeferedMessage = &nDeferedMessageRead;
1020    }
1021    else
1022    {
1023        pDeferedMessage = &nDeferedMessageWrite;
1024    }
1025    nDeferedMessageWrapper.mtype = 1;
1026    nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
1027    pDeferedMessage->pCallback = func;
1028    pDeferedMessage->pParameter = param;
1029    nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage;
1030    nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t);
1031    retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);
1032#endif
1033
1034}
1035
1036#undef _DAL_4_NFC_C
1037