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*/ 61 typedef 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 91 typedef void (*pphDal4Nfc_DeferFuncPointer_t) (void * ); 92 typedef void * (*pphDal4Nfc_thread_handler_t) (void * pParam); 93 94 95 /*----------------------------------------------------------------------------------- 96 VARIABLES 97 ------------------------------------------------------------------------------------*/ 98 static phDal4Nfc_RdWr_t gReadWriteContext; 99 static phDal4Nfc_SContext_t gDalContext; 100 static pphDal4Nfc_SContext_t pgDalContext; 101 static phHal_sHwReference_t * pgDalHwContext; 102 static sem_t nfc_read_sem; 103 static int low_level_traces; 104 #ifdef USE_MQ_MESSAGE_QUEUE 105 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessage; 106 static mqd_t nDeferedCallMessageQueueId; 107 108 #else 109 int nDeferedCallMessageQueueId = 0; 110 #endif 111 static phDal4Nfc_link_cbk_interface_t gLinkFunc; 112 /*----------------------------------------------------------------------------------- 113 PROTOTYPES 114 ------------------------------------------------------------------------------------*/ 115 static void phDal4Nfc_DeferredCb (void *params); 116 static NFCSTATUS phDal4Nfc_StartThreads (void); 117 static void phDal4Nfc_FillMsg (phDal4Nfc_Message_t *pDalMsg, phOsalNfc_Message_t *pOsalMsg); 118 119 /*----------------------------------------------------------------------------------- 120 DAL API IMPLEMENTATION 121 ------------------------------------------------------------------------------------*/ 122 123 static 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 150 FUNCTION: phDal4Nfc_Register 151 152 PURPOSE: DAL register function. 153 154 -----------------------------------------------------------------------------*/ 155 NFCSTATUS 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 203 FUNCTION: phDal4Nfc_Unregister 204 205 PURPOSE: DAL unregister function. 206 207 -----------------------------------------------------------------------------*/ 208 NFCSTATUS 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 238 FUNCTION: phDal4Nfc_Init 239 240 PURPOSE: DAL Init function. 241 242 -----------------------------------------------------------------------------*/ 243 NFCSTATUS 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 286 FUNCTION: phDal4Nfc_Shutdown 287 288 PURPOSE: DAL Shutdown function. 289 290 -----------------------------------------------------------------------------*/ 291 292 NFCSTATUS 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 315 NFCSTATUS 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 370 FUNCTION: phDal4Nfc_Write 371 372 PURPOSE: DAL Write function. 373 374 -----------------------------------------------------------------------------*/ 375 376 NFCSTATUS 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 437 FUNCTION: phDal4Nfc_Read 438 439 PURPOSE: DAL Read function. 440 441 -----------------------------------------------------------------------------*/ 442 443 NFCSTATUS 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 496 FUNCTION: phDal4Nfc_ReadWait 497 498 PURPOSE: DAL Read wait function. 499 500 -----------------------------------------------------------------------------*/ 501 502 NFCSTATUS 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 510 FUNCTION: phDal4Nfc_ReadWaitCancel 511 512 PURPOSE: Cancel the Read wait function. 513 514 -----------------------------------------------------------------------------*/ 515 516 NFCSTATUS 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 528 FUNCTION: phDal4Nfc_Config 529 530 PURPOSE: Configure the serial port. 531 532 -----------------------------------------------------------------------------*/ 533 NFCSTATUS 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 628 FUNCTION: phDal4Nfc_Reset 629 630 PURPOSE: Reset the PN544, using the VEN pin 631 632 -----------------------------------------------------------------------------*/ 633 NFCSTATUS 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 646 FUNCTION: phDal4Nfc_Download 647 648 PURPOSE: Put the PN544 in download mode, using the GPIO4 pin 649 650 -----------------------------------------------------------------------------*/ 651 NFCSTATUS 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 685 int 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 gReadWriteContext.nNbOfBytesRead=0; 724 DAL_DEBUG("RX Thread *New *** *****Request Length = %d",gReadWriteContext.nNbOfBytesToRead); 725 memsetRet=memset(gReadWriteContext.pReadBuffer,0,gReadWriteContext.nNbOfBytesToRead); 726 727 /* Wait for IRQ !!! */ 728 gReadWriteContext.nNbOfBytesRead = gLinkFunc.read(gReadWriteContext.pReadBuffer, gReadWriteContext.nNbOfBytesToRead); 729 730 if (low_level_traces) 731 { 732 phOsalNfc_PrintData("RECV", (uint16_t)gReadWriteContext.nNbOfBytesRead, 733 gReadWriteContext.pReadBuffer, low_level_traces); 734 } 735 DAL_DEBUG("RX Thread Read ok. nbToRead=%d\n", gReadWriteContext.nNbOfBytesToRead); 736 DAL_DEBUG("RX Thread NbReallyRead=%d\n", gReadWriteContext.nNbOfBytesRead); 737 738 /* read completed immediately */ 739 sMsg.eMsgType= PHDAL4NFC_READ_MESSAGE; 740 /* Update the state */ 741 phDal4Nfc_FillMsg(&sMsg,&OsalMsg); 742 phDal4Nfc_DeferredCall((pphDal4Nfc_DeferFuncPointer_t)phDal4Nfc_DeferredCb,(void *)pmsgType); 743 memsetRet=memset(&sMsg,0,sizeof(phDal4Nfc_Message_t)); 744 memsetRet=memset(&OsalMsg,0,sizeof(phOsalNfc_Message_t)); 745 746 } /* End of thread Loop*/ 747 748 DAL_PRINT("RX Thread exiting"); 749 750 return TRUE; 751 } 752 753 754 755 /** 756 * \ingroup grp_nfc_dal 757 * 758 * \brief DAL Start threads function 759 * This function is called from phDal4Nfc_Config and is responsible of creating the 760 * reader thread. 761 * 762 * \retval NFCSTATUS_SUCCESS If success. 763 * \retval NFCSTATUS_FAILED Can not create thread or retreive its attributes 764 */ 765 NFCSTATUS phDal4Nfc_StartThreads(void) 766 { 767 pthread_attr_t nReadThreadAttributes; 768 pthread_attr_t nWriteThreadAttributes; 769 int ret; 770 771 if(sem_init(&nfc_read_sem, 0, 0) == -1) 772 { 773 DAL_PRINT("NFC Init Semaphore creation Error"); 774 return -1; 775 } 776 777 ret = pthread_create(&gReadWriteContext.nReadThread, NULL, (pphDal4Nfc_thread_handler_t)phDal4Nfc_ReaderThread, (void*) "dal_read_thread"); 778 if(ret != 0) 779 return(PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_FAILED)); 780 781 return NFCSTATUS_SUCCESS; 782 } 783 784 /** 785 * \ingroup grp_nfc_dal 786 * 787 * \brief DAL fill message function 788 * Internal messages management. This function fills message structure 789 * depending on message types. 790 * 791 * \param[in, out] pDalMsg DAL message to fill 792 * \param[in, out] pOsalMsg OSAL message to fill 793 * 794 */ 795 void phDal4Nfc_FillMsg(phDal4Nfc_Message_t *pDalMsg,phOsalNfc_Message_t *pOsalMsg) 796 { 797 if(NULL != pgDalHwContext) 798 { 799 if(pDalMsg->eMsgType == PHDAL4NFC_WRITE_MESSAGE) 800 { 801 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesWritten; 802 pDalMsg->transactInfo.buffer = NULL; 803 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS; 804 pDalMsg->pHwRef = pgDalHwContext; 805 pDalMsg->writeCbPtr = pgDalContext->cb_if.send_complete; 806 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE; 807 pOsalMsg->pMsgData = pDalMsg; 808 return; 809 } 810 else if(pDalMsg->eMsgType == PHDAL4NFC_READ_MESSAGE) 811 { 812 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesRead; 813 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadBuffer; 814 pDalMsg->pContext= pgDalContext->cb_if.pif_ctxt; 815 } 816 else 817 { 818 pDalMsg->transactInfo.length = (uint8_t)gReadWriteContext.nNbOfBytesReadWait; 819 pDalMsg->transactInfo.buffer = gReadWriteContext.pReadWaitBuffer; 820 pDalMsg->pContext= pgDalContext; 821 } 822 pDalMsg->transactInfo.status = NFCSTATUS_SUCCESS; 823 pDalMsg->pHwRef = pgDalHwContext; 824 pDalMsg->readCbPtr = pgDalContext->cb_if.receive_complete; 825 /*map to OSAL msg format*/ 826 pOsalMsg->eMsgType = PH_DAL4NFC_MESSAGE_BASE; 827 pOsalMsg->pMsgData = pDalMsg; 828 } 829 830 } 831 832 /** 833 * \ingroup grp_nfc_dal 834 * 835 * \brief DAL deferred callback function 836 * Generic handler function called by a client thread when reading a message from the queue. 837 * Will function will directly call the client function (same context). See phDal4Nfc_DeferredCall 838 * 839 * \param[in] params Parameter that will be passed to the client function. 840 * 841 */ 842 void phDal4Nfc_DeferredCb (void *params) 843 { 844 int* pParam=NULL; 845 int i; 846 phNfc_sTransactionInfo_t TransactionInfo; 847 848 pParam=(int*)params; 849 850 switch(*pParam) 851 { 852 case PHDAL4NFC_READ_MESSAGE: 853 DAL_PRINT(" Dal deferred read called \n"); 854 TransactionInfo.buffer=gReadWriteContext.pReadBuffer; 855 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesRead; 856 if (gReadWriteContext.nNbOfBytesRead == gReadWriteContext.nNbOfBytesToRead) { 857 TransactionInfo.status=NFCSTATUS_SUCCESS; 858 } else { 859 TransactionInfo.status=NFCSTATUS_READ_FAILED; 860 } 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", (uint16_t)gReadWriteContext.nNbOfBytesToWrite, 879 gReadWriteContext.pWriteBuffer, low_level_traces); 880 } 881 882 /* DAL_DEBUG("dalMsg->transactInfo.length : %d\n", dalMsg->transactInfo.length); */ 883 /* Make a Physical WRITE */ 884 /* NOTE: need to usleep(3000) here if the write is for SWP */ 885 usleep(500); /* NXP advise 500us sleep required between I2C writes */ 886 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 887 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 888 { 889 /* controller may be in standby. do it again! */ 890 usleep(10000); /* wait 10 ms */ 891 gReadWriteContext.nNbOfBytesWritten = gLinkFunc.write(gReadWriteContext.pWriteBuffer, gReadWriteContext.nNbOfBytesToWrite); 892 } 893 if (gReadWriteContext.nNbOfBytesWritten != gReadWriteContext.nNbOfBytesToWrite) 894 { 895 /* Report write failure or timeout */ 896 DAL_PRINT(" Physical Write Error !!! \n"); 897 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 898 TransactionInfo.status = PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_BOARD_COMMUNICATION_ERROR); 899 } 900 else 901 { 902 DAL_PRINT(" Physical Write Success \n"); 903 TransactionInfo.length=(uint16_t)gReadWriteContext.nNbOfBytesWritten; 904 TransactionInfo.status=NFCSTATUS_SUCCESS; 905 /* DAL_PRINT("WriteBuff[]={ "); 906 for (i = 0; i < gReadWriteContext.nNbOfBytesWritten; i++) 907 { 908 DAL_DEBUG("0x%x ", gReadWriteContext.pWriteBuffer[i]); 909 } 910 DAL_PRINT("}\n"); */ 911 912 // Free TempWriteBuffer 913 if(gReadWriteContext.pTempWriteBuffer != NULL) 914 { 915 free(gReadWriteContext.pTempWriteBuffer); 916 } 917 } 918 /* Reset Write context */ 919 gReadWriteContext.nWriteBusy = FALSE; 920 gReadWriteContext.nWaitingOnWrite = FALSE; 921 922 /* call LLC callback */ 923 if ((NULL != pgDalContext) && (NULL != pgDalContext->cb_if.send_complete)) 924 { 925 pgDalContext->cb_if.send_complete(pgDalContext->cb_if.pif_ctxt, 926 pgDalHwContext,&TransactionInfo); 927 } 928 break; 929 default: 930 break; 931 } 932 } 933 934 /** 935 * \ingroup grp_nfc_dal 936 * 937 * \brief DAL deferred call function 938 * This function will enable to call the callback client asyncronously and in the client context. 939 * It will post a message in a queue that will be processed by a client thread. 940 * 941 * \param[in] func The function to call when message is read from the queue 942 * \param[in] param Parameter that will be passed to the 'func' function. 943 * 944 */ 945 void phDal4Nfc_DeferredCall(pphDal4Nfc_DeferFuncPointer_t func, void *param) 946 { 947 int retvalue = 0; 948 phDal4Nfc_Message_Wrapper_t nDeferedMessageWrapper; 949 phDal4Nfc_DeferredCall_Msg_t *pDeferedMessage; 950 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageRead; 951 static phDal4Nfc_DeferredCall_Msg_t nDeferedMessageWrite; 952 953 #ifdef USE_MQ_MESSAGE_QUEUE 954 nDeferedMessage.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 955 nDeferedMessage.def_call = func; 956 nDeferedMessage.params = param; 957 retvalue = (int)mq_send(nDeferedCallMessageQueueId, (char *)&nDeferedMessage, sizeof(phDal4Nfc_DeferredCall_Msg_t), 0); 958 #else 959 if(PHDAL4NFC_READ_MESSAGE==(* (int*)param)) 960 { 961 pDeferedMessage = &nDeferedMessageRead; 962 } 963 else 964 { 965 pDeferedMessage = &nDeferedMessageWrite; 966 } 967 nDeferedMessageWrapper.mtype = 1; 968 nDeferedMessageWrapper.msg.eMsgType = PH_DAL4NFC_MESSAGE_BASE; 969 pDeferedMessage->pCallback = func; 970 pDeferedMessage->pParameter = param; 971 nDeferedMessageWrapper.msg.pMsgData = pDeferedMessage; 972 nDeferedMessageWrapper.msg.Size = sizeof(phDal4Nfc_DeferredCall_Msg_t); 973 retvalue = phDal4Nfc_msgsnd(nDeferedCallMessageQueueId, (struct msgbuf *)&nDeferedMessageWrapper, sizeof(phLibNfc_Message_t), 0); 974 #endif 975 976 } 977 978 #undef _DAL_4_NFC_C 979