blob: 8683a17e32b1e0bf13083bae55fdb9f65285a3c4 [file] [log] [blame]
Nick Pelly5d9927b2010-09-23 12:47:58 -07001/*
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>
Daniel Tomase5201c12011-04-20 17:28:16 -070033#include <stdlib.h>
Nick Pelly5d9927b2010-09-23 12:47:58 -070034#ifdef ANDROID
35#include <linux/ipc.h>
Nick Pelly4812a722011-06-07 10:37:09 -070036#include <cutils/log.h>
37#include <cutils/properties.h> // for property_get
Nick Pelly5d9927b2010-09-23 12:47:58 -070038#else
39#include <sys/msg.h>
40#endif
Jeff Hamiltone7f38d32010-10-27 21:47:04 -050041#include <semaphore.h>
Nick Pelly5d9927b2010-09-23 12:47:58 -070042#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>
Martijn Coenenb99be652011-11-02 15:58:37 -070051#include <hardware/hardware.h>
52#include <hardware/nfc.h>
Nick Pelly5d9927b2010-09-23 12:47:58 -070053
Nick Pelly5d9927b2010-09-23 12:47:58 -070054
55/*-----------------------------------------------------------------------------------
56 TYPES
57------------------------------------------------------------------------------------*/
58/*structure holds members related for both read and write operations*/
59typedef struct Dal_RdWr_st
60{
61 /* Read members */
62 pthread_t nReadThread; /* Read thread Hanlde */
Nick Pelly5d9927b2010-09-23 12:47:58 -070063 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 */
Nick Pelly5d9927b2010-09-23 12:47:58 -070071 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 */
Nick Pelly5d9927b2010-09-23 12:47:58 -070080 uint8_t * pWriteBuffer; /* Write local buffer */
Jeff Hamilton3e987672010-10-27 21:29:08 -050081 uint8_t * pTempWriteBuffer; /* Temp Write local buffer */
Nick Pelly5d9927b2010-09-23 12:47:58 -070082 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
89typedef void (*pphDal4Nfc_DeferFuncPointer_t) (void * );
90typedef void * (*pphDal4Nfc_thread_handler_t) (void * pParam);
91
92
93/*-----------------------------------------------------------------------------------
94 VARIABLES
95------------------------------------------------------------------------------------*/
96static phDal4Nfc_RdWr_t gReadWriteContext;
97static phDal4Nfc_SContext_t gDalContext;
98static pphDal4Nfc_SContext_t pgDalContext;
99static phHal_sHwReference_t * pgDalHwContext;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500100static sem_t nfc_read_sem;
Nick Pelly4812a722011-06-07 10:37:09 -0700101static int low_level_traces;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700102#ifdef USE_MQ_MESSAGE_QUEUE
103static phDal4Nfc_DeferredCall_Msg_t nDeferedMessage;
104static mqd_t nDeferedCallMessageQueueId;
105
106#else
107int nDeferedCallMessageQueueId = 0;
108#endif
109static phDal4Nfc_link_cbk_interface_t gLinkFunc;
110/*-----------------------------------------------------------------------------------
111 PROTOTYPES
112------------------------------------------------------------------------------------*/
113static void phDal4Nfc_DeferredCb (void *params);
114static NFCSTATUS phDal4Nfc_StartThreads (void);
115static void phDal4Nfc_FillMsg (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg);
116
117/*-----------------------------------------------------------------------------------
118 DAL API IMPLEMENTATION
119------------------------------------------------------------------------------------*/
120
Nick Pelly4812a722011-06-07 10:37:09 -0700121static void refresh_low_level_traces() {
Nick Pelly4812a722011-06-07 10:37:09 -0700122#ifdef LOW_LEVEL_TRACES
123 low_level_traces = 1;
Nick Pelly23482d02011-06-17 15:44:30 -0700124 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
Nick Pelly5ea62ad2011-10-19 18:36:47 -0700136 property_get("debug.nfc.LOW_LEVEL_TRACES", value, "0");
Nick Pelly23482d02011-06-17 15:44:30 -0700137 if (value[0]) {
Nick Pelly5ea62ad2011-10-19 18:36:47 -0700138 low_level_traces = atoi(value);
Nick Pelly23482d02011-06-17 15:44:30 -0700139 return;
140 }
141#endif
142 low_level_traces = 0;
Nick Pelly4812a722011-06-07 10:37:09 -0700143#endif
144}
145
Nick Pelly5d9927b2010-09-23 12:47:58 -0700146/*-----------------------------------------------------------------------------
147
148FUNCTION: phDal4Nfc_Register
149
150PURPOSE: DAL register function.
151
152-----------------------------------------------------------------------------*/
153NFCSTATUS 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
201FUNCTION: phDal4Nfc_Unregister
202
203PURPOSE: DAL unregister function.
204
205-----------------------------------------------------------------------------*/
206NFCSTATUS 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 ;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700224
225 }
226 else
227 {
228 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_NOT_INITIALISED);
229 }
230 }
231 return result;
232}
233
234/*-----------------------------------------------------------------------------
235
236FUNCTION: phDal4Nfc_Init
237
238PURPOSE: DAL Init function.
239
240-----------------------------------------------------------------------------*/
241NFCSTATUS phDal4Nfc_Init(void *pContext, void *pHwRef )
242{
243 NFCSTATUS result = NFCSTATUS_SUCCESS;
244
Nick Pelly4812a722011-06-07 10:37:09 -0700245 refresh_low_level_traces();
246
Nick Pelly5d9927b2010-09-23 12:47:58 -0700247 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;
Martijn Coenenb99be652011-11-02 15:58:37 -0700270 hw_config.deviceNode = NULL;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700271 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
284FUNCTION: phDal4Nfc_Shutdown
285
286PURPOSE: DAL Shutdown function.
287
288-----------------------------------------------------------------------------*/
289
290NFCSTATUS 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
Nick Pelly5d9927b2010-09-23 12:47:58 -0700303 /* Close the message queue */
304#ifdef USE_MQ_MESSAGE_QUEUE
305 mq_close(nDeferedCallMessageQueueId);
306#endif
307
Nick Pelly5d9927b2010-09-23 12:47:58 -0700308 }
309
Nick Pelly5d9927b2010-09-23 12:47:58 -0700310 return result;
311}
312
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200313NFCSTATUS phDal4Nfc_ConfigRelease(void *pHwRef)
Nick Pelly5d9927b2010-09-23 12:47:58 -0700314{
315
316 NFCSTATUS result = NFCSTATUS_SUCCESS;
317 void * pThreadReturn;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500318
319 DAL_PRINT("phDal4Nfc_ConfigRelease ");
Nick Pelly5d9927b2010-09-23 12:47:58 -0700320
321 if (gDalContext.hw_valid == TRUE)
322 {
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200323 /* 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;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500328
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200329 /* Wake up the read thread so it can exit */
330 DAL_PRINT("Release Read Semaphore");
331 sem_post(&nfc_read_sem);
daniel_Tomas5e976052010-12-09 10:46:12 -0800332
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200333 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 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700340
341 /* Close the message queue */
342#ifdef USE_MQ_MESSAGE_QUEUE
343 mq_close(nDeferedCallMessageQueueId);
344#endif
345
daniel_Tomas5e976052010-12-09 10:46:12 -0800346 /* Shutdown NFC Chip */
347 phDal4Nfc_Reset(0);
348
Nick Pelly5d9927b2010-09-23 12:47:58 -0700349 /* Close the link */
350 gLinkFunc.close();
351
Martijn Coenenb99be652011-11-02 15:58:37 -0700352 if (gDalContext.pDev != NULL) {
353 nfc_pn544_close(gDalContext.pDev);
354 }
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500355 /* Reset the Read Writer context to NULL */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700356 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
daniel_Tomas5e976052010-12-09 10:46:12 -0800365
Nick Pelly5d9927b2010-09-23 12:47:58 -0700366 return result;
367}
368
369/*-----------------------------------------------------------------------------
370
371FUNCTION: phDal4Nfc_Write
372
373PURPOSE: DAL Write function.
374
375-----------------------------------------------------------------------------*/
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500376
Nick Pelly5d9927b2010-09-23 12:47:58 -0700377NFCSTATUS phDal4Nfc_Write( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
378{
379 NFCSTATUS result = NFCSTATUS_SUCCESS;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500380 static int MsgType= PHDAL4NFC_WRITE_MESSAGE;
381 int * pmsgType=&MsgType;
382 phDal4Nfc_Message_t sMsg;
383 phOsalNfc_Message_t OsalMsg;
384
Nick Pelly5d9927b2010-09-23 12:47:58 -0700385 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))
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500392 {
393 DAL_PRINT("phDal4Nfc_Write() : Temporary buffer !! \n");
Jeff Hamilton3e987672010-10-27 21:29:08 -0500394 gReadWriteContext.pTempWriteBuffer = (uint8_t*)malloc(length * sizeof(uint8_t));
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500395 /* Make a copy of the passed arguments */
Jeff Hamilton3e987672010-10-27 21:29:08 -0500396 memcpy(gReadWriteContext.pTempWriteBuffer,pBuffer,length);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700397 DAL_DEBUG("phDal4Nfc_Write(): %d\n", length);
Jeff Hamilton3e987672010-10-27 21:29:08 -0500398 gReadWriteContext.pWriteBuffer = gReadWriteContext.pTempWriteBuffer;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700399 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;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500406 /* 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));
Nick Pelly5d9927b2010-09-23 12:47:58 -0700414 }
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
438FUNCTION: phDal4Nfc_Read
439
440PURPOSE: DAL Read function.
441
442-----------------------------------------------------------------------------*/
443
444NFCSTATUS 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);
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500457
Nick Pelly5d9927b2010-09-23 12:47:58 -0700458 /* 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;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500465 /* Update the return state */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700466 result = NFCSTATUS_PENDING;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500467 /* unlock reader thread */
468 sem_post(&nfc_read_sem);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700469 }
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;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700478 }
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
497FUNCTION: phDal4Nfc_ReadWait
498
499PURPOSE: DAL Read wait function.
500
501-----------------------------------------------------------------------------*/
502
503NFCSTATUS phDal4Nfc_ReadWait(void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length)
504{
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500505 /* not used */
506 DAL_PRINT("phDal4Nfc_ReadWait");
507 return 0;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700508}
509/*-----------------------------------------------------------------------------
510
511FUNCTION: phDal4Nfc_ReadWaitCancel
512
513PURPOSE: Cancel the Read wait function.
514
515-----------------------------------------------------------------------------*/
516
517NFCSTATUS phDal4Nfc_ReadWaitCancel( void *pContext, void *pHwRef)
518{
daniel_Tomas73fcd522010-12-03 14:16:11 +0100519 DAL_PRINT("phDal4Nfc_ReadWaitCancel");
520
521 /* unlock read semaphore */
522 sem_post(&nfc_read_sem);
523
Nick Pelly5d9927b2010-09-23 12:47:58 -0700524 return 0;
525}
526
527/*-----------------------------------------------------------------------------
528
529FUNCTION: phDal4Nfc_Config
530
531PURPOSE: Configure the serial port.
532
533-----------------------------------------------------------------------------*/
534NFCSTATUS phDal4Nfc_Config(pphDal4Nfc_sConfig_t config,void **phwref)
535{
536 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
Martijn Coenenb99be652011-11-02 15:58:37 -0700537 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) {
Steve Blocka12acb12012-01-06 19:10:18 +0000546 ALOGE("hw_get_module() failed");
Martijn Coenenb99be652011-11-02 15:58:37 -0700547 return NFCSTATUS_FAILED;
548 }
549 ret = nfc_pn544_open(hw_module, &pn544_dev);
550 if (ret) {
Steve Blocka12acb12012-01-06 19:10:18 +0000551 ALOGE("Could not open pn544 hw_module");
Martijn Coenenb99be652011-11-02 15:58:37 -0700552 return NFCSTATUS_FAILED;
553 }
554 config->deviceNode = pn544_dev->device_node;
555 if (config->deviceNode == NULL) {
Steve Blocka12acb12012-01-06 19:10:18 +0000556 ALOGE("deviceNode NULL");
Martijn Coenenb99be652011-11-02 15:58:37 -0700557 return NFCSTATUS_FAILED;
558 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700559
560 DAL_PRINT("phDal4Nfc_Config");
561
Martijn Coenenb99be652011-11-02 15:58:37 -0700562 if ((config == NULL) || (phwref == NULL))
Nick Pelly5d9927b2010-09-23 12:47:58 -0700563 return NFCSTATUS_INVALID_PARAMETER;
564
565 /* Register the link callbacks */
566 memset(&gLinkFunc, 0, sizeof(phDal4Nfc_link_cbk_interface_t));
Martijn Coenenb99be652011-11-02 15:58:37 -0700567 switch(pn544_dev->linktype)
Nick Pelly5d9927b2010-09-23 12:47:58 -0700568 {
Martijn Coenenb99be652011-11-02 15:58:37 -0700569 case PN544_LINK_TYPE_UART:
570 case PN544_LINK_TYPE_USB:
Nick Pelly5d9927b2010-09-23 12:47:58 -0700571 {
Jeff Hamilton3e987672010-10-27 21:29:08 -0500572 DAL_PRINT("UART link Config");
Nick Pelly5d9927b2010-09-23 12:47:58 -0700573 /* 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;
daniel_Tomas5e976052010-12-09 10:46:12 -0800582 gLinkFunc.reset = phDal4Nfc_uart_reset;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700583 }
584 break;
585
Martijn Coenenb99be652011-11-02 15:58:37 -0700586 case PN544_LINK_TYPE_I2C:
Nick Pelly5d9927b2010-09-23 12:47:58 -0700587 {
Jeff Hamilton3e987672010-10-27 21:29:08 -0500588 DAL_PRINT("I2C link Config");
589 /* i2c link interface */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700590 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;
daniel_Tomas5e976052010-12-09 10:46:12 -0800598 gLinkFunc.reset = phDal4Nfc_i2c_reset;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700599 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;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500617
Nick Pelly5d9927b2010-09-23 12:47:58 -0700618 /* Reset the Reader Thread values to NULL */
619 memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext));
620 gReadWriteContext.nReadThreadAlive = TRUE;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500621 gReadWriteContext.nWriteBusy = FALSE;
622 gReadWriteContext.nWaitingOnWrite = FALSE;
623
Nick Pelly5d9927b2010-09-23 12:47:58 -0700624 /* 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
Martijn Coenenb99be652011-11-02 15:58:37 -0700630
631 gDalContext.pDev = pn544_dev;
632
Nick Pelly5d9927b2010-09-23 12:47:58 -0700633 /* 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;
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200640 phDal4Nfc_Reset(1);
Jeff Hamilton3e987672010-10-27 21:29:08 -0500641 phDal4Nfc_Reset(0);
642 phDal4Nfc_Reset(1);
643
Nick Pelly5d9927b2010-09-23 12:47:58 -0700644 return NFCSTATUS_SUCCESS;
645}
646
Jeff Hamilton3e987672010-10-27 21:29:08 -0500647/*-----------------------------------------------------------------------------
648
649FUNCTION: phDal4Nfc_Reset
650
651PURPOSE: Reset the PN544, using the VEN pin
652
653-----------------------------------------------------------------------------*/
654NFCSTATUS phDal4Nfc_Reset(long level)
655{
656 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
657
Nick Pelly34ff48f2011-06-27 09:01:51 -0700658 DAL_DEBUG("phDal4Nfc_Reset: VEN to %ld",level);
Jeff Hamilton3e987672010-10-27 21:29:08 -0500659
660 retstatus = gLinkFunc.reset(level);
661
662 return retstatus;
663}
664
665/*-----------------------------------------------------------------------------
666
667FUNCTION: phDal4Nfc_Download
668
669PURPOSE: Put the PN544 in download mode, using the GPIO4 pin
670
671-----------------------------------------------------------------------------*/
daniel_Tomas5e976052010-12-09 10:46:12 -0800672NFCSTATUS phDal4Nfc_Download()
Jeff Hamilton3e987672010-10-27 21:29:08 -0500673{
674 NFCSTATUS retstatus = NFCSTATUS_SUCCESS;
675
daniel_Tomas5e976052010-12-09 10:46:12 -0800676 DAL_DEBUG("phDal4Nfc_Download: GPIO4 to %d",1);
Jeff Hamilton3e987672010-10-27 21:29:08 -0500677
daniel_Tomas5e976052010-12-09 10:46:12 -0800678 usleep(10000);
679 retstatus = phDal4Nfc_Reset(2);
Jeff Hamilton3e987672010-10-27 21:29:08 -0500680
681 return retstatus;
682}
Nick Pelly5d9927b2010-09-23 12:47:58 -0700683
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 */
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500705
Nick Pelly5d9927b2010-09-23 12:47:58 -0700706int 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;
Nick Pelly92c7e012011-05-07 20:25:41 -0700719 int i2c_error_count;
Martijn Coenenb99be652011-11-02 15:58:37 -0700720 int i2c_workaround;
Rakesh Goyal3f791032012-01-27 15:51:26 +0530721 int i2c_device_address = 0x57;
Martijn Coenenb99be652011-11-02 15:58:37 -0700722 if (gDalContext.pDev != NULL) {
723 i2c_workaround = gDalContext.pDev->enable_i2c_workaround;
Rakesh Goyal3f791032012-01-27 15:51:26 +0530724 if (gDalContext.pDev->i2c_device_address) {
725 i2c_device_address = gDalContext.pDev->i2c_device_address;
726 if (i2c_workaround && i2c_device_address < 32)
727 {
Ramanan Rajeswaranc67f72f2012-03-09 12:30:43 -0800728 ALOGE("i2c_device_address not set to valid value");
Rakesh Goyal3f791032012-01-27 15:51:26 +0530729 return NFCSTATUS_FAILED;
730 }
731 }
Martijn Coenenb99be652011-11-02 15:58:37 -0700732 } else {
Steve Blocka12acb12012-01-06 19:10:18 +0000733 ALOGE("gDalContext.pDev is not set");
Martijn Coenenb99be652011-11-02 15:58:37 -0700734 return NFCSTATUS_FAILED;
735 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700736
Nick Pelly8763a192010-10-27 01:12:35 -0700737 pthread_setname_np(pthread_self(), "reader");
738
Nick Pelly5d9927b2010-09-23 12:47:58 -0700739 /* 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*/
Nick Pelly5d9927b2010-09-23 12:47:58 -0700741
742 DAL_PRINT("RX Thread \n");
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500743 DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive);
744 DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700745 while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */
746 {
Nick Pelly5d9927b2010-09-23 12:47:58 -0700747 /* Check for the read request from user */
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500748 DAL_PRINT("RX Thread Sem Lock\n");
749 sem_wait(&nfc_read_sem);
750 DAL_PRINT("RX Thread Sem UnLock\n");
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200751
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
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500759 /* Issue read operation.*/
Nick Pelly92c7e012011-05-07 20:25:41 -0700760
761 i2c_error_count = 0;
762retry:
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500763 gReadWriteContext.nNbOfBytesRead=0;
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200764 DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead);
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500765 memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead);
766
767 /* Wait for IRQ !!! */
Daniel Tomase5201c12011-04-20 17:28:16 -0700768 gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead);
769
Rakesh Goyal3f791032012-01-27 15:51:26 +0530770 /* A read value equal to the i2c_device_address indicates a HW I2C error at I2C address i2c_device_address
Daniel Tomase5201c12011-04-20 17:28:16 -0700771 * (pn544). There should not be false positives because a read of length 1
Rakesh Goyal3f791032012-01-27 15:51:26 +0530772 * must be a HCI length read, and a length of i2c_device_address is impossible (max is 33).
Daniel Tomase5201c12011-04-20 17:28:16 -0700773 */
Rakesh Goyal3f791032012-01-27 15:51:26 +0530774 if (i2c_workaround && gReadWriteContext.nNbOfBytesToRead == 1 &&
775 gReadWriteContext.pReadBuffer[0] == i2c_device_address)
Daniel Tomase5201c12011-04-20 17:28:16 -0700776 {
Nick Pelly92c7e012011-05-07 20:25:41 -0700777 i2c_error_count++;
Rakesh Goyal3f791032012-01-27 15:51:26 +0530778 DAL_DEBUG("RX Thread Read 0x%02x ", i2c_device_address);
779 DAL_DEBUG("%d times\n", i2c_error_count);
780
Nick Pelly92c7e012011-05-07 20:25:41 -0700781 if (i2c_error_count < 5) {
782 usleep(2000);
783 goto retry;
784 }
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200785 DAL_PRINT("RX Thread NOTHING TO READ, RECOVER");
Daniel Tomase5201c12011-04-20 17:28:16 -0700786 phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
787 }
788 else
789 {
Nick Pelly92c7e012011-05-07 20:25:41 -0700790 i2c_error_count = 0;
Nick Pelly4812a722011-06-07 10:37:09 -0700791
792 if (low_level_traces)
793 {
Nick Pelly5ea62ad2011-10-19 18:36:47 -0700794 phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead,
795 gReadWriteContext.pReadBuffer, low_level_traces);
Nick Pelly4812a722011-06-07 10:37:09 -0700796 }
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200797 DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead);
798 DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead);
Jeff Hamilton71b688d2011-09-13 16:22:03 -0500799/* DAL_PRINT("RX Thread ReadBuff[]={ ");
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500800 for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++)
Nick Pelly5d9927b2010-09-23 12:47:58 -0700801 {
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200802 DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]);
Nick Pelly5d9927b2010-09-23 12:47:58 -0700803 }
Jeff Hamilton71b688d2011-09-13 16:22:03 -0500804 DAL_PRINT("RX Thread }\n"); */
Daniel Tomase5201c12011-04-20 17:28:16 -0700805
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500806 /* read completed immediately */
Daniel Tomase5201c12011-04-20 17:28:16 -0700807 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 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700814
Nick Pelly5d9927b2010-09-23 12:47:58 -0700815 } /* End of thread Loop*/
Daniel TOMASdf82c4d2011-09-01 17:09:40 +0200816
817 DAL_PRINT("RX Thread exiting");
818
Nick Pelly5d9927b2010-09-23 12:47:58 -0700819 return TRUE;
820}
821
Nick Pelly5d9927b2010-09-23 12:47:58 -0700822
Nick Pelly5d9927b2010-09-23 12:47:58 -0700823
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
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500829 * reader thread.
Nick Pelly5d9927b2010-09-23 12:47:58 -0700830 *
831 * \retval NFCSTATUS_SUCCESS If success.
832 * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes
833 */
834NFCSTATUS phDal4Nfc_StartThreads(void)
835{
836 pthread_attr_t nReadThreadAttributes;
837 pthread_attr_t nWriteThreadAttributes;
838 int ret;
839
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500840 if(sem_init(&nfc_read_sem, 0, 0) == -1)
841 {
842 DAL_PRINT("NFC Init Semaphore creation Error");
843 return -1;
844 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700845
Nick Pelly5d9927b2010-09-23 12:47:58 -0700846 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));
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500849
Nick Pelly5d9927b2010-09-23 12:47:58 -0700850 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 */
864void 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 */
911void phDal4Nfc_DeferredCb (void *params)
912{
913 int* pParam=NULL;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500914 int i;
Nick Pelly5d9927b2010-09-23 12:47:58 -0700915 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;
Nick Pelly5ea62ad2011-10-19 18:36:47 -0700925 if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) {
926 TransactionInfo.status=NFCSTATUS_SUCCESS;
927 } else {
928 TransactionInfo.status=NFCSTATUS_READ_FAILED;
929 }
Nick Pelly5d9927b2010-09-23 12:47:58 -0700930 gReadWriteContext.nReadBusy = FALSE;
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500931
932
Nick Pelly5d9927b2010-09-23 12:47:58 -0700933 /* 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 }
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500940
Nick Pelly5d9927b2010-09-23 12:47:58 -0700941 break;
942 case PHDAL4NFC_WRITE_MESSAGE:
943 DAL_PRINT(" Dal deferred write called \n");
Daniel Tomasc1f33132011-04-21 14:11:28 -0700944
Nick Pelly4812a722011-06-07 10:37:09 -0700945 if(low_level_traces)
946 {
Nick Pelly5ea62ad2011-10-19 18:36:47 -0700947 phOsalNfc_PrintData("SEND", (uint16_t)gReadWriteContext.nNbOfBytesToWrite,
948 gReadWriteContext.pWriteBuffer, low_level_traces);
Nick Pelly4812a722011-06-07 10:37:09 -0700949 }
Daniel Tomasc1f33132011-04-21 14:11:28 -0700950
Nick Pelly5d9927b2010-09-23 12:47:58 -0700951 /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500952 /* Make a Physical WRITE */
Nick Pelly74decc92011-05-23 14:59:56 -0700953 /* NOTE: need to usleep(3000) here if the write is for SWP */
Nick Pelly99141cd2011-06-08 09:44:14 -0700954 usleep(500); /* NXP advise 500us sleep required between I2C writes */
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500955 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;
Nick Pelly34ff48f2011-06-27 09:01:51 -0700974/* DAL_PRINT("WriteBuff[]={ ");
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500975 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++)
976 {
977 DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]);
978 }
Nick Pelly34ff48f2011-06-27 09:01:51 -0700979 DAL_PRINT("}\n"); */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700980
Jeff Hamiltone7f38d32010-10-27 21:47:04 -0500981 // 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 */
Nick Pelly5d9927b2010-09-23 12:47:58 -0700992 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 */
1014void 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
Nick Pelly5d9927b2010-09-23 12:47:58 -07001022#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
Nick Pelly5d9927b2010-09-23 12:47:58 -07001045}
1046
1047#undef _DAL_4_NFC_C