1 /* 2 * Copyright (C) 2015 The Android Open Source Project 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 #ifdef ESE_NFC_SYNCHRONIZATION 17 #include <linux/ese-nfc-sync.h> 18 #endif 19 #include <fcntl.h> 20 #include <sys/ioctl.h> 21 #include <sys/time.h> 22 23 #include <android-base/stringprintf.h> 24 #include <base/logging.h> 25 #include <phNxpConfig.h> 26 #include <phNxpExtns_MifareStd.h> 27 #include <phNxpLog.h> 28 29 using android::base::StringPrintf; 30 31 extern phNxpExtns_Context_t gphNxpExtns_Context; 32 extern phFriNfc_NdefMap_t* NdefMap; 33 extern phNci_mfc_auth_cmd_t gAuthCmdBuf; 34 35 static NFCSTATUS phNxpExtns_ProcessSysMessage(phLibNfc_Message_t* msg); 36 static NFCSTATUS phNxpExtns_SendMsg(phLibNfc_Message_t* sysmsg); 37 38 #ifdef ESE_NFC_SYNCHRONIZATION 39 /* timing calculation structure*/ 40 typedef struct time_cal { 41 struct timeval tv1; 42 struct timeval tv2; 43 } TimeCal; 44 static int fd_ese_nfc_sync; /*file descriptor to hold sync driver handle*/ 45 #endif 46 47 /******************************************************************************* 48 ** 49 ** Function EXTNS_Init 50 ** 51 ** Description This function Initializes Mifare Classic Extns. Allocates 52 ** required memory and initializes the Mifare Classic Vars 53 ** 54 ** Returns NFCSTATUS_SUCCESS if successfully initialized 55 ** NFCSTATUS_FAILED otherwise 56 ** 57 *******************************************************************************/ 58 NFCSTATUS EXTNS_Init(tNFA_DM_CBACK* p_nfa_dm_cback, 59 tNFA_CONN_CBACK* p_nfa_conn_cback) { 60 NFCSTATUS status = NFCSTATUS_FAILED; 61 62 /* reset config cache */ 63 resetNxpConfig(); 64 65 /* Initialize Log level */ 66 phNxpLog_InitializeLogLevel(); 67 68 /* Validate parameters */ 69 if ((!p_nfa_dm_cback) || (!p_nfa_conn_cback)) { 70 LOG(ERROR) << StringPrintf("EXTNS_Init(): error null callback"); 71 goto clean_and_return; 72 } 73 74 gphNxpExtns_Context.p_dm_cback = p_nfa_dm_cback; 75 gphNxpExtns_Context.p_conn_cback = p_nfa_conn_cback; 76 77 if (NFCSTATUS_SUCCESS != phNxpExtns_MfcModuleInit()) { 78 LOG(ERROR) << StringPrintf("ERROR: MFC Module Init Failed"); 79 goto clean_and_return; 80 } 81 gphNxpExtns_Context.Extns_status = EXTNS_STATUS_OPEN; 82 83 status = NFCSTATUS_SUCCESS; 84 return status; 85 86 clean_and_return: 87 gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE; 88 return status; 89 } 90 91 /******************************************************************************* 92 ** 93 ** Function EXTNS_Close 94 ** 95 ** Description This function de-initializes Mifare Classic Extns. 96 ** De-allocates memory 97 ** 98 ** Returns None 99 ** 100 *******************************************************************************/ 101 void EXTNS_Close(void) { 102 gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE; 103 phNxpExtns_MfcModuleDeInit(); 104 return; 105 } 106 107 /******************************************************************************* 108 ** 109 ** Function EXTNS_MfcCallBack 110 ** 111 ** Description Decodes Mifare Classic Tag Response 112 ** This is called from NFA_SendRaw Callback 113 ** 114 ** Returns: 115 ** NFCSTATUS_SUCCESS if successfully initiated 116 ** NFCSTATUS_FAILED otherwise 117 ** 118 *******************************************************************************/ 119 NFCSTATUS EXTNS_MfcCallBack(uint8_t* buf, uint32_t buflen) { 120 NFCSTATUS status = NFCSTATUS_SUCCESS; 121 122 phLibNfc_Message_t msg; 123 124 msg.eMsgType = PH_NXPEXTNS_RX_DATA; 125 msg.pMsgData = buf; 126 msg.Size = buflen; 127 128 status = phNxpExtns_SendMsg(&msg); 129 if (NFCSTATUS_SUCCESS != status) { 130 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 131 } 132 return status; 133 } 134 135 /******************************************************************************* 136 ** 137 ** Function EXTNS_MfcCheckNDef 138 ** 139 ** Description Performs NDEF detection for Mifare Classic Tag 140 ** 141 ** Upon successful completion of NDEF detection, a 142 ** NFA_NDEF_DETECT_EVT will be sent, to notify the application 143 ** of the NDEF attributes (NDEF total memory size, current 144 ** size, etc.). 145 ** 146 ** Returns: 147 ** NFCSTATUS_SUCCESS if successfully initiated 148 ** NFCSTATUS_FAILED otherwise 149 ** 150 *******************************************************************************/ 151 NFCSTATUS EXTNS_MfcCheckNDef(void) { 152 NFCSTATUS status = NFCSTATUS_SUCCESS; 153 phLibNfc_Message_t msg; 154 155 msg.eMsgType = PH_NXPEXTNS_MIFARE_CHECK_NDEF; 156 msg.pMsgData = NULL; 157 msg.Size = 0; 158 159 status = phNxpExtns_SendMsg(&msg); 160 if (NFCSTATUS_SUCCESS != status) { 161 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 162 } 163 164 return status; 165 } 166 167 /******************************************************************************* 168 ** 169 ** Function EXTNS_MfcReadNDef 170 ** 171 ** Description Reads NDEF message from Mifare Classic Tag. 172 ** 173 ** Upon receiving the NDEF message, the message will be sent to 174 ** the handler registered with 175 *EXTNS_MfcRegisterNDefTypeHandler. 176 ** 177 ** Returns: 178 ** NFCSTATUS_SUCCESS if successfully initiated 179 ** NFCSTATUS_FAILED otherwise 180 ** 181 *******************************************************************************/ 182 NFCSTATUS EXTNS_MfcReadNDef(void) { 183 NFCSTATUS status = NFCSTATUS_SUCCESS; 184 185 phLibNfc_Message_t msg; 186 187 msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_NDEF; 188 msg.pMsgData = NULL; 189 msg.Size = 0; 190 191 status = phNxpExtns_SendMsg(&msg); 192 if (NFCSTATUS_SUCCESS != status) { 193 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 194 } 195 196 return status; 197 } 198 /******************************************************************************* 199 ** 200 ** Function EXTNS_MfcPresenceCheck 201 ** 202 ** Description Do the check presence for Mifare Classic Tag. 203 ** 204 ** 205 ** Returns: 206 ** NFCSTATUS_SUCCESS if successfully initiated 207 ** NFCSTATUS_FAILED otherwise 208 ** 209 *******************************************************************************/ 210 NFCSTATUS EXTNS_MfcPresenceCheck(void) { 211 NFCSTATUS status = NFCSTATUS_SUCCESS; 212 213 phLibNfc_Message_t msg; 214 215 msg.eMsgType = PH_NXPEXTNS_MIFARE_PRESENCE_CHECK; 216 msg.pMsgData = NULL; 217 msg.Size = 0; 218 219 gAuthCmdBuf.status = NFCSTATUS_FAILED; 220 if (sem_init(&gAuthCmdBuf.semPresenceCheck, 0, 0) == -1) { 221 LOG(ERROR) << StringPrintf("%s: semaphore creation failed (errno=%d)", 222 __func__, errno); 223 return NFCSTATUS_FAILED; 224 } 225 226 status = phNxpExtns_SendMsg(&msg); 227 if (NFCSTATUS_SUCCESS != status) { 228 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 229 sem_destroy(&gAuthCmdBuf.semPresenceCheck); 230 } 231 232 return status; 233 } 234 235 /******************************************************************************* 236 ** 237 ** Function EXTNS_MfcSetReadOnly 238 ** 239 ** 240 ** Description: 241 ** Sets tag as read only. 242 ** 243 ** When tag is set as read only, or if an error occurs, the app will be 244 ** notified with NFA_SET_TAG_RO_EVT. 245 ** 246 ** Returns: 247 ** NFCSTATUS_SUCCESS if successfully initiated 248 ** NFCSTATUS_FAILED otherwise 249 ** 250 *******************************************************************************/ 251 NFCSTATUS EXTNS_MfcSetReadOnly(uint8_t* key, uint8_t len) { 252 NFCSTATUS status = NFCSTATUS_SUCCESS; 253 254 phLibNfc_Message_t msg; 255 256 msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_ONLY; 257 msg.pMsgData = key; 258 msg.Size = len; 259 260 status = phNxpExtns_SendMsg(&msg); 261 if (NFCSTATUS_SUCCESS != status) { 262 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 263 } 264 265 return status; 266 } 267 268 /******************************************************************************* 269 ** 270 ** Function EXTNS_MfcWriteNDef 271 ** 272 ** Description Writes NDEF data to Mifare Classic Tag. 273 ** 274 ** When the entire message has been written, or if an error 275 ** occurs, the app will be notified with NFA_WRITE_CPLT_EVT. 276 ** 277 ** p_data needs to be persistent until NFA_WRITE_CPLT_EVT 278 ** 279 ** Returns: 280 ** NFCSTATUS_SUCCESS if successfully initiated 281 ** NFCSTATUS_FAILED otherwise 282 ** 283 *******************************************************************************/ 284 NFCSTATUS EXTNS_MfcWriteNDef(uint8_t* p_data, uint32_t len) { 285 NFCSTATUS status = NFCSTATUS_SUCCESS; 286 287 phLibNfc_Message_t msg; 288 289 msg.eMsgType = PH_NXPEXTNS_MIFARE_WRITE_NDEF; 290 msg.pMsgData = p_data; 291 msg.Size = len; 292 293 status = phNxpExtns_SendMsg(&msg); 294 if (NFCSTATUS_SUCCESS != status) { 295 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 296 } 297 298 return status; 299 } 300 301 /***************************************************************************** 302 ** 303 ** Function EXTNS_MfcFormatTag 304 ** 305 ** Description Formats Mifare Classic Tag. 306 ** 307 ** The NFA_RW_FORMAT_CPLT_EVT, status is used to 308 ** indicate if tag is successfully formated or not 309 ** 310 ** Returns 311 ** NFCSTATUS_SUCCESS if successfully initiated 312 ** NFCSTATUS_FAILED otherwise 313 ** 314 *****************************************************************************/ 315 NFCSTATUS EXTNS_MfcFormatTag(uint8_t* key, uint8_t len) { 316 NFCSTATUS status = NFCSTATUS_SUCCESS; 317 318 phLibNfc_Message_t msg; 319 320 msg.eMsgType = PH_NXPEXTNS_MIFARE_FORMAT_NDEF; 321 msg.pMsgData = key; 322 msg.Size = len; 323 324 status = phNxpExtns_SendMsg(&msg); 325 if (NFCSTATUS_SUCCESS != status) { 326 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 327 } 328 329 return status; 330 } 331 332 /***************************************************************************** 333 ** 334 ** Function EXTNS_MfcDisconnect 335 ** 336 ** Description Disconnects Mifare Classic Tag. 337 ** 338 ** Returns 339 ** NFCSTATUS_SUCCESS if successfully initiated 340 ** NFCSTATUS_FAILED otherwise 341 ** 342 *****************************************************************************/ 343 NFCSTATUS EXTNS_MfcDisconnect(void) { 344 NFCSTATUS status = NFCSTATUS_SUCCESS; 345 346 phLibNfc_Message_t msg; 347 348 msg.eMsgType = PH_NXPEXTNS_DISCONNECT; 349 msg.pMsgData = NULL; 350 msg.Size = 0; 351 352 status = phNxpExtns_SendMsg(&msg); 353 if (NFCSTATUS_SUCCESS != status) { 354 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 355 } 356 357 return status; 358 } 359 360 /***************************************************************************** 361 ** 362 ** Function EXTNS_MfcActivated 363 ** 364 ** Description Activates Mifare Classic Tag. 365 ** 366 ** Returns 367 ** NFCSTATUS_SUCCESS if successfully initiated 368 ** NFCSTATUS_FAILED otherwise 369 ** 370 *****************************************************************************/ 371 NFCSTATUS EXTNS_MfcActivated(void) { 372 NFCSTATUS status = NFCSTATUS_SUCCESS; 373 phLibNfc_Message_t msg; 374 375 msg.eMsgType = PH_NXPEXTNS_ACTIVATED; 376 msg.pMsgData = NULL; 377 msg.Size = 0; 378 379 status = phNxpExtns_SendMsg(&msg); 380 if (NFCSTATUS_SUCCESS != status) { 381 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 382 } 383 384 return status; 385 } 386 387 /******************************************************************************* 388 ** 389 ** Function EXTNS_MfcTransceive 390 ** 391 ** Description Sends raw frame to Mifare Classic Tag. 392 ** 393 ** Returns NFCSTATUS_SUCCESS if successfully initiated 394 ** NFCSTATUS_FAILED otherwise 395 ** 396 *******************************************************************************/ 397 NFCSTATUS EXTNS_MfcTransceive(uint8_t* p_data, uint32_t len) { 398 NFCSTATUS status = NFCSTATUS_SUCCESS; 399 400 phLibNfc_Message_t msg; 401 402 msg.eMsgType = PH_NXPEXTNS_MIFARE_TRANSCEIVE; 403 msg.pMsgData = p_data; 404 msg.Size = len; 405 406 status = phNxpExtns_SendMsg(&msg); 407 if (NFCSTATUS_SUCCESS != status) { 408 LOG(ERROR) << StringPrintf("Error Sending msg to Extension Thread"); 409 } 410 411 return status; 412 } 413 414 /******************************************************************************* 415 ** 416 ** Function EXTNS_MfcInit 417 ** 418 ** Description This function is used to Init Mifare Classic Extns. 419 ** This function should be called when the tag detected is 420 ** Mifare Classic. 421 ** 422 ** Returns NFCSTATUS_SUCCESS 423 ** 424 *******************************************************************************/ 425 NFCSTATUS EXTNS_MfcInit(tNFA_ACTIVATED activationData) { 426 tNFC_ACTIVATE_DEVT rfDetail = activationData.activate_ntf; 427 428 NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak = 429 rfDetail.rf_tech_param.param.pa.sel_rsp; 430 NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[0] = 431 rfDetail.rf_tech_param.param.pa.sens_res[0]; 432 NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA[1] = 433 rfDetail.rf_tech_param.param.pa.sens_res[1]; 434 435 return NFCSTATUS_SUCCESS; 436 } 437 438 /******************************************************************************* 439 ** 440 ** Function phNxpExtns_ProcessSysMessage 441 ** 442 ** Description Internal function to route the request from JNI and Callback 443 ** from NFA_SendRawFrame to right function 444 ** 445 ** Returns NFCSTATUS_SUCCESS if valid request 446 ** NFCSTATUS_FAILED otherwise 447 ** 448 *******************************************************************************/ 449 static NFCSTATUS phNxpExtns_ProcessSysMessage(phLibNfc_Message_t* msg) { 450 NFCSTATUS status = NFCSTATUS_SUCCESS; 451 452 if (gphNxpExtns_Context.Extns_status == EXTNS_STATUS_CLOSE) { 453 return NFCSTATUS_FAILED; 454 } 455 456 switch (msg->eMsgType) { 457 case PH_NXPEXTNS_RX_DATA: 458 status = Mfc_RecvPacket((uint8_t*)msg->pMsgData, msg->Size); 459 break; 460 461 case PH_NXPEXTNS_MIFARE_CHECK_NDEF: 462 pthread_mutex_init(&gAuthCmdBuf.syncmutex, NULL); 463 pthread_mutex_lock(&gAuthCmdBuf.syncmutex); 464 status = Mfc_CheckNdef(); 465 pthread_mutex_unlock(&gAuthCmdBuf.syncmutex); 466 pthread_mutex_destroy(&gAuthCmdBuf.syncmutex); 467 break; 468 469 case PH_NXPEXTNS_MIFARE_READ_NDEF: 470 status = Mfc_ReadNdef(); 471 break; 472 473 case PH_NXPEXTNS_MIFARE_WRITE_NDEF: 474 status = Mfc_WriteNdef((uint8_t*)msg->pMsgData, msg->Size); 475 break; 476 477 case PH_NXPEXTNS_MIFARE_FORMAT_NDEF: 478 status = Mfc_FormatNdef((uint8_t*)msg->pMsgData, msg->Size); 479 break; 480 481 case PH_NXPEXTNS_DISCONNECT: 482 Mfc_DeactivateCbackSelect(); 483 break; 484 485 case PH_NXPEXTNS_ACTIVATED: 486 Mfc_ActivateCback(); 487 break; 488 489 case PH_NXPEXTNS_MIFARE_TRANSCEIVE: 490 status = Mfc_Transceive((uint8_t*)msg->pMsgData, msg->Size); 491 break; 492 493 case PH_NXPEXTNS_MIFARE_READ_ONLY: 494 status = Mfc_SetReadOnly((uint8_t*)msg->pMsgData, msg->Size); 495 break; 496 case PH_NXPEXTNS_MIFARE_PRESENCE_CHECK: 497 pthread_mutex_init(&gAuthCmdBuf.syncmutex, NULL); 498 pthread_mutex_lock(&gAuthCmdBuf.syncmutex); 499 status = Mfc_PresenceCheck(); 500 pthread_mutex_unlock(&gAuthCmdBuf.syncmutex); 501 pthread_mutex_destroy(&gAuthCmdBuf.syncmutex); 502 break; 503 default: 504 status = NFCSTATUS_FAILED; 505 LOG(ERROR) << StringPrintf("Illegal Command for Extension"); 506 break; 507 } 508 509 return status; 510 } 511 512 /******************************************************************************* 513 ** 514 ** Function phNxpExtns_SendMsg 515 ** 516 ** Description unlocks phNxpExtns_ProcessSysMessage with a valid message 517 ** 518 ** Returns NFCSTATUS_SUCCESS if successfully initiated 519 ** NFCSTATUS_FAILED otherwise 520 ** 521 *******************************************************************************/ 522 static NFCSTATUS phNxpExtns_SendMsg(phLibNfc_Message_t* sysmsg) { 523 NFCSTATUS status = NFCSTATUS_SUCCESS; 524 525 status = phNxpExtns_ProcessSysMessage(sysmsg); 526 527 return status; 528 } 529 530 /******************************************************************************* 531 ** 532 ** Function EXTNS_MfcRegisterNDefTypeHandler 533 ** 534 ** Description This function allows the applications to register for 535 ** specific types of NDEF records. 536 ** 537 ** For records types which were not registered, the record will 538 ** be sent to the default handler. 539 ** 540 ** Returns NFCSTATUS_SUCCESS 541 ** 542 *******************************************************************************/ 543 NFCSTATUS 544 EXTNS_MfcRegisterNDefTypeHandler(tNFA_NDEF_CBACK* ndefHandlerCallback) { 545 NFCSTATUS status = NFCSTATUS_FAILED; 546 if (NULL != ndefHandlerCallback) { 547 gphNxpExtns_Context.p_ndef_cback = ndefHandlerCallback; 548 status = NFCSTATUS_SUCCESS; 549 } 550 551 return status; 552 } 553 554 /******************************************************************************* 555 ** Synchronizing Functions ** 556 ** Synchronizes Callback in JNI and MFC Extns ** 557 *******************************************************************************/ 558 559 bool_t EXTNS_GetConnectFlag(void) { return (gphNxpExtns_Context.ExtnsConnect); } 560 561 void EXTNS_SetConnectFlag(bool_t flagval) { 562 gphNxpExtns_Context.ExtnsConnect = flagval; 563 } 564 565 bool_t EXTNS_GetDeactivateFlag(void) { 566 return (gphNxpExtns_Context.ExtnsDeactivate); 567 } 568 569 void EXTNS_SetDeactivateFlag(bool_t flagval) { 570 gphNxpExtns_Context.ExtnsDeactivate = flagval; 571 } 572 573 bool_t EXTNS_GetCallBackFlag(void) { 574 return (gphNxpExtns_Context.ExtnsCallBack); 575 } 576 577 void EXTNS_SetCallBackFlag(bool_t flagval) { 578 gphNxpExtns_Context.ExtnsCallBack = flagval; 579 } 580 NFCSTATUS EXTNS_GetPresenceCheckStatus(void) { 581 struct timespec ts; 582 583 clock_gettime(CLOCK_REALTIME, &ts); 584 ts.tv_sec += 0; 585 ts.tv_nsec += 100 * 1000 * 1000; // 100 milisec 586 if (ts.tv_nsec >= 1000 * 1000 * 1000) { 587 ts.tv_sec += 1; 588 ts.tv_nsec = ts.tv_nsec - (1000 * 1000 * 1000); 589 } 590 591 if (sem_timedwait(&gAuthCmdBuf.semPresenceCheck, &ts)) { 592 LOG(ERROR) << StringPrintf("%s: failed to wait (errno=%d)", __func__, 593 errno); 594 sem_destroy(&gAuthCmdBuf.semPresenceCheck); 595 gAuthCmdBuf.auth_sent = false; 596 return NFCSTATUS_FAILED; 597 } 598 if (sem_destroy(&gAuthCmdBuf.semPresenceCheck)) { 599 LOG(ERROR) << StringPrintf( 600 "%s: Failed to destroy check Presence semaphore (errno=%d)", __func__, 601 errno); 602 } 603 return gAuthCmdBuf.status; 604 } 605 606 void MfcPresenceCheckResult(NFCSTATUS status) { 607 gAuthCmdBuf.status = status; 608 EXTNS_SetCallBackFlag(true); 609 sem_post(&gAuthCmdBuf.semPresenceCheck); 610 } 611 void MfcResetPresenceCheckStatus(void) { gAuthCmdBuf.auth_sent = false; } 612 /******************************************************************************* 613 ** 614 ** Function EXTNS_CheckMfcResponse 615 ** 616 ** Description This function is called from JNI Transceive for Mifare 617 ** Classic Tag status interpretation and to send the required 618 ** status to application 619 ** 620 ** Returns NFCSTATUS_SUCCESS 621 ** NFCSTATUS_FAILED 622 ** 623 *******************************************************************************/ 624 NFCSTATUS EXTNS_CheckMfcResponse(uint8_t** sTransceiveData, 625 uint32_t* sTransceiveDataLen) { 626 NFCSTATUS status = NFCSTATUS_SUCCESS; 627 628 if (*sTransceiveDataLen == 3) { 629 if ((*sTransceiveData)[0] == 0x10 && (*sTransceiveData)[1] != 0x0A) { 630 LOG(ERROR) << StringPrintf("Mifare Error in payload response"); 631 *sTransceiveDataLen = 0x1; 632 *sTransceiveData += 1; 633 return NFCSTATUS_FAILED; 634 } 635 } 636 if ((*sTransceiveData)[0] == 0x40) { 637 *sTransceiveData += 1; 638 *sTransceiveDataLen = 0x01; 639 if ((*sTransceiveData)[0] == 0x03) { 640 *sTransceiveDataLen = 0x00; 641 status = NFCSTATUS_FAILED; 642 } 643 } else if ((*sTransceiveData)[0] == 0x10) { 644 *sTransceiveData += 1; 645 *sTransceiveDataLen = 0x10; 646 } 647 648 return status; 649 } 650