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