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