phDal4Nfc.c revision a12acb119fa8cda91ca23d191b41b9438402e4d1
1/* 2 * Copyright (C) 2010 NXP Semiconductors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/** 18 * \file phDalNfc.c 19 * \brief DAL Implementation for linux 20 * 21 * Project: Trusted NFC Linux Lignt 22 * 23 * $Date: 07 aug 2009 24 * $Author: Jonathan roux 25 * $Revision: 1.0 $ 26 * 27 */ 28 29#define _DAL_4_NFC_C 30 31#include <unistd.h> 32#include <pthread.h> 33#include <stdlib.h> 34#ifdef ANDROID 35#include <linux/ipc.h> 36#include <cutils/log.h> 37#include <cutils/properties.h> // for property_get 38#else 39#include <sys/msg.h> 40#endif 41#include <semaphore.h> 42#include <phDal4Nfc.h> 43#include <phOsalNfc.h> 44#include <phNfcStatus.h> 45#include <phDal4Nfc_DeferredCall.h> 46#include <phDal4Nfc_debug.h> 47#include <phDal4Nfc_uart.h> 48#include <phDal4Nfc_i2c.h> 49#include <phDal4Nfc_link.h> 50#include <phDal4Nfc_messageQueueLib.h> 51#include <hardware/hardware.h> 52#include <hardware/nfc.h> 53 54 55/*----------------------------------------------------------------------------------- 56 TYPES 57------------------------------------------------------------------------------------*/ 58/*structure holds members related for both read and write operations*/ 59typedef 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 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; 100static sem_t nfc_read_sem; 101static int low_level_traces; 102#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 121static void refresh_low_level_traces() { 122#ifdef LOW_LEVEL_TRACES 123 low_level_traces = 1; 124 return; 125#else 126 127#ifdef ANDROID 128 char value[PROPERTY_VALUE_MAX]; 129 130 property_get("ro.debuggable", value, ""); 131 if (!value[0] || !atoi(value)) { 132 low_level_traces = 0; // user build, do not allow debug 133 return; 134 } 135 136 property_get("debug.nfc.LOW_LEVEL_TRACES", value, "0"); 137 if (value[0]) { 138 low_level_traces = atoi(value); 139 return; 140 } 141#endif 142 low_level_traces = 0; 143#endif 144} 145 146/*----------------------------------------------------------------------------- 147 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 ; 224 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 245 refresh_low_level_traces(); 246 247 if ((NULL != pContext) && (NULL != pHwRef)) 248 { 249 pContext = pgDalContext; 250 pgDalHwContext = (phHal_sHwReference_t *)pHwRef; 251 252 if ( gDalContext.hw_valid == TRUE ) 253 { 254 /* The link has been opened from the application interface */ 255 gLinkFunc.open_from_handle(pgDalHwContext); 256 257 if (!gLinkFunc.is_opened()) 258 { 259 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); 260 } 261 else 262 { 263 /* Clear link buffers */ 264 gLinkFunc.flush(); 265 } 266 } 267 else 268 { 269 static phDal4Nfc_sConfig_t hw_config; 270 hw_config.deviceNode = NULL; 271 result = phDal4Nfc_Config(&hw_config, pHwRef ); 272 } 273 } 274 else /*Input parametrs invalid*/ 275 { 276 result = NFCSTATUS_INVALID_PARAMETER; 277 } 278 279 return result; 280} 281 282/*----------------------------------------------------------------------------- 283 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 303 /* Close the message queue */ 304#ifdef USE_MQ_MESSAGE_QUEUE 305 mq_close(nDeferedCallMessageQueueId); 306#endif 307 308 } 309 310 return result; 311} 312 313NFCSTATUS phDal4Nfc_ConfigRelease(void *pHwRef) 314{ 315 316 NFCSTATUS result = NFCSTATUS_SUCCESS; 317 void * pThreadReturn; 318 319 DAL_PRINT("phDal4Nfc_ConfigRelease "); 320 321 if (gDalContext.hw_valid == TRUE) 322 { 323 /* Signal the read and write threads to exit. NOTE: there 324 actually is no write thread! :) */ 325 DAL_PRINT("Stop Reader Thread"); 326 gReadWriteContext.nReadThreadAlive = 0; 327 gReadWriteContext.nWriteThreadAlive = 0; 328 329 /* Wake up the read thread so it can exit */ 330 DAL_PRINT("Release Read Semaphore"); 331 sem_post(&nfc_read_sem); 332 333 DAL_DEBUG("phDal4Nfc_ConfigRelease - doing pthread_join(%d)", 334 gReadWriteContext.nReadThread); 335 if (pthread_join(gReadWriteContext.nReadThread, &pThreadReturn) != 0) 336 { 337 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED); 338 DAL_PRINT("phDal4Nfc_ConfigRelease KO"); 339 } 340 341 /* Close the message queue */ 342#ifdef USE_MQ_MESSAGE_QUEUE 343 mq_close(nDeferedCallMessageQueueId); 344#endif 345 346 /* Shutdown NFC Chip */ 347 phDal4Nfc_Reset(0); 348 349 /* Close the link */ 350 gLinkFunc.close(); 351 352 if (gDalContext.pDev != NULL) { 353 nfc_pn544_close(gDalContext.pDev); 354 } 355 /* Reset the Read Writer context to NULL */ 356 memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext)); 357 /* Reset the DAL context values to NULL */ 358 memset((void *)&gDalContext,0,sizeof(gDalContext)); 359 } 360 361 gDalContext.hw_valid = FALSE; 362 363 DAL_DEBUG("phDal4Nfc_ConfigRelease(): %04x\n", result); 364 365 366 return result; 367} 368 369/*----------------------------------------------------------------------------- 370 371FUNCTION: phDal4Nfc_Write 372 373PURPOSE: DAL Write function. 374 375-----------------------------------------------------------------------------*/ 376 377NFCSTATUS phDal4Nfc_Write( void *pContext, void *pHwRef,uint8_t *pBuffer, uint16_t length) 378{ 379 NFCSTATUS result = NFCSTATUS_SUCCESS; 380 static int MsgType= PHDAL4NFC_WRITE_MESSAGE; 381 int * pmsgType=&MsgType; 382 phDal4Nfc_Message_t sMsg; 383 phOsalNfc_Message_t OsalMsg; 384 385 if ((NULL != pContext) && (NULL != pHwRef)&& 386 (NULL != pBuffer) && (0 != length)) 387 { 388 if( gDalContext.hw_valid== TRUE) 389 { 390 if((!gReadWriteContext.nWriteBusy)&& 391 (!gReadWriteContext.nWaitingOnWrite)) 392 { 393 DAL_PRINT("phDal4Nfc_Write() : Temporary buffer !! \n"); 394 gReadWriteContext.pTempWriteBuffer = (uint8_t*)malloc(length * sizeof(uint8_t)); 395 /* Make a copy of the passed arguments */ 396 memcpy(gReadWriteContext.pTempWriteBuffer,pBuffer,length); 397 DAL_DEBUG("phDal4Nfc_Write(): %d\n", length); 398 gReadWriteContext.pWriteBuffer = gReadWriteContext.pTempWriteBuffer; 399 gReadWriteContext.nNbOfBytesToWrite = length; 400 /* Change the write state so that thread can take over the write */ 401 gReadWriteContext.nWriteBusy = TRUE; 402 /* Just set variable here. This is the trigger for the Write thread */ 403 gReadWriteContext.nWaitingOnWrite = TRUE; 404 /* Update the error state */ 405 result = NFCSTATUS_PENDING; 406 /* Send Message and perform physical write in the DefferedCallback */ 407 /* read completed immediately */ 408 sMsg.eMsgType= PHDAL4NFC_WRITE_MESSAGE; 409 /* Update the state */ 410 phDal4Nfc_FillMsg(&sMsg,&OsalMsg); 411 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType); 412 memset(&sMsg,0,sizeof(phDal4Nfc_Message_t)); 413 memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t)); 414 } 415 else 416 { 417 /* Driver is BUSY with previous Write */ 418 DAL_PRINT("phDal4Nfc_Write() : Busy \n"); 419 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BUSY) ; 420 } 421 } 422 else 423 { 424 /* TBD :Additional error code : NOT_INITIALISED */ 425 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); 426 } 427 428 }/*end if-Input parametrs valid-check*/ 429 else 430 { 431 result = NFCSTATUS_INVALID_PARAMETER; 432 } 433 return result; 434} 435 436/*----------------------------------------------------------------------------- 437 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); 457 458 /* Make a copy of the passed arguments */ 459 gReadWriteContext.pReadBuffer = pBuffer; 460 gReadWriteContext.nNbOfBytesToRead = length; 461 /* Change the Read state so that thread can take over the read */ 462 gReadWriteContext.nReadBusy = TRUE; 463 /* Just set variable here. This is the trigger for the Reader thread */ 464 gReadWriteContext.nWaitingOnRead = TRUE; 465 /* Update the return state */ 466 result = NFCSTATUS_PENDING; 467 /* unlock reader thread */ 468 sem_post(&nfc_read_sem); 469 } 470 else 471 { 472 /* Driver is BUSY with prev Read */ 473 DAL_PRINT("DAL BUSY\n"); 474 /* Make a copy of the passed arguments */ 475 gReadWriteContext.pReadBuffer = pBuffer; 476 gReadWriteContext.nNbOfBytesToRead = length; 477 result = NFCSTATUS_PENDING; 478 } 479 } 480 else 481 { 482 /* TBD :Additional error code : NOT_INITIALISED */ 483 result = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); 484 } 485 }/*end if-Input parametrs valid-check*/ 486 else 487 { 488 result = NFCSTATUS_INVALID_PARAMETER; 489 } 490 DAL_DEBUG("*****DAl Read called result : %x\n", result); 491 return result; 492} 493 494 495/*----------------------------------------------------------------------------- 496 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{ 505 /* not used */ 506 DAL_PRINT("phDal4Nfc_ReadWait"); 507 return 0; 508} 509/*----------------------------------------------------------------------------- 510 511FUNCTION: phDal4Nfc_ReadWaitCancel 512 513PURPOSE: Cancel the Read wait function. 514 515-----------------------------------------------------------------------------*/ 516 517NFCSTATUS phDal4Nfc_ReadWaitCancel( void *pContext, void *pHwRef) 518{ 519 DAL_PRINT("phDal4Nfc_ReadWaitCancel"); 520 521 /* unlock read semaphore */ 522 sem_post(&nfc_read_sem); 523 524 return 0; 525} 526 527/*----------------------------------------------------------------------------- 528 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; 537 const hw_module_t* hw_module; 538 nfc_pn544_device_t* pn544_dev; 539 uint8_t num_eeprom_settings; 540 uint8_t* eeprom_settings; 541 int ret; 542 543 /* Retrieve the hw module from the Android NFC HAL */ 544 ret = hw_get_module(NFC_HARDWARE_MODULE_ID, &hw_module); 545 if (ret) { 546 ALOGE("hw_get_module() failed"); 547 return NFCSTATUS_FAILED; 548 } 549 ret = nfc_pn544_open(hw_module, &pn544_dev); 550 if (ret) { 551 ALOGE("Could not open pn544 hw_module"); 552 return NFCSTATUS_FAILED; 553 } 554 config->deviceNode = pn544_dev->device_node; 555 if (config->deviceNode == NULL) { 556 ALOGE("deviceNode NULL"); 557 return NFCSTATUS_FAILED; 558 } 559 560 DAL_PRINT("phDal4Nfc_Config"); 561 562 if ((config == NULL) || (phwref == NULL)) 563 return NFCSTATUS_INVALID_PARAMETER; 564 565 /* Register the link callbacks */ 566 memset(&gLinkFunc, 0, sizeof(phDal4Nfc_link_cbk_interface_t)); 567 switch(pn544_dev->linktype) 568 { 569 case PN544_LINK_TYPE_UART: 570 case PN544_LINK_TYPE_USB: 571 { 572 DAL_PRINT("UART link Config"); 573 /* Uart link interface */ 574 gLinkFunc.init = phDal4Nfc_uart_initialize; 575 gLinkFunc.open_from_handle = phDal4Nfc_uart_set_open_from_handle; 576 gLinkFunc.is_opened = phDal4Nfc_uart_is_opened; 577 gLinkFunc.flush = phDal4Nfc_uart_flush; 578 gLinkFunc.close = phDal4Nfc_uart_close; 579 gLinkFunc.open_and_configure = phDal4Nfc_uart_open_and_configure; 580 gLinkFunc.read = phDal4Nfc_uart_read; 581 gLinkFunc.write = phDal4Nfc_uart_write; 582 gLinkFunc.reset = phDal4Nfc_uart_reset; 583 } 584 break; 585 586 case PN544_LINK_TYPE_I2C: 587 { 588 DAL_PRINT("I2C link Config"); 589 /* i2c link interface */ 590 gLinkFunc.init = phDal4Nfc_i2c_initialize; 591 gLinkFunc.open_from_handle = phDal4Nfc_i2c_set_open_from_handle; 592 gLinkFunc.is_opened = phDal4Nfc_i2c_is_opened; 593 gLinkFunc.flush = phDal4Nfc_i2c_flush; 594 gLinkFunc.close = phDal4Nfc_i2c_close; 595 gLinkFunc.open_and_configure = phDal4Nfc_i2c_open_and_configure; 596 gLinkFunc.read = phDal4Nfc_i2c_read; 597 gLinkFunc.write = phDal4Nfc_i2c_write; 598 gLinkFunc.reset = phDal4Nfc_i2c_reset; 599 break; 600 } 601 602 default: 603 { 604 /* Shound not happen : Bad parameter */ 605 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_PARAMETER); 606 } 607 } 608 609 gLinkFunc.init(); /* So that link interface can initialize its internal state */ 610 retstatus = gLinkFunc.open_and_configure(config, phwref); 611 if (retstatus != NFCSTATUS_SUCCESS) 612 return retstatus; 613 614 /* Iniatilize the DAL context */ 615 (void)memset(&gDalContext,0,sizeof(phDal4Nfc_SContext_t)); 616 pgDalContext = &gDalContext; 617 618 /* Reset the Reader Thread values to NULL */ 619 memset((void *)&gReadWriteContext,0,sizeof(gReadWriteContext)); 620 gReadWriteContext.nReadThreadAlive = TRUE; 621 gReadWriteContext.nWriteBusy = FALSE; 622 gReadWriteContext.nWaitingOnWrite = FALSE; 623 624 /* Prepare the message queue for the defered calls */ 625#ifdef USE_MQ_MESSAGE_QUEUE 626 nDeferedCallMessageQueueId = mq_open(MQ_NAME_IDENTIFIER, O_CREAT|O_RDWR, 0666, &MQ_QUEUE_ATTRIBUTES); 627#else 628 nDeferedCallMessageQueueId = config->nClientId; 629#endif 630 631 gDalContext.pDev = pn544_dev; 632 633 /* Start Read and Write Threads */ 634 if(NFCSTATUS_SUCCESS != phDal4Nfc_StartThreads()) 635 { 636 return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED); 637 } 638 639 gDalContext.hw_valid = TRUE; 640 phDal4Nfc_Reset(1); 641 phDal4Nfc_Reset(0); 642 phDal4Nfc_Reset(1); 643 644 return NFCSTATUS_SUCCESS; 645} 646 647/*----------------------------------------------------------------------------- 648 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 658 DAL_DEBUG("phDal4Nfc_Reset: VEN to %ld",level); 659 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-----------------------------------------------------------------------------*/ 672NFCSTATUS phDal4Nfc_Download() 673{ 674 NFCSTATUS retstatus = NFCSTATUS_SUCCESS; 675 676 DAL_DEBUG("phDal4Nfc_Download: GPIO4 to %d",1); 677 678 usleep(10000); 679 retstatus = phDal4Nfc_Reset(2); 680 681 return retstatus; 682} 683 684 685 686/*----------------------------------------------------------------------------------- 687 DAL INTERNAL IMPLEMENTATION 688------------------------------------------------------------------------------------*/ 689 690 691 692/** 693 * \ingroup grp_nfc_dal 694 * 695 * \brief DAL Reader thread handler 696 * This function manages the reads from the link interface. The reads are done from 697 * this thread to create the asynchronous mecanism. When calling the synchronous 698 * function phDal4Nfc_Read, the nWaitingOnRead mutex is unlocked and the read 699 * can be done. Then a client callback is called to send the result. 700 * 701 * \param[in] pArg A custom argument that can be passed to the thread (not used) 702 * 703 * \retval TRUE Thread exiting. 704 */ 705 706int phDal4Nfc_ReaderThread(void * pArg) 707{ 708 char retvalue; 709 NFCSTATUS result = NFCSTATUS_SUCCESS; 710 uint8_t retry_cnt=0; 711 void * memsetRet; 712 713 static int MsgType= PHDAL4NFC_READ_MESSAGE; 714 int * pmsgType=&MsgType; 715 716 phDal4Nfc_Message_t sMsg; 717 phOsalNfc_Message_t OsalMsg ; 718 int i; 719 int i2c_error_count; 720 int i2c_workaround; 721 if (gDalContext.pDev != NULL) { 722 i2c_workaround = gDalContext.pDev->enable_i2c_workaround; 723 } else { 724 ALOGE("gDalContext.pDev is not set"); 725 return NFCSTATUS_FAILED; 726 } 727 728 pthread_setname_np(pthread_self(), "reader"); 729 730 /* Create the overlapped event. Must be closed before exiting 731 to avoid a handle leak. This event is used READ API and the Reader thread*/ 732 733 DAL_PRINT("RX Thread \n"); 734 DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive); 735 DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead); 736 while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */ 737 { 738 /* Check for the read request from user */ 739 DAL_PRINT("RX Thread Sem Lock\n"); 740 sem_wait(&nfc_read_sem); 741 DAL_PRINT("RX Thread Sem UnLock\n"); 742 743 if (!gReadWriteContext.nReadThreadAlive) 744 { 745 /* got the signal that we should exit. NOTE: we don't 746 attempt to read below, since the read may block */ 747 break; 748 } 749 750 /* Issue read operation.*/ 751 752 i2c_error_count = 0; 753retry: 754 gReadWriteContext.nNbOfBytesRead=0; 755 DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead); 756 memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead); 757 758 /* Wait for IRQ !!! */ 759 gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead); 760 761 /* Reading the value 0x57 indicates a HW I2C error at I2C address 0x57 762 * (pn544). There should not be false positives because a read of length 1 763 * must be a HCI length read, and a length of 0x57 is impossible (max is 33). 764 */ 765 if(i2c_workaround && gReadWriteContext.nNbOfBytesToRead == 1 && 766 gReadWriteContext.pReadBuffer[0] == 0x57) 767 { 768 i2c_error_count++; 769 DAL_DEBUG("RX Thread Read 0x57 %d times\n", i2c_error_count); 770 if (i2c_error_count < 5) { 771 usleep(2000); 772 goto retry; 773 } 774 DAL_PRINT("RX Thread NOTHING TO READ, RECOVER"); 775 phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); 776 } 777 else 778 { 779 i2c_error_count = 0; 780 781 if (low_level_traces) 782 { 783 phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead, 784 gReadWriteContext.pReadBuffer, low_level_traces); 785 } 786 DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead); 787 DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead); 788/* DAL_PRINT("RX Thread ReadBuff[]={ "); 789 for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++) 790 { 791 DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]); 792 } 793 DAL_PRINT("RX Thread }\n"); */ 794 795 /* read completed immediately */ 796 sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE; 797 /* Update the state */ 798 phDal4Nfc_FillMsg(&sMsg,&OsalMsg); 799 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType); 800 memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t)); 801 memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t)); 802 } 803 804 } /* End of thread Loop*/ 805 806 DAL_PRINT("RX Thread exiting"); 807 808 return TRUE; 809} 810 811 812 813/** 814 * \ingroup grp_nfc_dal 815 * 816 * \brief DAL Start threads function 817 * This function is called from phDal4Nfc_Config and is responsible of creating the 818 * reader thread. 819 * 820 * \retval NFCSTATUS_SUCCESS If success. 821 * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes 822 */ 823NFCSTATUS phDal4Nfc_StartThreads(void) 824{ 825 pthread_attr_t nReadThreadAttributes; 826 pthread_attr_t nWriteThreadAttributes; 827 int ret; 828 829 if(sem_init(&nfc_read_sem, 0, 0) == -1) 830 { 831 DAL_PRINT("NFC Init Semaphore creation Error"); 832 return -1; 833 } 834 835 ret = pthread_create(&gReadWriteContext.nReadThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread, (void*) "dal_read_thread"); 836 if(ret != 0) 837 return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED)); 838 839 return NFCSTATUS_SUCCESS; 840} 841 842/** 843 * \ingroup grp_nfc_dal 844 * 845 * \brief DAL fill message function 846 * Internal messages management. This function fills message structure 847 * depending on message types. 848 * 849 * \param[in, out] pDalMsg DAL message to fill 850 * \param[in, out] pOsalMsg OSAL message to fill 851 * 852 */ 853void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg) 854{ 855 if(NULL != pgDalHwContext) 856 { 857 if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE) 858 { 859 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesWritten; 860 pDalMsg->transactInfo.buffer = NULL; 861 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS; 862 pDalMsg->pHwRef = pgDalHwContext; 863 pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete; 864 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE; 865 pOsalMsg->pMsgData = pDalMsg; 866 return; 867 } 868 else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE) 869 { 870 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesRead; 871 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer; 872 pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt; 873 } 874 else 875 { 876 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesReadWait; 877 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer; 878 pDalMsg->pContext= pgDalContext; 879 } 880 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS; 881 pDalMsg->pHwRef = pgDalHwContext; 882 pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete; 883 /*map to OSAL msg format*/ 884 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE; 885 pOsalMsg->pMsgData = pDalMsg; 886 } 887 888} 889 890/** 891 * \ingroup grp_nfc_dal 892 * 893 * \brief DAL deferred callback function 894 * Generic handler function called by a client thread when reading a message from the queue. 895 * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall 896 * 897 * \param[in] params Parameter that will be passed to the client function. 898 * 899 */ 900void phDal4Nfc_DeferredCb (void *params) 901{ 902 int* pParam=NULL; 903 int i; 904 phNfc_sTransactionInfo_t TransactionInfo; 905 906 pParam=(int*)params; 907 908 switch(*pParam) 909 { 910 case PHDAL4NFC_READ_MESSAGE: 911 DAL_PRINT(" Dal deferred read called \n"); 912 TransactionInfo.buffer=gReadWriteContext.pReadBuffer; 913 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead; 914 if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) { 915 TransactionInfo.status=NFCSTATUS_SUCCESS; 916 } else { 917 TransactionInfo.status=NFCSTATUS_READ_FAILED; 918 } 919 gReadWriteContext.nReadBusy = FALSE; 920 921 922 /* Reset flag so that another opertion can be issued.*/ 923 gReadWriteContext.nWaitingOnRead = FALSE; 924 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete)) 925 { 926 pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt, 927 pgDalHwContext,&TransactionInfo); 928 } 929 930 break; 931 case PHDAL4NFC_WRITE_MESSAGE: 932 DAL_PRINT(" Dal deferred write called \n"); 933 934 if(low_level_traces) 935 { 936 phOsalNfc_PrintData("SEND", (uint16_t)gReadWriteContext.nNbOfBytesToWrite, 937 gReadWriteContext.pWriteBuffer, low_level_traces); 938 } 939 940 /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */ 941 /* Make a Physical WRITE */ 942 /* NOTE: need to usleep(3000) here if the write is for SWP */ 943 usleep(500); /* NXP advise 500us sleep required between I2C writes */ 944 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 945 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 946 { 947 /* controller may be in standby. do it again! */ 948 usleep(10000); /* wait 10 ms */ 949 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 950 } 951 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 952 { 953 /* Report write failure or timeout */ 954 DAL_PRINT(" Physical Write Error !!! \n"); 955 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 956 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR); 957 } 958 else 959 { 960 DAL_PRINT(" Physical Write Success \n"); 961 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 962 TransactionInfo.status=NFCSTATUS_SUCCESS; 963/* DAL_PRINT("WriteBuff[]={ "); 964 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++) 965 { 966 DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]); 967 } 968 DAL_PRINT("}\n"); */ 969 970 // Free TempWriteBuffer 971 if(gReadWriteContext.pTempWriteBuffer != NULL) 972 { 973 free(gReadWriteContext.pTempWriteBuffer); 974 } 975 } 976 /* Reset Write context */ 977 gReadWriteContext.nWriteBusy = FALSE; 978 gReadWriteContext.nWaitingOnWrite = FALSE; 979 980 /* call LLC callback */ 981 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete)) 982 { 983 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt, 984 pgDalHwContext,&TransactionInfo); 985 } 986 break; 987 default: 988 break; 989 } 990} 991 992/** 993 * \ingroup grp_nfc_dal 994 * 995 * \brief DAL deferred call function 996 * This function will enable to call the callback client asyncronously and in the client context. 997 * It will post a message in a queue that will be processed by a client thread. 998 * 999 * \param[in] func The function to call when message is read from the queue 1000 * \param[in] param Parameter that will be passed to the 'func' function. 1001 * 1002 */ 1003void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param) 1004{ 1005 int retvalue = 0; 1006 phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper; 1007 phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage; 1008 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead; 1009 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite; 1010 1011#ifdef USE_MQ_MESSAGE_QUEUE 1012 nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 1013 nDeferedMessage.def_call = func; 1014 nDeferedMessage.params = param; 1015 retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0); 1016#else 1017 if(PHDAL4NFC_READ_MESSAGE==(* (int*)param)) 1018 { 1019 pDeferedMessage = &nDeferedMessageRead; 1020 } 1021 else 1022 { 1023 pDeferedMessage = &nDeferedMessageWrite; 1024 } 1025 nDeferedMessageWrapper.mtype = 1; 1026 nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 1027 pDeferedMessage->pCallback = func; 1028 pDeferedMessage->pParameter = param; 1029 nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage; 1030 nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t); 1031 retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0); 1032#endif 1033 1034} 1035 1036#undef _DAL_4_NFC_C 1037