• 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 #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*/
61 typedef 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 
91 typedef void   (*pphDal4Nfc_DeferFuncPointer_t) (void * );
92 typedef void * (*pphDal4Nfc_thread_handler_t)   (void * pParam);
93 
94 
95 /*-----------------------------------------------------------------------------------
96                                       VARIABLES
97 ------------------------------------------------------------------------------------*/
98 static phDal4Nfc_RdWr_t               gReadWriteContext;
99 static phDal4Nfc_SContext_t           gDalContext;
100 static pphDal4Nfc_SContext_t          pgDalContext;
101 static phHal_sHwReference_t   *       pgDalHwContext;
102 static sem_t                          nfc_read_sem;
103 static int                            low_level_traces;
104 #ifdef USE_MQ_MESSAGE_QUEUE
105 static phDal4Nfc_DeferredCall_Msg_t   nDeferedMessage;
106 static mqd_t                          nDeferedCallMessageQueueId;
107 
108 #else
109 int                            nDeferedCallMessageQueueId = 0;
110 #endif
111 static phDal4Nfc_link_cbk_interface_t gLinkFunc;
112 /*-----------------------------------------------------------------------------------
113                                      PROTOTYPES
114 ------------------------------------------------------------------------------------*/
115 static void      phDal4Nfc_DeferredCb     (void  *params);
116 static NFCSTATUS phDal4Nfc_StartThreads   (void);
117 static void      phDal4Nfc_FillMsg        (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
118 
119 /*-----------------------------------------------------------------------------------
120                                 DAL API IMPLEMENTATION
121 ------------------------------------------------------------------------------------*/
122 
refresh_low_level_traces()123 static 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 
150 FUNCTION: phDal4Nfc_Register
151 
152 PURPOSE:  DAL register function.
153 
154 -----------------------------------------------------------------------------*/
phDal4Nfc_Register(phNfcIF_sReference_t * psRefer,phNfcIF_sCallBack_t if_cb,void * psIFConf)155 NFCSTATUS 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 
203 FUNCTION: phDal4Nfc_Unregister
204 
205 PURPOSE:  DAL unregister function.
206 
207 -----------------------------------------------------------------------------*/
phDal4Nfc_Unregister(void * pContext,void * pHwRef)208 NFCSTATUS 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 
238 FUNCTION: phDal4Nfc_Init
239 
240 PURPOSE:  DAL Init function.
241 
242 -----------------------------------------------------------------------------*/
phDal4Nfc_Init(void * pContext,void * pHwRef)243 NFCSTATUS 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 
286 FUNCTION: phDal4Nfc_Shutdown
287 
288 PURPOSE:  DAL Shutdown function.
289 
290 -----------------------------------------------------------------------------*/
291 
phDal4Nfc_Shutdown(void * pContext,void * pHwRef)292 NFCSTATUS 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 
phDal4Nfc_ConfigRelease(void * pHwRef)315 NFCSTATUS 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 
370 FUNCTION: phDal4Nfc_Write
371 
372 PURPOSE:  DAL Write function.
373 
374 -----------------------------------------------------------------------------*/
375 
phDal4Nfc_Write(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)376 NFCSTATUS 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 
437 FUNCTION: phDal4Nfc_Read
438 
439 PURPOSE:  DAL Read  function.
440 
441 -----------------------------------------------------------------------------*/
442 
phDal4Nfc_Read(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)443 NFCSTATUS 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 
496 FUNCTION: phDal4Nfc_ReadWait
497 
498 PURPOSE:  DAL Read wait function.
499 
500 -----------------------------------------------------------------------------*/
501 
phDal4Nfc_ReadWait(void * pContext,void * pHwRef,uint8_t * pBuffer,uint16_t length)502 NFCSTATUS 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 
510 FUNCTION: phDal4Nfc_ReadWaitCancel
511 
512 PURPOSE: Cancel the Read wait function.
513 
514 -----------------------------------------------------------------------------*/
515 
phDal4Nfc_ReadWaitCancel(void * pContext,void * pHwRef)516 NFCSTATUS 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 
528 FUNCTION: phDal4Nfc_Config
529 
530 PURPOSE: Configure the serial port.
531 
532 -----------------------------------------------------------------------------*/
phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void ** phwref)533 NFCSTATUS 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 
628 FUNCTION: phDal4Nfc_Reset
629 
630 PURPOSE: Reset the PN544, using the VEN pin
631 
632 -----------------------------------------------------------------------------*/
phDal4Nfc_Reset(long level)633 NFCSTATUS 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 
646 FUNCTION: phDal4Nfc_Download
647 
648 PURPOSE: Put the PN544 in download mode, using the GPIO4 pin
649 
650 -----------------------------------------------------------------------------*/
phDal4Nfc_Download()651 NFCSTATUS 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 
phDal4Nfc_ReaderThread(void * pArg)685 int 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         gReadWriteContext.nNbOfBytesRead=0;
724         DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
725         memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);
726 
727         /* Wait for IRQ !!!  */
728         gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
729 
730         if (low_level_traces)
731         {
732              phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead,
733                     gReadWriteContext.pReadBuffer, low_level_traces);
734         }
735         DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
736         DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
737 
738         /* read completed immediately */
739         sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE;
740         /* Update the state */
741         phDal4Nfc_FillMsg(&sMsg,&OsalMsg);
742         phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType);
743         memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t));
744         memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t));
745 
746     } /* End of thread Loop*/
747 
748     DAL_PRINT("RX Thread  exiting");
749 
750     return TRUE;
751 }
752 
753 
754 
755 /**
756  * \ingroup grp_nfc_dal
757  *
758  * \brief DAL Start threads function
759  * This function is called from phDal4Nfc_Config and is responsible of creating the
760  * reader thread.
761  *
762  * \retval NFCSTATUS_SUCCESS                    If success.
763  * \retval NFCSTATUS_FAILED                     Can not create thread or retreive its attributes
764  */
phDal4Nfc_StartThreads(void)765 NFCSTATUS phDal4Nfc_StartThreads(void)
766 {
767     pthread_attr_t nReadThreadAttributes;
768     pthread_attr_t nWriteThreadAttributes;
769     int ret;
770 
771     if(sem_init(&nfc_read_sem, 0, 0) == -1)
772     {
773       DAL_PRINT("NFC Init Semaphore creation Error");
774       return -1;
775     }
776 
777     ret = pthread_create(&gReadWriteContext.nReadThread, NULL,  (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread,  (void*) "dal_read_thread");
778     if(ret != 0)
779         return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED));
780 
781     return NFCSTATUS_SUCCESS;
782 }
783 
784 /**
785  * \ingroup grp_nfc_dal
786  *
787  * \brief DAL fill message function
788  * Internal messages management. This function fills message structure
789  * depending on message types.
790  *
791  * \param[in, out]       pDalMsg     DAL message to fill
792  * \param[in, out]       pOsalMsg    OSAL message to fill
793  *
794  */
phDal4Nfc_FillMsg(phDal4Nfc_Message_t * pDalMsg,phOsalNfc_Message_t * pOsalMsg)795 void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg)
796 {
797   if(NULL != pgDalHwContext)
798   {
799     if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE)
800     {
801         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesWritten;
802         pDalMsg->transactInfo.buffer = NULL;
803         pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
804         pDalMsg->pHwRef  = pgDalHwContext;
805         pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete;
806         pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
807         pOsalMsg->pMsgData = pDalMsg;
808         return;
809     }
810     else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE)
811     {
812         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesRead;
813         pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer;
814         pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt;
815     }
816     else
817     {
818         pDalMsg->transactInfo.length  = (uint8_t)gReadWriteContext.nNbOfBytesReadWait;
819         pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer;
820         pDalMsg->pContext= pgDalContext;
821     }
822     pDalMsg->transactInfo.status  = NFCSTATUS_SUCCESS;
823     pDalMsg->pHwRef  = pgDalHwContext;
824     pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete;
825     /*map to OSAL msg format*/
826     pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE;
827     pOsalMsg->pMsgData = pDalMsg;
828   }
829 
830 }
831 
832 /**
833  * \ingroup grp_nfc_dal
834  *
835  * \brief DAL deferred callback function
836  * Generic handler function called by a client thread when reading a message from the queue.
837  * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall
838  *
839   * \param[in]       params    Parameter that will be passed to the client function.
840  *
841  */
phDal4Nfc_DeferredCb(void * params)842 void phDal4Nfc_DeferredCb (void  *params)
843 {
844     int*    pParam=NULL;
845     int     i;
846     phNfc_sTransactionInfo_t TransactionInfo;
847 
848     pParam=(int*)params;
849 
850     switch(*pParam)
851     {
852         case PHDAL4NFC_READ_MESSAGE:
853             DAL_PRINT(" Dal deferred read called \n");
854             TransactionInfo.buffer=gReadWriteContext.pReadBuffer;
855             TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead;
856             if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) {
857                 TransactionInfo.status=NFCSTATUS_SUCCESS;
858             } else {
859                 TransactionInfo.status=NFCSTATUS_READ_FAILED;
860             }
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", (uint16_t)gReadWriteContext.nNbOfBytesToWrite,
879                         gReadWriteContext.pWriteBuffer, low_level_traces);
880             }
881 
882             /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
883             /* Make a Physical WRITE */
884             /* NOTE: need to usleep(3000) here if the write is for SWP */
885             usleep(500);  /* NXP advise 500us sleep required between I2C writes */
886             gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
887             if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
888             {
889                 /* controller may be in standby. do it again! */
890                 usleep(10000); /* wait 10 ms */
891                 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite);
892             }
893             if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite)
894             {
895                 /* Report write failure or timeout */
896                 DAL_PRINT(" Physical Write Error !!! \n");
897                 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
898                 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR);
899             }
900             else
901             {
902                 DAL_PRINT(" Physical Write Success \n");
903 	        TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten;
904 	        TransactionInfo.status=NFCSTATUS_SUCCESS;
905 /*              DAL_PRINT("WriteBuff[]={ ");
906                 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
907                 {
908                   DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
909                 }
910                 DAL_PRINT("}\n"); */
911 
912 		// Free TempWriteBuffer
913 		if(gReadWriteContext.pTempWriteBuffer != NULL)
914 		{
915 		    free(gReadWriteContext.pTempWriteBuffer);
916 		}
917             }
918             /* Reset Write context */
919             gReadWriteContext.nWriteBusy = FALSE;
920             gReadWriteContext.nWaitingOnWrite = FALSE;
921 
922             /* call LLC callback */
923             if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete))
924             {
925                 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt,
926                                                     pgDalHwContext,&TransactionInfo);
927             }
928             break;
929         default:
930             break;
931     }
932 }
933 
934 /**
935  * \ingroup grp_nfc_dal
936  *
937  * \brief DAL deferred call function
938  * This function will enable to call the callback client asyncronously and in the client context.
939  * It will post a message in a queue that will be processed by a client thread.
940  *
941  * \param[in]       func     The function to call when message is read from the queue
942  * \param[in]       param    Parameter that will be passed to the 'func' function.
943  *
944  */
phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func,void * param)945 void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param)
946 {
947     int                retvalue = 0;
948     phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper;
949     phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage;
950     static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead;
951     static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite;
952 
953 #ifdef USE_MQ_MESSAGE_QUEUE
954     nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
955     nDeferedMessage.def_call = func;
956     nDeferedMessage.params   = param;
957     retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0);
958 #else
959     if(PHDAL4NFC_READ_MESSAGE==(* (int*)param))
960     {
961         pDeferedMessage = &nDeferedMessageRead;
962     }
963     else
964     {
965         pDeferedMessage = &nDeferedMessageWrite;
966     }
967     nDeferedMessageWrapper.mtype = 1;
968     nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE;
969     pDeferedMessage->pCallback = func;
970     pDeferedMessage->pParameter = param;
971     nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage;
972     nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t);
973     retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0);
974 #endif
975 
976 }
977 
978 #undef _DAL_4_NFC_C
979