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 int i2c_device_address = 0x57; 722 if (gDalContext.pDev != NULL) { 723 i2c_workaround = gDalContext.pDev->enable_i2c_workaround; 724 if (gDalContext.pDev->i2c_device_address) { 725 i2c_device_address = gDalContext.pDev->i2c_device_address; 726 if (i2c_workaround && i2c_device_address < 32) 727 { 728 ALOGE("i2c_device_address not set to valid value"); 729 return NFCSTATUS_FAILED; 730 } 731 } 732 } else { 733 ALOGE("gDalContext.pDev is not set"); 734 return NFCSTATUS_FAILED; 735 } 736 737 pthread_setname_np(pthread_self(), "reader"); 738 739 /* Create the overlapped event. Must be closed before exiting 740 to avoid a handle leak. This event is used READ API and the Reader thread*/ 741 742 DAL_PRINT("RX Thread \n"); 743 DAL_DEBUG("\nRX Thread nReadThreadAlive = %d",gReadWriteContext.nReadThreadAlive); 744 DAL_DEBUG("\nRX Thread nWaitingOnRead = %d",gReadWriteContext.nWaitingOnRead); 745 while(gReadWriteContext.nReadThreadAlive) /* Thread Loop */ 746 { 747 /* Check for the read request from user */ 748 DAL_PRINT("RX Thread Sem Lock\n"); 749 sem_wait(&nfc_read_sem); 750 DAL_PRINT("RX Thread Sem UnLock\n"); 751 752 if (!gReadWriteContext.nReadThreadAlive) 753 { 754 /* got the signal that we should exit. NOTE: we don't 755 attempt to read below, since the read may block */ 756 break; 757 } 758 759 /* Issue read operation.*/ 760 761 i2c_error_count = 0; 762retry: 763 gReadWriteContext.nNbOfBytesRead=0; 764 DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead); 765 memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead); 766 767 /* Wait for IRQ !!! */ 768 gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead); 769 770 /* A read value equal to the i2c_device_address indicates a HW I2C error at I2C address i2c_device_address 771 * (pn544). There should not be false positives because a read of length 1 772 * must be a HCI length read, and a length of i2c_device_address is impossible (max is 33). 773 */ 774 if (i2c_workaround && gReadWriteContext.nNbOfBytesToRead == 1 && 775 gReadWriteContext.pReadBuffer[0] == i2c_device_address) 776 { 777 i2c_error_count++; 778 DAL_DEBUG("RX Thread Read 0x%02x ", i2c_device_address); 779 DAL_DEBUG("%d times\n", i2c_error_count); 780 781 if (i2c_error_count < 5) { 782 usleep(2000); 783 goto retry; 784 } 785 DAL_PRINT("RX Thread NOTHING TO READ, RECOVER"); 786 phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1); 787 } 788 else 789 { 790 i2c_error_count = 0; 791 792 if (low_level_traces) 793 { 794 phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead, 795 gReadWriteContext.pReadBuffer, low_level_traces); 796 } 797 DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead); 798 DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead); 799/* DAL_PRINT("RX Thread ReadBuff[]={ "); 800 for (i = 0; i < gReadWriteContext.nNbOfBytesRead; i++) 801 { 802 DAL_DEBUG("RX Thread 0x%x ", gReadWriteContext.pReadBuffer[i]); 803 } 804 DAL_PRINT("RX Thread }\n"); */ 805 806 /* read completed immediately */ 807 sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE; 808 /* Update the state */ 809 phDal4Nfc_FillMsg(&sMsg,&OsalMsg); 810 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType); 811 memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t)); 812 memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t)); 813 } 814 815 } /* End of thread Loop*/ 816 817 DAL_PRINT("RX Thread exiting"); 818 819 return TRUE; 820} 821 822 823 824/** 825 * \ingroup grp_nfc_dal 826 * 827 * \brief DAL Start threads function 828 * This function is called from phDal4Nfc_Config and is responsible of creating the 829 * reader thread. 830 * 831 * \retval NFCSTATUS_SUCCESS If success. 832 * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes 833 */ 834NFCSTATUS phDal4Nfc_StartThreads(void) 835{ 836 pthread_attr_t nReadThreadAttributes; 837 pthread_attr_t nWriteThreadAttributes; 838 int ret; 839 840 if(sem_init(&nfc_read_sem, 0, 0) == -1) 841 { 842 DAL_PRINT("NFC Init Semaphore creation Error"); 843 return -1; 844 } 845 846 ret = pthread_create(&gReadWriteContext.nReadThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread, (void*) "dal_read_thread"); 847 if(ret != 0) 848 return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED)); 849 850 return NFCSTATUS_SUCCESS; 851} 852 853/** 854 * \ingroup grp_nfc_dal 855 * 856 * \brief DAL fill message function 857 * Internal messages management. This function fills message structure 858 * depending on message types. 859 * 860 * \param[in, out] pDalMsg DAL message to fill 861 * \param[in, out] pOsalMsg OSAL message to fill 862 * 863 */ 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; 914 int i; 915 phNfc_sTransactionInfo_t TransactionInfo; 916 917 pParam=(int*)params; 918 919 switch(*pParam) 920 { 921 case PHDAL4NFC_READ_MESSAGE: 922 DAL_PRINT(" Dal deferred read called \n"); 923 TransactionInfo.buffer=gReadWriteContext.pReadBuffer; 924 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead; 925 if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) { 926 TransactionInfo.status=NFCSTATUS_SUCCESS; 927 } else { 928 TransactionInfo.status=NFCSTATUS_READ_FAILED; 929 } 930 gReadWriteContext.nReadBusy = FALSE; 931 932 933 /* Reset flag so that another opertion can be issued.*/ 934 gReadWriteContext.nWaitingOnRead = FALSE; 935 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.receive_complete)) 936 { 937 pgDalContext->cb_if.receive_complete(pgDalContext->cb_if.pif_ctxt, 938 pgDalHwContext,&TransactionInfo); 939 } 940 941 break; 942 case PHDAL4NFC_WRITE_MESSAGE: 943 DAL_PRINT(" Dal deferred write called \n"); 944 945 if(low_level_traces) 946 { 947 phOsalNfc_PrintData("SEND", (uint16_t)gReadWriteContext.nNbOfBytesToWrite, 948 gReadWriteContext.pWriteBuffer, low_level_traces); 949 } 950 951 /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */ 952 /* Make a Physical WRITE */ 953 /* NOTE: need to usleep(3000) here if the write is for SWP */ 954 usleep(500); /* NXP advise 500us sleep required between I2C writes */ 955 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 956 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 957 { 958 /* controller may be in standby. do it again! */ 959 usleep(10000); /* wait 10 ms */ 960 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 961 } 962 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 963 { 964 /* Report write failure or timeout */ 965 DAL_PRINT(" Physical Write Error !!! \n"); 966 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 967 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR); 968 } 969 else 970 { 971 DAL_PRINT(" Physical Write Success \n"); 972 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 973 TransactionInfo.status=NFCSTATUS_SUCCESS; 974/* DAL_PRINT("WriteBuff[]={ "); 975 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++) 976 { 977 DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]); 978 } 979 DAL_PRINT("}\n"); */ 980 981 // Free TempWriteBuffer 982 if(gReadWriteContext.pTempWriteBuffer != NULL) 983 { 984 free(gReadWriteContext.pTempWriteBuffer); 985 } 986 } 987 /* Reset Write context */ 988 gReadWriteContext.nWriteBusy = FALSE; 989 gReadWriteContext.nWaitingOnWrite = FALSE; 990 991 /* call LLC callback */ 992 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete)) 993 { 994 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt, 995 pgDalHwContext,&TransactionInfo); 996 } 997 break; 998 default: 999 break; 1000 } 1001} 1002 1003/** 1004 * \ingroup grp_nfc_dal 1005 * 1006 * \brief DAL deferred call function 1007 * This function will enable to call the callback client asyncronously and in the client context. 1008 * It will post a message in a queue that will be processed by a client thread. 1009 * 1010 * \param[in] func The function to call when message is read from the queue 1011 * \param[in] param Parameter that will be passed to the 'func' function. 1012 * 1013 */ 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 1022#ifdef USE_MQ_MESSAGE_QUEUE 1023 nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 1024 nDeferedMessage.def_call = func; 1025 nDeferedMessage.params = param; 1026 retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0); 1027#else 1028 if(PHDAL4NFC_READ_MESSAGE==(* (int*)param)) 1029 { 1030 pDeferedMessage = &nDeferedMessageRead; 1031 } 1032 else 1033 { 1034 pDeferedMessage = &nDeferedMessageWrite; 1035 } 1036 nDeferedMessageWrapper.mtype = 1; 1037 nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 1038 pDeferedMessage->pCallback = func; 1039 pDeferedMessage->pParameter = param; 1040 nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage; 1041 nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t); 1042 retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0); 1043#endif 1044 1045} 1046 1047#undef _DAL_4_NFC_C 1048