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