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