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