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