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    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;
762retry:
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 */
834NFCSTATUS 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 */
864void 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 */
911void 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 */
1014void 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