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