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