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