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