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