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