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