1 /* 2 * Copyright (C) 2012 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 17 #include <android-base/stringprintf.h> 18 #include <base/logging.h> 19 #include <errno.h> 20 #include <malloc.h> 21 #include <nativehelper/ScopedLocalRef.h> 22 #include <nativehelper/ScopedPrimitiveArray.h> 23 #include <semaphore.h> 24 #include <signal.h> 25 #include <string.h> 26 #include <time.h> 27 #include <string> 28 #include "IntervalTimer.h" 29 #include "JavaClassConstants.h" 30 #include "Mutex.h" 31 #include "NfcJniUtil.h" 32 #include "NfcTag.h" 33 #include "Pn544Interop.h" 34 35 #include "ndef_utils.h" 36 #include "nfa_api.h" 37 #include "nfa_rw_api.h" 38 #include "nfc_brcm_defs.h" 39 #include "phNxpExtns.h" 40 #include "rw_api.h" 41 42 using android::base::StringPrintf; 43 44 namespace android { 45 extern nfc_jni_native_data* getNative(JNIEnv* e, jobject o); 46 extern bool nfcManager_isNfcActive(); 47 } // namespace android 48 49 extern bool gActivated; 50 extern SyncEvent gDeactivatedEvent; 51 extern bool nfc_debug_enabled; 52 53 /***************************************************************************** 54 ** 55 ** public variables and functions 56 ** 57 *****************************************************************************/ 58 namespace android { 59 bool gIsTagDeactivating = false; // flag for nfa callback indicating we are 60 // deactivating for RF interface switch 61 bool gIsSelectingRfInterface = 62 false; // flag for nfa callback indicating we are 63 // selecting for RF interface switch 64 } // namespace android 65 66 /***************************************************************************** 67 ** 68 ** private variables and functions 69 ** 70 *****************************************************************************/ 71 namespace android { 72 73 // Pre-defined tag type values. These must match the values in 74 // framework Ndef.java for Google public NFC API. 75 #define NDEF_UNKNOWN_TYPE (-1) 76 #define NDEF_TYPE1_TAG 1 77 #define NDEF_TYPE2_TAG 2 78 #define NDEF_TYPE3_TAG 3 79 #define NDEF_TYPE4_TAG 4 80 #define NDEF_MIFARE_CLASSIC_TAG 101 81 82 #define STATUS_CODE_TARGET_LOST 146 // this error code comes from the service 83 84 static uint32_t sCheckNdefCurrentSize = 0; 85 static tNFA_STATUS sCheckNdefStatus = 86 0; // whether tag already contains a NDEF message 87 static bool sCheckNdefCapable = false; // whether tag has NDEF capability 88 static tNFA_HANDLE sNdefTypeHandlerHandle = NFA_HANDLE_INVALID; 89 static tNFA_INTF_TYPE sCurrentRfInterface = NFA_INTERFACE_ISO_DEP; 90 static std::basic_string<uint8_t> sRxDataBuffer; 91 static tNFA_STATUS sRxDataStatus = NFA_STATUS_OK; 92 static bool sWaitingForTransceive = false; 93 static bool sTransceiveRfTimeout = false; 94 static Mutex sRfInterfaceMutex; 95 static uint32_t sReadDataLen = 0; 96 static uint8_t* sReadData = NULL; 97 static bool sIsReadingNdefMessage = false; 98 static SyncEvent sReadEvent; 99 static sem_t sWriteSem; 100 static sem_t sFormatSem; 101 static SyncEvent sTransceiveEvent; 102 static SyncEvent sReconnectEvent; 103 static sem_t sCheckNdefSem; 104 static SyncEvent sPresenceCheckEvent; 105 static sem_t sMakeReadonlySem; 106 static IntervalTimer sSwitchBackTimer; // timer used to tell us to switch back 107 // to ISO_DEP frame interface 108 static jboolean sWriteOk = JNI_FALSE; 109 static jboolean sWriteWaitingForComplete = JNI_FALSE; 110 static bool sFormatOk = false; 111 static jboolean sConnectOk = JNI_FALSE; 112 static jboolean sConnectWaitingForComplete = JNI_FALSE; 113 static bool sGotDeactivate = false; 114 static uint32_t sCheckNdefMaxSize = 0; 115 static bool sCheckNdefCardReadOnly = false; 116 static jboolean sCheckNdefWaitingForComplete = JNI_FALSE; 117 static bool sIsTagPresent = true; 118 static tNFA_STATUS sMakeReadonlyStatus = NFA_STATUS_FAILED; 119 static jboolean sMakeReadonlyWaitingForComplete = JNI_FALSE; 120 static int sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN; 121 static int sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN; 122 static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded); 123 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface); 124 125 /******************************************************************************* 126 ** 127 ** Function: nativeNfcTag_abortWaits 128 ** 129 ** Description: Unblock all thread synchronization objects. 130 ** 131 ** Returns: None 132 ** 133 *******************************************************************************/ 134 void nativeNfcTag_abortWaits() { 135 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 136 { 137 SyncEventGuard g(sReadEvent); 138 sReadEvent.notifyOne(); 139 } 140 sem_post(&sWriteSem); 141 sem_post(&sFormatSem); 142 { 143 SyncEventGuard g(sTransceiveEvent); 144 sTransceiveEvent.notifyOne(); 145 } 146 { 147 SyncEventGuard g(sReconnectEvent); 148 sReconnectEvent.notifyOne(); 149 } 150 151 sem_post(&sCheckNdefSem); 152 { 153 SyncEventGuard guard(sPresenceCheckEvent); 154 sPresenceCheckEvent.notifyOne(); 155 } 156 sem_post(&sMakeReadonlySem); 157 sCurrentRfInterface = NFA_INTERFACE_ISO_DEP; 158 sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN; 159 sCurrentConnectedTargetProtocol = NFC_PROTOCOL_UNKNOWN; 160 } 161 162 /******************************************************************************* 163 ** 164 ** Function: nativeNfcTag_doReadCompleted 165 ** 166 ** Description: Receive the completion status of read operation. Called by 167 ** NFA_READ_CPLT_EVT. 168 ** status: Status of operation. 169 ** 170 ** Returns: None 171 ** 172 *******************************************************************************/ 173 void nativeNfcTag_doReadCompleted(tNFA_STATUS status) { 174 DLOG_IF(INFO, nfc_debug_enabled) 175 << StringPrintf("%s: status=0x%X; is reading=%u", __func__, status, 176 sIsReadingNdefMessage); 177 178 if (sIsReadingNdefMessage == false) 179 return; // not reading NDEF message right now, so just return 180 181 if (status != NFA_STATUS_OK) { 182 sReadDataLen = 0; 183 if (sReadData) free(sReadData); 184 sReadData = NULL; 185 } 186 SyncEventGuard g(sReadEvent); 187 sReadEvent.notifyOne(); 188 } 189 190 /******************************************************************************* 191 ** 192 ** Function: nativeNfcTag_setRfInterface 193 ** 194 ** Description: Set rf interface. 195 ** 196 ** Returns: void 197 ** 198 *******************************************************************************/ 199 void nativeNfcTag_setRfInterface(tNFA_INTF_TYPE rfInterface) { 200 sCurrentRfInterface = rfInterface; 201 } 202 203 /******************************************************************************* 204 ** 205 ** Function: ndefHandlerCallback 206 ** 207 ** Description: Receive NDEF-message related events from stack. 208 ** event: Event code. 209 ** p_data: Event data. 210 ** 211 ** Returns: None 212 ** 213 *******************************************************************************/ 214 static void ndefHandlerCallback(tNFA_NDEF_EVT event, 215 tNFA_NDEF_EVT_DATA* eventData) { 216 DLOG_IF(INFO, nfc_debug_enabled) 217 << StringPrintf("%s: event=%u, eventData=%p", __func__, event, eventData); 218 219 switch (event) { 220 case NFA_NDEF_REGISTER_EVT: { 221 tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg; 222 DLOG_IF(INFO, nfc_debug_enabled) 223 << StringPrintf("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X", 224 __func__, ndef_reg.status, ndef_reg.ndef_type_handle); 225 sNdefTypeHandlerHandle = ndef_reg.ndef_type_handle; 226 } break; 227 228 case NFA_NDEF_DATA_EVT: { 229 DLOG_IF(INFO, nfc_debug_enabled) 230 << StringPrintf("%s: NFA_NDEF_DATA_EVT; data_len = %u", __func__, 231 eventData->ndef_data.len); 232 sReadDataLen = eventData->ndef_data.len; 233 sReadData = (uint8_t*)malloc(sReadDataLen); 234 memcpy(sReadData, eventData->ndef_data.p_data, eventData->ndef_data.len); 235 } break; 236 237 default: 238 LOG(ERROR) << StringPrintf("%s: Unknown event %u ????", __func__, event); 239 break; 240 } 241 } 242 243 /******************************************************************************* 244 ** 245 ** Function: nativeNfcTag_doRead 246 ** 247 ** Description: Read the NDEF message on the tag. 248 ** e: JVM environment. 249 ** o: Java object. 250 ** 251 ** Returns: NDEF message. 252 ** 253 *******************************************************************************/ 254 static jbyteArray nativeNfcTag_doRead(JNIEnv* e, jobject) { 255 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 256 tNFA_STATUS status = NFA_STATUS_FAILED; 257 jbyteArray buf = NULL; 258 259 sReadDataLen = 0; 260 if (sReadData != NULL) { 261 free(sReadData); 262 sReadData = NULL; 263 } 264 265 if (sCheckNdefCurrentSize > 0) { 266 { 267 SyncEventGuard g(sReadEvent); 268 sIsReadingNdefMessage = true; 269 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 270 status = EXTNS_MfcReadNDef(); 271 } else { 272 status = NFA_RwReadNDef(); 273 } 274 sReadEvent.wait(); // wait for NFA_READ_CPLT_EVT 275 } 276 sIsReadingNdefMessage = false; 277 278 if (sReadDataLen > 0) // if stack actually read data from the tag 279 { 280 DLOG_IF(INFO, nfc_debug_enabled) 281 << StringPrintf("%s: read %u bytes", __func__, sReadDataLen); 282 buf = e->NewByteArray(sReadDataLen); 283 e->SetByteArrayRegion(buf, 0, sReadDataLen, (jbyte*)sReadData); 284 } 285 } else { 286 DLOG_IF(INFO, nfc_debug_enabled) 287 << StringPrintf("%s: create empty buffer", __func__); 288 sReadDataLen = 0; 289 sReadData = (uint8_t*)malloc(1); 290 buf = e->NewByteArray(sReadDataLen); 291 e->SetByteArrayRegion(buf, 0, sReadDataLen, (jbyte*)sReadData); 292 } 293 294 if (sReadData) { 295 free(sReadData); 296 sReadData = NULL; 297 } 298 sReadDataLen = 0; 299 300 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); 301 return buf; 302 } 303 304 /******************************************************************************* 305 ** 306 ** Function: nativeNfcTag_doWriteStatus 307 ** 308 ** Description: Receive the completion status of write operation. Called 309 ** by NFA_WRITE_CPLT_EVT. 310 ** isWriteOk: Status of operation. 311 ** 312 ** Returns: None 313 ** 314 *******************************************************************************/ 315 void nativeNfcTag_doWriteStatus(jboolean isWriteOk) { 316 if (sWriteWaitingForComplete != JNI_FALSE) { 317 sWriteWaitingForComplete = JNI_FALSE; 318 sWriteOk = isWriteOk; 319 sem_post(&sWriteSem); 320 } 321 } 322 323 /******************************************************************************* 324 ** 325 ** Function: nativeNfcTag_formatStatus 326 ** 327 ** Description: Receive the completion status of format operation. Called 328 ** by NFA_FORMAT_CPLT_EVT. 329 ** isOk: Status of operation. 330 ** 331 ** Returns: None 332 ** 333 *******************************************************************************/ 334 void nativeNfcTag_formatStatus(bool isOk) { 335 sFormatOk = isOk; 336 sem_post(&sFormatSem); 337 } 338 339 /******************************************************************************* 340 ** 341 ** Function: nativeNfcTag_doWrite 342 ** 343 ** Description: Write a NDEF message to the tag. 344 ** e: JVM environment. 345 ** o: Java object. 346 ** buf: Contains a NDEF message. 347 ** 348 ** Returns: True if ok. 349 ** 350 *******************************************************************************/ 351 static jboolean nativeNfcTag_doWrite(JNIEnv* e, jobject, jbyteArray buf) { 352 jboolean result = JNI_FALSE; 353 tNFA_STATUS status = 0; 354 const int maxBufferSize = 1024; 355 uint8_t buffer[maxBufferSize] = {0}; 356 uint32_t curDataSize = 0; 357 358 ScopedByteArrayRO bytes(e, buf); 359 uint8_t* p_data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>( 360 &bytes[0])); // TODO: const-ness API bug in NFA_RwWriteNDef! 361 362 DLOG_IF(INFO, nfc_debug_enabled) 363 << StringPrintf("%s: enter; len = %zu", __func__, bytes.size()); 364 365 /* Create the write semaphore */ 366 if (sem_init(&sWriteSem, 0, 0) == -1) { 367 LOG(ERROR) << StringPrintf("%s: semaphore creation failed (errno=0x%08x)", 368 __func__, errno); 369 return JNI_FALSE; 370 } 371 372 sWriteWaitingForComplete = JNI_TRUE; 373 if (sCheckNdefStatus == NFA_STATUS_FAILED) { 374 // if tag does not contain a NDEF message 375 // and tag is capable of storing NDEF message 376 if (sCheckNdefCapable) { 377 DLOG_IF(INFO, nfc_debug_enabled) 378 << StringPrintf("%s: try format", __func__); 379 sem_init(&sFormatSem, 0, 0); 380 sFormatOk = false; 381 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 382 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 383 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; 384 385 status = EXTNS_MfcFormatTag(mfc_key1, sizeof(mfc_key1)); 386 if (status != NFA_STATUS_OK) { 387 LOG(ERROR) << StringPrintf("%s: can't format mifare classic tag", 388 __func__); 389 sem_destroy(&sFormatSem); 390 goto TheEnd; 391 } 392 393 if (sFormatOk == false) // if format operation failed 394 { 395 sem_wait(&sFormatSem); 396 sem_destroy(&sFormatSem); 397 sem_init(&sFormatSem, 0, 0); 398 status = EXTNS_MfcFormatTag(mfc_key2, sizeof(mfc_key2)); 399 if (status != NFA_STATUS_OK) { 400 LOG(ERROR) << StringPrintf("%s: can't format mifare classic tag", 401 __func__); 402 sem_destroy(&sFormatSem); 403 goto TheEnd; 404 } 405 } 406 } else { 407 status = NFA_RwFormatTag(); 408 } 409 sem_wait(&sFormatSem); 410 sem_destroy(&sFormatSem); 411 if (sFormatOk == false) // if format operation failed 412 goto TheEnd; 413 } 414 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: try write", __func__); 415 status = NFA_RwWriteNDef(p_data, bytes.size()); 416 } else if (bytes.size() == 0) { 417 // if (NXP TagWriter wants to erase tag) then create and write an empty ndef 418 // message 419 NDEF_MsgInit(buffer, maxBufferSize, &curDataSize); 420 status = NDEF_MsgAddRec(buffer, maxBufferSize, &curDataSize, NDEF_TNF_EMPTY, 421 NULL, 0, NULL, 0, NULL, 0); 422 DLOG_IF(INFO, nfc_debug_enabled) 423 << StringPrintf("%s: create empty ndef msg; status=%u; size=%u", 424 __func__, status, curDataSize); 425 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 426 status = EXTNS_MfcWriteNDef(buffer, curDataSize); 427 } else { 428 status = NFA_RwWriteNDef(buffer, curDataSize); 429 } 430 } else { 431 DLOG_IF(INFO, nfc_debug_enabled) 432 << StringPrintf("%s: NFA_RwWriteNDef", __func__); 433 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 434 status = EXTNS_MfcWriteNDef(p_data, bytes.size()); 435 } else { 436 status = NFA_RwWriteNDef(p_data, bytes.size()); 437 } 438 } 439 440 if (status != NFA_STATUS_OK) { 441 LOG(ERROR) << StringPrintf("%s: write/format error=%d", __func__, status); 442 goto TheEnd; 443 } 444 445 /* Wait for write completion status */ 446 sWriteOk = false; 447 if (sem_wait(&sWriteSem)) { 448 LOG(ERROR) << StringPrintf("%s: wait semaphore (errno=0x%08x)", __func__, 449 errno); 450 goto TheEnd; 451 } 452 453 result = sWriteOk; 454 455 TheEnd: 456 /* Destroy semaphore */ 457 if (sem_destroy(&sWriteSem)) { 458 LOG(ERROR) << StringPrintf("%s: failed destroy semaphore (errno=0x%08x)", 459 __func__, errno); 460 } 461 sWriteWaitingForComplete = JNI_FALSE; 462 DLOG_IF(INFO, nfc_debug_enabled) 463 << StringPrintf("%s: exit; result=%d", __func__, result); 464 return result; 465 } 466 467 /******************************************************************************* 468 ** 469 ** Function: nativeNfcTag_doConnectStatus 470 ** 471 ** Description: Receive the completion status of connect operation. 472 ** isConnectOk: Status of the operation. 473 ** 474 ** Returns: None 475 ** 476 *******************************************************************************/ 477 void nativeNfcTag_doConnectStatus(jboolean isConnectOk) { 478 if (EXTNS_GetConnectFlag() == TRUE) { 479 EXTNS_MfcActivated(); 480 EXTNS_SetConnectFlag(FALSE); 481 return; 482 } 483 484 if (sConnectWaitingForComplete != JNI_FALSE) { 485 sConnectWaitingForComplete = JNI_FALSE; 486 sConnectOk = isConnectOk; 487 SyncEventGuard g(sReconnectEvent); 488 sReconnectEvent.notifyOne(); 489 } 490 } 491 492 /******************************************************************************* 493 ** 494 ** Function: nativeNfcTag_doDeactivateStatus 495 ** 496 ** Description: Receive the completion status of deactivate operation. 497 ** 498 ** Returns: None 499 ** 500 *******************************************************************************/ 501 void nativeNfcTag_doDeactivateStatus(int status) { 502 if (EXTNS_GetDeactivateFlag() == TRUE) { 503 EXTNS_MfcDisconnect(); 504 EXTNS_SetDeactivateFlag(FALSE); 505 return; 506 } 507 508 sGotDeactivate = (status == 0); 509 510 SyncEventGuard g(sReconnectEvent); 511 sReconnectEvent.notifyOne(); 512 } 513 514 /******************************************************************************* 515 ** 516 ** Function: nativeNfcTag_doConnect 517 ** 518 ** Description: Connect to the tag in RF field. 519 ** e: JVM environment. 520 ** o: Java object. 521 ** targetHandle: Handle of the tag. 522 ** 523 ** Returns: Must return NXP status code, which NFC service expects. 524 ** 525 *******************************************************************************/ 526 static jint nativeNfcTag_doConnect(JNIEnv*, jobject, jint targetHandle) { 527 DLOG_IF(INFO, nfc_debug_enabled) 528 << StringPrintf("%s: targetHandle = %d", __func__, targetHandle); 529 int i = targetHandle; 530 NfcTag& natTag = NfcTag::getInstance(); 531 int retCode = NFCSTATUS_SUCCESS; 532 533 if (i >= NfcTag::MAX_NUM_TECHNOLOGY) { 534 LOG(ERROR) << StringPrintf("%s: Handle not found", __func__); 535 retCode = NFCSTATUS_FAILED; 536 goto TheEnd; 537 } 538 539 if (natTag.getActivationState() != NfcTag::Active) { 540 LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__); 541 retCode = NFCSTATUS_FAILED; 542 goto TheEnd; 543 } 544 545 sCurrentConnectedTargetType = natTag.mTechList[i]; 546 sCurrentConnectedTargetProtocol = natTag.mTechLibNfcTypes[i]; 547 548 if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP) { 549 DLOG_IF(INFO, nfc_debug_enabled) 550 << StringPrintf("%s() Nfc type = %d, do nothing for non ISO_DEP", 551 __func__, sCurrentConnectedTargetProtocol); 552 retCode = NFCSTATUS_SUCCESS; 553 goto TheEnd; 554 } 555 556 if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A || 557 sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3B) { 558 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 559 "%s: switching to tech: %d need to switch rf intf to frame", __func__, 560 sCurrentConnectedTargetType); 561 retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK 562 : NFA_STATUS_FAILED; 563 } else { 564 retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK 565 : NFA_STATUS_FAILED; 566 } 567 568 TheEnd: 569 DLOG_IF(INFO, nfc_debug_enabled) 570 << StringPrintf("%s: exit 0x%X", __func__, retCode); 571 return retCode; 572 } 573 574 /******************************************************************************* 575 ** 576 ** Function: reSelect 577 ** 578 ** Description: Deactivates the tag and re-selects it with the specified 579 ** rf interface. 580 ** 581 ** Returns: status code, 0 on success, 1 on failure, 582 ** 146 (defined in service) on tag lost 583 ** 584 *******************************************************************************/ 585 static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded) { 586 DLOG_IF(INFO, nfc_debug_enabled) 587 << StringPrintf("%s: enter; rf intf = %d, current intf = %d", __func__, 588 rfInterface, sCurrentRfInterface); 589 590 sRfInterfaceMutex.lock(); 591 592 if (fSwitchIfNeeded && (rfInterface == sCurrentRfInterface)) { 593 // already in the requested interface 594 sRfInterfaceMutex.unlock(); 595 return 0; // success 596 } 597 598 NfcTag& natTag = NfcTag::getInstance(); 599 600 tNFA_STATUS status; 601 int rVal = 1; 602 603 do { 604 // if tag has shutdown, abort this method 605 if (NfcTag::getInstance().isNdefDetectionTimedOut()) { 606 DLOG_IF(INFO, nfc_debug_enabled) 607 << StringPrintf("%s: ndef detection timeout; break", __func__); 608 rVal = STATUS_CODE_TARGET_LOST; 609 break; 610 } 611 612 { 613 SyncEventGuard g(sReconnectEvent); 614 gIsTagDeactivating = true; 615 sGotDeactivate = false; 616 DLOG_IF(INFO, nfc_debug_enabled) 617 << StringPrintf("%s: deactivate to sleep", __func__); 618 if (NFA_STATUS_OK != 619 (status = NFA_Deactivate(TRUE))) // deactivate to sleep state 620 { 621 LOG(ERROR) << StringPrintf("%s: deactivate failed, status = %d", 622 __func__, status); 623 break; 624 } 625 626 if (sReconnectEvent.wait(1000) == false) // if timeout occurred 627 { 628 LOG(ERROR) << StringPrintf("%s: timeout waiting for deactivate", 629 __func__); 630 } 631 } 632 633 if (!sGotDeactivate) { 634 rVal = STATUS_CODE_TARGET_LOST; 635 break; 636 } 637 638 if (NfcTag::getInstance().getActivationState() != NfcTag::Sleep) { 639 LOG(ERROR) << StringPrintf("%s: tag is not in sleep", __func__); 640 rVal = STATUS_CODE_TARGET_LOST; 641 break; 642 } 643 644 gIsTagDeactivating = false; 645 646 { 647 SyncEventGuard g2(sReconnectEvent); 648 649 sConnectWaitingForComplete = JNI_TRUE; 650 DLOG_IF(INFO, nfc_debug_enabled) 651 << StringPrintf("%s: select interface %u", __func__, rfInterface); 652 gIsSelectingRfInterface = true; 653 if (NFA_STATUS_OK != 654 (status = NFA_Select(natTag.mTechHandles[0], 655 natTag.mTechLibNfcTypes[0], rfInterface))) { 656 LOG(ERROR) << StringPrintf("%s: NFA_Select failed, status = %d", 657 __func__, status); 658 break; 659 } 660 661 sConnectOk = false; 662 if (sReconnectEvent.wait(1000) == false) // if timeout occured 663 { 664 LOG(ERROR) << StringPrintf("%s: timeout waiting for select", __func__); 665 break; 666 } 667 } 668 669 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 670 "%s: select completed; sConnectOk=%d", __func__, sConnectOk); 671 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) { 672 LOG(ERROR) << StringPrintf("%s: tag is not active", __func__); 673 rVal = STATUS_CODE_TARGET_LOST; 674 break; 675 } 676 if (sConnectOk) { 677 rVal = 0; // success 678 sCurrentRfInterface = rfInterface; 679 } else { 680 rVal = 1; 681 } 682 } while (0); 683 684 sConnectWaitingForComplete = JNI_FALSE; 685 gIsTagDeactivating = false; 686 gIsSelectingRfInterface = false; 687 sRfInterfaceMutex.unlock(); 688 DLOG_IF(INFO, nfc_debug_enabled) 689 << StringPrintf("%s: exit; status=%d", __func__, rVal); 690 return rVal; 691 } 692 693 /******************************************************************************* 694 ** 695 ** Function: switchRfInterface 696 ** 697 ** Description: Switch controller's RF interface to frame, ISO-DEP, or 698 *NFC-DEP. 699 ** rfInterface: Type of RF interface. 700 ** 701 ** Returns: True if ok. 702 ** 703 *******************************************************************************/ 704 static bool switchRfInterface(tNFA_INTF_TYPE rfInterface) { 705 NfcTag& natTag = NfcTag::getInstance(); 706 707 if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP) { 708 DLOG_IF(INFO, nfc_debug_enabled) 709 << StringPrintf("%s: protocol: %d not ISO_DEP, do nothing", __func__, 710 natTag.mTechLibNfcTypes[0]); 711 return true; 712 } 713 714 DLOG_IF(INFO, nfc_debug_enabled) 715 << StringPrintf("%s: new rf intf = %d, cur rf intf = %d", __func__, 716 rfInterface, sCurrentRfInterface); 717 718 return (0 == reSelect(rfInterface, true)); 719 } 720 721 /******************************************************************************* 722 ** 723 ** Function: nativeNfcTag_doReconnect 724 ** 725 ** Description: Re-connect to the tag in RF field. 726 ** e: JVM environment. 727 ** o: Java object. 728 ** 729 ** Returns: Status code. 730 ** 731 *******************************************************************************/ 732 static jint nativeNfcTag_doReconnect(JNIEnv*, jobject) { 733 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 734 int retCode = NFCSTATUS_SUCCESS; 735 NfcTag& natTag = NfcTag::getInstance(); 736 737 if (natTag.getActivationState() != NfcTag::Active) { 738 LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__); 739 retCode = NFCSTATUS_FAILED; 740 goto TheEnd; 741 } 742 743 // special case for Kovio 744 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) { 745 DLOG_IF(INFO, nfc_debug_enabled) 746 << StringPrintf("%s: fake out reconnect for Kovio", __func__); 747 goto TheEnd; 748 } 749 750 // this is only supported for type 2 or 4 (ISO_DEP) tags 751 if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP) 752 retCode = reSelect(NFA_INTERFACE_ISO_DEP, false); 753 else if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_T2T) 754 retCode = reSelect(NFA_INTERFACE_FRAME, false); 755 else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) 756 retCode = reSelect(NFA_INTERFACE_MIFARE, false); 757 758 TheEnd: 759 DLOG_IF(INFO, nfc_debug_enabled) 760 << StringPrintf("%s: exit 0x%X", __func__, retCode); 761 return retCode; 762 } 763 764 /******************************************************************************* 765 ** 766 ** Function: nativeNfcTag_doHandleReconnect 767 ** 768 ** Description: Re-connect to the tag in RF field. 769 ** e: JVM environment. 770 ** o: Java object. 771 ** targetHandle: Handle of the tag. 772 ** 773 ** Returns: Status code. 774 ** 775 *******************************************************************************/ 776 static jint nativeNfcTag_doHandleReconnect(JNIEnv* e, jobject o, 777 jint targetHandle) { 778 DLOG_IF(INFO, nfc_debug_enabled) 779 << StringPrintf("%s: targetHandle = %d", __func__, targetHandle); 780 return nativeNfcTag_doConnect(e, o, targetHandle); 781 } 782 783 /******************************************************************************* 784 ** 785 ** Function: nativeNfcTag_doDisconnect 786 ** 787 ** Description: Deactivate the RF field. 788 ** e: JVM environment. 789 ** o: Java object. 790 ** 791 ** Returns: True if ok. 792 ** 793 *******************************************************************************/ 794 jboolean nativeNfcTag_doDisconnect(JNIEnv*, jobject) { 795 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 796 tNFA_STATUS nfaStat = NFA_STATUS_OK; 797 798 NfcTag::getInstance().resetAllTransceiveTimeouts(); 799 800 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) { 801 LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__); 802 goto TheEnd; 803 } 804 805 nfaStat = NFA_Deactivate(FALSE); 806 if (nfaStat != NFA_STATUS_OK) 807 LOG(ERROR) << StringPrintf("%s: deactivate failed; error=0x%X", __func__, 808 nfaStat); 809 810 TheEnd: 811 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); 812 return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE; 813 } 814 815 /******************************************************************************* 816 ** 817 ** Function: nativeNfcTag_doTransceiveStatus 818 ** 819 ** Description: Receive the completion status of transceive operation. 820 ** status: operation status. 821 ** buf: Contains tag's response. 822 ** bufLen: Length of buffer. 823 ** 824 ** Returns: None 825 ** 826 *******************************************************************************/ 827 void nativeNfcTag_doTransceiveStatus(tNFA_STATUS status, uint8_t* buf, 828 uint32_t bufLen) { 829 SyncEventGuard g(sTransceiveEvent); 830 DLOG_IF(INFO, nfc_debug_enabled) 831 << StringPrintf("%s: data len=%d", __func__, bufLen); 832 833 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 834 if (EXTNS_GetCallBackFlag() == FALSE) { 835 EXTNS_MfcCallBack(buf, bufLen); 836 return; 837 } 838 } 839 840 if (!sWaitingForTransceive) { 841 LOG(ERROR) << StringPrintf("%s: drop data", __func__); 842 return; 843 } 844 sRxDataStatus = status; 845 if (sRxDataStatus == NFA_STATUS_OK || sRxDataStatus == NFC_STATUS_CONTINUE) 846 sRxDataBuffer.append(buf, bufLen); 847 848 if (sRxDataStatus == NFA_STATUS_OK) sTransceiveEvent.notifyOne(); 849 } 850 851 void nativeNfcTag_notifyRfTimeout() { 852 SyncEventGuard g(sTransceiveEvent); 853 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 854 "%s: waiting for transceive: %d", __func__, sWaitingForTransceive); 855 if (!sWaitingForTransceive) return; 856 857 sTransceiveRfTimeout = true; 858 859 sTransceiveEvent.notifyOne(); 860 } 861 862 /******************************************************************************* 863 ** 864 ** Function: nativeNfcTag_doTransceive 865 ** 866 ** Description: Send raw data to the tag; receive tag's response. 867 ** e: JVM environment. 868 ** o: Java object. 869 ** raw: Not used. 870 ** statusTargetLost: Whether tag responds or times out. 871 ** 872 ** Returns: Response from tag. 873 ** 874 *******************************************************************************/ 875 static jbyteArray nativeNfcTag_doTransceive(JNIEnv* e, jobject o, 876 jbyteArray data, jboolean raw, 877 jintArray statusTargetLost) { 878 int timeout = 879 NfcTag::getInstance().getTransceiveTimeout(sCurrentConnectedTargetType); 880 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 881 "%s: enter; raw=%u; timeout = %d", __func__, raw, timeout); 882 883 bool waitOk = false; 884 bool isNack = false; 885 jint* targetLost = NULL; 886 tNFA_STATUS status; 887 888 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) { 889 if (statusTargetLost) { 890 targetLost = e->GetIntArrayElements(statusTargetLost, 0); 891 if (targetLost) 892 *targetLost = 1; // causes NFC service to throw TagLostException 893 e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0); 894 } 895 DLOG_IF(INFO, nfc_debug_enabled) 896 << StringPrintf("%s: tag not active", __func__); 897 return NULL; 898 } 899 900 NfcTag& natTag = NfcTag::getInstance(); 901 902 // get input buffer and length from java call 903 ScopedByteArrayRO bytes(e, data); 904 uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>( 905 &bytes[0])); // TODO: API bug; NFA_SendRawFrame should take const*! 906 size_t bufLen = bytes.size(); 907 908 if (statusTargetLost) { 909 targetLost = e->GetIntArrayElements(statusTargetLost, 0); 910 if (targetLost) *targetLost = 0; // success, tag is still present 911 } 912 913 sSwitchBackTimer.kill(); 914 ScopedLocalRef<jbyteArray> result(e, NULL); 915 do { 916 { 917 SyncEventGuard g(sTransceiveEvent); 918 sTransceiveRfTimeout = false; 919 sWaitingForTransceive = true; 920 sRxDataStatus = NFA_STATUS_OK; 921 sRxDataBuffer.clear(); 922 923 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 924 status = EXTNS_MfcTransceive(buf, bufLen); 925 } else { 926 status = NFA_SendRawFrame(buf, bufLen, 927 NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY); 928 } 929 930 if (status != NFA_STATUS_OK) { 931 LOG(ERROR) << StringPrintf("%s: fail send; error=%d", __func__, status); 932 break; 933 } 934 waitOk = sTransceiveEvent.wait(timeout); 935 } 936 937 if (waitOk == false || sTransceiveRfTimeout) // if timeout occurred 938 { 939 LOG(ERROR) << StringPrintf("%s: wait response timeout", __func__); 940 if (targetLost) 941 *targetLost = 1; // causes NFC service to throw TagLostException 942 break; 943 } 944 945 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) { 946 LOG(ERROR) << StringPrintf("%s: already deactivated", __func__); 947 if (targetLost) 948 *targetLost = 1; // causes NFC service to throw TagLostException 949 break; 950 } 951 952 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 953 "%s: response %zu bytes", __func__, sRxDataBuffer.size()); 954 955 if ((natTag.getProtocol() == NFA_PROTOCOL_T2T) && 956 natTag.isT2tNackResponse(sRxDataBuffer.data(), sRxDataBuffer.size())) { 957 isNack = true; 958 } 959 960 if (sRxDataBuffer.size() > 0) { 961 if (isNack) { 962 // Some Mifare Ultralight C tags enter the HALT state after it 963 // responds with a NACK. Need to perform a "reconnect" operation 964 // to wake it. 965 DLOG_IF(INFO, nfc_debug_enabled) 966 << StringPrintf("%s: try reconnect", __func__); 967 nativeNfcTag_doReconnect(NULL, NULL); 968 DLOG_IF(INFO, nfc_debug_enabled) 969 << StringPrintf("%s: reconnect finish", __func__); 970 } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 971 uint32_t transDataLen = sRxDataBuffer.size(); 972 uint8_t* transData = (uint8_t*)sRxDataBuffer.data(); 973 if (EXTNS_CheckMfcResponse(&transData, &transDataLen) == 974 NFCSTATUS_FAILED) { 975 nativeNfcTag_doReconnect(e, o); 976 } 977 if (transDataLen != 0) { 978 result.reset(e->NewByteArray(transDataLen)); 979 if (result.get() != NULL) { 980 e->SetByteArrayRegion(result.get(), 0, transDataLen, 981 (const jbyte*)transData); 982 } else 983 LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array", 984 __func__); 985 } 986 } else { 987 // marshall data to java for return 988 result.reset(e->NewByteArray(sRxDataBuffer.size())); 989 if (result.get() != NULL) { 990 e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(), 991 (const jbyte*)sRxDataBuffer.data()); 992 } else 993 LOG(ERROR) << StringPrintf("%s: Failed to allocate java byte array", 994 __func__); 995 } // else a nack is treated as a transceive failure to the upper layers 996 997 sRxDataBuffer.clear(); 998 } 999 } while (0); 1000 1001 sWaitingForTransceive = false; 1002 if (targetLost) e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0); 1003 1004 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); 1005 return result.release(); 1006 } 1007 1008 /******************************************************************************* 1009 ** 1010 ** Function: nativeNfcTag_doGetNdefType 1011 ** 1012 ** Description: Retrieve the type of tag. 1013 ** e: JVM environment. 1014 ** o: Java object. 1015 ** libnfcType: Type of tag represented by JNI. 1016 ** javaType: Not used. 1017 ** 1018 ** Returns: Type of tag represented by NFC Service. 1019 ** 1020 *******************************************************************************/ 1021 static jint nativeNfcTag_doGetNdefType(JNIEnv*, jobject, jint libnfcType, 1022 jint javaType) { 1023 DLOG_IF(INFO, nfc_debug_enabled) 1024 << StringPrintf("%s: enter; libnfc type=%d; java type=%d", __func__, 1025 libnfcType, javaType); 1026 jint ndefType = NDEF_UNKNOWN_TYPE; 1027 1028 // For NFA, libnfcType is mapped to the protocol value received 1029 // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event. 1030 if (NFA_PROTOCOL_T1T == libnfcType) { 1031 ndefType = NDEF_TYPE1_TAG; 1032 } else if (NFA_PROTOCOL_T2T == libnfcType) { 1033 ndefType = NDEF_TYPE2_TAG; 1034 } else if (NFA_PROTOCOL_T3T == libnfcType) { 1035 ndefType = NDEF_TYPE3_TAG; 1036 } else if (NFA_PROTOCOL_ISO_DEP == libnfcType) { 1037 ndefType = NDEF_TYPE4_TAG; 1038 } else if (NFC_PROTOCOL_MIFARE == libnfcType) { 1039 ndefType = NDEF_MIFARE_CLASSIC_TAG; 1040 } else { 1041 /* NFA_PROTOCOL_T5T, NFA_PROTOCOL_INVALID and others */ 1042 ndefType = NDEF_UNKNOWN_TYPE; 1043 } 1044 DLOG_IF(INFO, nfc_debug_enabled) 1045 << StringPrintf("%s: exit; ndef type=%d", __func__, ndefType); 1046 return ndefType; 1047 } 1048 1049 /******************************************************************************* 1050 ** 1051 ** Function: nativeNfcTag_doCheckNdefResult 1052 ** 1053 ** Description: Receive the result of checking whether the tag contains a 1054 *NDEF 1055 ** message. Called by the NFA_NDEF_DETECT_EVT. 1056 ** status: Status of the operation. 1057 ** maxSize: Maximum size of NDEF message. 1058 ** currentSize: Current size of NDEF message. 1059 ** flags: Indicate various states. 1060 ** 1061 ** Returns: None 1062 ** 1063 *******************************************************************************/ 1064 void nativeNfcTag_doCheckNdefResult(tNFA_STATUS status, uint32_t maxSize, 1065 uint32_t currentSize, uint8_t flags) { 1066 // this function's flags parameter is defined using the following macros 1067 // in nfc/include/rw_api.h; 1068 //#define RW_NDEF_FL_READ_ONLY 0x01 /* Tag is read only */ 1069 //#define RW_NDEF_FL_FORMATED 0x02 /* Tag formated for NDEF */ 1070 //#define RW_NDEF_FL_SUPPORTED 0x04 /* NDEF supported by the tag */ 1071 //#define RW_NDEF_FL_UNKNOWN 0x08 /* Unable to find if tag is ndef 1072 // capable/formated/read only */ #define RW_NDEF_FL_FORMATABLE 0x10 /* Tag 1073 // supports format operation */ 1074 1075 if (!sCheckNdefWaitingForComplete) { 1076 LOG(ERROR) << StringPrintf("%s: not waiting", __func__); 1077 return; 1078 } 1079 1080 if (flags & RW_NDEF_FL_READ_ONLY) 1081 DLOG_IF(INFO, nfc_debug_enabled) 1082 << StringPrintf("%s: flag read-only", __func__); 1083 if (flags & RW_NDEF_FL_FORMATED) 1084 DLOG_IF(INFO, nfc_debug_enabled) 1085 << StringPrintf("%s: flag formatted for ndef", __func__); 1086 if (flags & RW_NDEF_FL_SUPPORTED) 1087 DLOG_IF(INFO, nfc_debug_enabled) 1088 << StringPrintf("%s: flag ndef supported", __func__); 1089 if (flags & RW_NDEF_FL_UNKNOWN) 1090 DLOG_IF(INFO, nfc_debug_enabled) 1091 << StringPrintf("%s: flag all unknown", __func__); 1092 if (flags & RW_NDEF_FL_FORMATABLE) 1093 DLOG_IF(INFO, nfc_debug_enabled) 1094 << StringPrintf("%s: flag formattable", __func__); 1095 1096 sCheckNdefWaitingForComplete = JNI_FALSE; 1097 sCheckNdefStatus = status; 1098 if (sCheckNdefStatus != NFA_STATUS_OK && 1099 sCheckNdefStatus != NFA_STATUS_TIMEOUT) 1100 sCheckNdefStatus = NFA_STATUS_FAILED; 1101 sCheckNdefCapable = false; // assume tag is NOT ndef capable 1102 if (sCheckNdefStatus == NFA_STATUS_OK) { 1103 // NDEF content is on the tag 1104 sCheckNdefMaxSize = maxSize; 1105 sCheckNdefCurrentSize = currentSize; 1106 sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY; 1107 sCheckNdefCapable = true; 1108 } else if (sCheckNdefStatus == NFA_STATUS_FAILED) { 1109 // no NDEF content on the tag 1110 sCheckNdefMaxSize = 0; 1111 sCheckNdefCurrentSize = 0; 1112 sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY; 1113 if ((flags & RW_NDEF_FL_UNKNOWN) == 0) // if stack understands the tag 1114 { 1115 if (flags & RW_NDEF_FL_SUPPORTED) // if tag is ndef capable 1116 sCheckNdefCapable = true; 1117 } 1118 } else { 1119 LOG(ERROR) << StringPrintf("%s: unknown status=0x%X", __func__, status); 1120 sCheckNdefMaxSize = 0; 1121 sCheckNdefCurrentSize = 0; 1122 sCheckNdefCardReadOnly = false; 1123 } 1124 sem_post(&sCheckNdefSem); 1125 } 1126 1127 /******************************************************************************* 1128 ** 1129 ** Function: nativeNfcTag_doCheckNdef 1130 ** 1131 ** Description: Does the tag contain a NDEF message? 1132 ** e: JVM environment. 1133 ** o: Java object. 1134 ** ndefInfo: NDEF info. 1135 ** 1136 ** Returns: Status code; 0 is success. 1137 ** 1138 *******************************************************************************/ 1139 static jint nativeNfcTag_doCheckNdef(JNIEnv* e, jobject o, jintArray ndefInfo) { 1140 tNFA_STATUS status = NFA_STATUS_FAILED; 1141 jint* ndef = NULL; 1142 1143 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 1144 1145 // special case for Kovio 1146 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) { 1147 DLOG_IF(INFO, nfc_debug_enabled) 1148 << StringPrintf("%s: Kovio tag, no NDEF", __func__); 1149 ndef = e->GetIntArrayElements(ndefInfo, 0); 1150 ndef[0] = 0; 1151 ndef[1] = NDEF_MODE_READ_ONLY; 1152 e->ReleaseIntArrayElements(ndefInfo, ndef, 0); 1153 return NFA_STATUS_FAILED; 1154 } else if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1155 nativeNfcTag_doReconnect(e, o); 1156 } 1157 1158 /* Create the write semaphore */ 1159 if (sem_init(&sCheckNdefSem, 0, 0) == -1) { 1160 LOG(ERROR) << StringPrintf( 1161 "%s: Check NDEF semaphore creation failed (errno=0x%08x)", __func__, 1162 errno); 1163 return JNI_FALSE; 1164 } 1165 1166 if (NfcTag::getInstance().getActivationState() != NfcTag::Active) { 1167 LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__); 1168 goto TheEnd; 1169 } 1170 1171 DLOG_IF(INFO, nfc_debug_enabled) 1172 << StringPrintf("%s: try NFA_RwDetectNDef", __func__); 1173 sCheckNdefWaitingForComplete = JNI_TRUE; 1174 1175 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1176 status = EXTNS_MfcCheckNDef(); 1177 } else { 1178 status = NFA_RwDetectNDef(); 1179 } 1180 1181 if (status != NFA_STATUS_OK) { 1182 LOG(ERROR) << StringPrintf("%s: NFA_RwDetectNDef failed, status = 0x%X", 1183 __func__, status); 1184 goto TheEnd; 1185 } 1186 1187 /* Wait for check NDEF completion status */ 1188 if (sem_wait(&sCheckNdefSem)) { 1189 LOG(ERROR) << StringPrintf( 1190 "%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __func__, 1191 errno); 1192 goto TheEnd; 1193 } 1194 1195 if (sCheckNdefStatus == NFA_STATUS_OK) { 1196 // stack found a NDEF message on the tag 1197 ndef = e->GetIntArrayElements(ndefInfo, 0); 1198 if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T) 1199 ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize(); 1200 else 1201 ndef[0] = sCheckNdefMaxSize; 1202 if (sCheckNdefCardReadOnly) 1203 ndef[1] = NDEF_MODE_READ_ONLY; 1204 else 1205 ndef[1] = NDEF_MODE_READ_WRITE; 1206 e->ReleaseIntArrayElements(ndefInfo, ndef, 0); 1207 status = NFA_STATUS_OK; 1208 } else if (sCheckNdefStatus == NFA_STATUS_FAILED) { 1209 // stack did not find a NDEF message on the tag; 1210 ndef = e->GetIntArrayElements(ndefInfo, 0); 1211 if (NfcTag::getInstance().getProtocol() == NFA_PROTOCOL_T1T) 1212 ndef[0] = NfcTag::getInstance().getT1tMaxMessageSize(); 1213 else 1214 ndef[0] = sCheckNdefMaxSize; 1215 if (sCheckNdefCardReadOnly) 1216 ndef[1] = NDEF_MODE_READ_ONLY; 1217 else 1218 ndef[1] = NDEF_MODE_READ_WRITE; 1219 e->ReleaseIntArrayElements(ndefInfo, ndef, 0); 1220 status = NFA_STATUS_FAILED; 1221 } else if ((sCheckNdefStatus == NFA_STATUS_TIMEOUT) && 1222 (NfcTag::getInstance().getProtocol() == NFC_PROTOCOL_ISO_DEP)) { 1223 pn544InteropStopPolling(); 1224 status = sCheckNdefStatus; 1225 } else { 1226 DLOG_IF(INFO, nfc_debug_enabled) 1227 << StringPrintf("%s: unknown status 0x%X", __func__, sCheckNdefStatus); 1228 status = sCheckNdefStatus; 1229 } 1230 1231 /* Reconnect Mifare Classic Tag for furture use */ 1232 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1233 nativeNfcTag_doReconnect(e, o); 1234 } 1235 1236 TheEnd: 1237 /* Destroy semaphore */ 1238 if (sem_destroy(&sCheckNdefSem)) { 1239 LOG(ERROR) << StringPrintf( 1240 "%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __func__, 1241 errno); 1242 } 1243 sCheckNdefWaitingForComplete = JNI_FALSE; 1244 DLOG_IF(INFO, nfc_debug_enabled) 1245 << StringPrintf("%s: exit; status=0x%X", __func__, status); 1246 return status; 1247 } 1248 1249 /******************************************************************************* 1250 ** 1251 ** Function: nativeNfcTag_resetPresenceCheck 1252 ** 1253 ** Description: Reset variables related to presence-check. 1254 ** 1255 ** Returns: None 1256 ** 1257 *******************************************************************************/ 1258 void nativeNfcTag_resetPresenceCheck() { sIsTagPresent = true; } 1259 1260 /******************************************************************************* 1261 ** 1262 ** Function: nativeNfcTag_doPresenceCheckResult 1263 ** 1264 ** Description: Receive the result of presence-check. 1265 ** status: Result of presence-check. 1266 ** 1267 ** Returns: None 1268 ** 1269 *******************************************************************************/ 1270 void nativeNfcTag_doPresenceCheckResult(tNFA_STATUS status) { 1271 SyncEventGuard guard(sPresenceCheckEvent); 1272 sIsTagPresent = status == NFA_STATUS_OK; 1273 sPresenceCheckEvent.notifyOne(); 1274 } 1275 1276 /******************************************************************************* 1277 ** 1278 ** Function: nativeNfcTag_doPresenceCheck 1279 ** 1280 ** Description: Check if the tag is in the RF field. 1281 ** e: JVM environment. 1282 ** o: Java object. 1283 ** 1284 ** Returns: True if tag is in RF field. 1285 ** 1286 *******************************************************************************/ 1287 static jboolean nativeNfcTag_doPresenceCheck(JNIEnv*, jobject) { 1288 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1289 tNFA_STATUS status = NFA_STATUS_OK; 1290 jboolean isPresent = JNI_FALSE; 1291 1292 // Special case for Kovio. The deactivation would have already occurred 1293 // but was ignored so that normal tag opertions could complete. Now we 1294 // want to process as if the deactivate just happened. 1295 if (sCurrentConnectedTargetProtocol == TARGET_TYPE_KOVIO_BARCODE) { 1296 DLOG_IF(INFO, nfc_debug_enabled) 1297 << StringPrintf("%s: Kovio, force deactivate handling", __func__); 1298 tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE}; 1299 { 1300 SyncEventGuard g(gDeactivatedEvent); 1301 gActivated = false; // guard this variable from multi-threaded access 1302 gDeactivatedEvent.notifyOne(); 1303 } 1304 1305 NfcTag::getInstance().setDeactivationState(deactivated); 1306 nativeNfcTag_resetPresenceCheck(); 1307 NfcTag::getInstance().connectionEventHandler(NFA_DEACTIVATED_EVT, NULL); 1308 nativeNfcTag_abortWaits(); 1309 NfcTag::getInstance().abort(); 1310 1311 return JNI_FALSE; 1312 } 1313 1314 if (nfcManager_isNfcActive() == false) { 1315 DLOG_IF(INFO, nfc_debug_enabled) 1316 << StringPrintf("%s: NFC is no longer active.", __func__); 1317 return JNI_FALSE; 1318 } 1319 1320 if (!sRfInterfaceMutex.tryLock()) { 1321 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 1322 "%s: tag is being reSelected assume it is present", __func__); 1323 return JNI_TRUE; 1324 } 1325 1326 sRfInterfaceMutex.unlock(); 1327 1328 if (NfcTag::getInstance().isActivated() == false) { 1329 DLOG_IF(INFO, nfc_debug_enabled) 1330 << StringPrintf("%s: tag already deactivated", __func__); 1331 return JNI_FALSE; 1332 } 1333 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1334 status = EXTNS_MfcPresenceCheck(); 1335 if (status == NFCSTATUS_SUCCESS) { 1336 return (NFCSTATUS_SUCCESS == EXTNS_GetPresenceCheckStatus()) ? JNI_TRUE 1337 : JNI_FALSE; 1338 } 1339 } 1340 1341 { 1342 SyncEventGuard guard(sPresenceCheckEvent); 1343 status = 1344 NFA_RwPresenceCheck(NfcTag::getInstance().getPresenceCheckAlgorithm()); 1345 if (status == NFA_STATUS_OK) { 1346 sPresenceCheckEvent.wait(); 1347 isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE; 1348 } 1349 } 1350 1351 if (isPresent == JNI_FALSE) 1352 DLOG_IF(INFO, nfc_debug_enabled) 1353 << StringPrintf("%s: tag absent", __func__); 1354 return isPresent; 1355 } 1356 1357 /******************************************************************************* 1358 ** 1359 ** Function: nativeNfcTag_doIsNdefFormatable 1360 ** 1361 ** Description: Can tag be formatted to store NDEF message? 1362 ** e: JVM environment. 1363 ** o: Java object. 1364 ** libNfcType: Type of tag. 1365 ** uidBytes: Tag's unique ID. 1366 ** pollBytes: Data from activation. 1367 ** actBytes: Data from activation. 1368 ** 1369 ** Returns: True if formattable. 1370 ** 1371 *******************************************************************************/ 1372 static jboolean nativeNfcTag_doIsNdefFormatable(JNIEnv* e, jobject o, 1373 jint /*libNfcType*/, jbyteArray, 1374 jbyteArray, jbyteArray) { 1375 jboolean isFormattable = JNI_FALSE; 1376 tNFC_PROTOCOL protocol = NfcTag::getInstance().getProtocol(); 1377 if (NFA_PROTOCOL_T1T == protocol || NFA_PROTOCOL_T5T == protocol || 1378 NFC_PROTOCOL_MIFARE == protocol) { 1379 isFormattable = JNI_TRUE; 1380 } else if (NFA_PROTOCOL_T3T == protocol) { 1381 isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE; 1382 } else if (NFA_PROTOCOL_T2T == protocol) { 1383 isFormattable = (NfcTag::getInstance().isMifareUltralight() | 1384 NfcTag::getInstance().isInfineonMyDMove() | 1385 NfcTag::getInstance().isKovioType2Tag()) 1386 ? JNI_TRUE 1387 : JNI_FALSE; 1388 } else if (NFA_PROTOCOL_ISO_DEP == protocol) { 1389 /** 1390 * Determines whether this is a formatable IsoDep tag - currectly only NXP 1391 * DESFire is supported. 1392 */ 1393 uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00}; 1394 1395 if (NfcTag::getInstance().isMifareDESFire()) { 1396 /* Identifies as DESfire, use get version cmd to be sure */ 1397 jbyteArray versionCmd = e->NewByteArray(5); 1398 e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd); 1399 jbyteArray respBytes = 1400 nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL); 1401 if (respBytes != NULL) { 1402 // Check whether the response matches a typical DESfire 1403 // response. 1404 // libNFC even does more advanced checking than we do 1405 // here, and will only format DESfire's with a certain 1406 // major/minor sw version and NXP as a manufacturer. 1407 // We don't want to do such checking here, to avoid 1408 // having to change code in multiple places. 1409 // A succesful (wrapped) DESFire getVersion command returns 1410 // 9 bytes, with byte 7 0x91 and byte 8 having status 1411 // code 0xAF (these values are fixed and well-known). 1412 int respLength = e->GetArrayLength(respBytes); 1413 uint8_t* resp = (uint8_t*)e->GetByteArrayElements(respBytes, NULL); 1414 if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF) { 1415 isFormattable = JNI_TRUE; 1416 } 1417 e->ReleaseByteArrayElements(respBytes, (jbyte*)resp, JNI_ABORT); 1418 } 1419 } 1420 } 1421 1422 DLOG_IF(INFO, nfc_debug_enabled) 1423 << StringPrintf("%s: is formattable=%u", __func__, isFormattable); 1424 return isFormattable; 1425 } 1426 1427 /******************************************************************************* 1428 ** 1429 ** Function: nativeNfcTag_doIsIsoDepNdefFormatable 1430 ** 1431 ** Description: Is ISO-DEP tag formattable? 1432 ** e: JVM environment. 1433 ** o: Java object. 1434 ** pollBytes: Data from activation. 1435 ** actBytes: Data from activation. 1436 ** 1437 ** Returns: True if formattable. 1438 ** 1439 *******************************************************************************/ 1440 static jboolean nativeNfcTag_doIsIsoDepNdefFormatable(JNIEnv* e, jobject o, 1441 jbyteArray pollBytes, 1442 jbyteArray actBytes) { 1443 uint8_t uidFake[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 1444 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1445 jbyteArray uidArray = e->NewByteArray(8); 1446 e->SetByteArrayRegion(uidArray, 0, 8, (jbyte*)uidFake); 1447 return nativeNfcTag_doIsNdefFormatable(e, o, 0, uidArray, pollBytes, 1448 actBytes); 1449 } 1450 1451 /******************************************************************************* 1452 ** 1453 ** Function: nativeNfcTag_makeMifareNdefFormat 1454 ** 1455 ** Description: Format a mifare classic tag so it can store NDEF message. 1456 ** e: JVM environment. 1457 ** o: Java object. 1458 ** key: Key to acces tag. 1459 ** keySize: size of Key. 1460 ** 1461 ** Returns: True if ok. 1462 ** 1463 *******************************************************************************/ 1464 static jboolean nativeNfcTag_makeMifareNdefFormat(JNIEnv* e, jobject o, 1465 uint8_t* key, 1466 uint32_t keySize) { 1467 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 1468 tNFA_STATUS status = NFA_STATUS_OK; 1469 1470 status = nativeNfcTag_doReconnect(e, o); 1471 if (status != NFA_STATUS_OK) { 1472 DLOG_IF(INFO, nfc_debug_enabled) 1473 << StringPrintf("%s: reconnect error, status=%u", __func__, status); 1474 return JNI_FALSE; 1475 } 1476 1477 sem_init(&sFormatSem, 0, 0); 1478 sFormatOk = false; 1479 1480 status = EXTNS_MfcFormatTag(key, keySize); 1481 1482 if (status == NFA_STATUS_OK) { 1483 DLOG_IF(INFO, nfc_debug_enabled) 1484 << StringPrintf("%s: wait for completion", __func__); 1485 sem_wait(&sFormatSem); 1486 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED; 1487 } else { 1488 LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status); 1489 } 1490 1491 sem_destroy(&sFormatSem); 1492 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); 1493 return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE; 1494 } 1495 1496 /******************************************************************************* 1497 ** 1498 ** Function: nativeNfcTag_doNdefFormat 1499 ** 1500 ** Description: Format a tag so it can store NDEF message. 1501 ** e: JVM environment. 1502 ** o: Java object. 1503 ** key: Not used. 1504 ** 1505 ** Returns: True if ok. 1506 ** 1507 *******************************************************************************/ 1508 static jboolean nativeNfcTag_doNdefFormat(JNIEnv* e, jobject o, jbyteArray) { 1509 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", __func__); 1510 tNFA_STATUS status = NFA_STATUS_OK; 1511 1512 // Do not try to format if tag is already deactivated. 1513 if (NfcTag::getInstance().isActivated() == false) { 1514 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 1515 "%s: tag already deactivated(no need to format)", __func__); 1516 return JNI_FALSE; 1517 } 1518 1519 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1520 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1521 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; 1522 jboolean result; 1523 1524 result = 1525 nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key1, sizeof(mfc_key1)); 1526 if (result == JNI_FALSE) { 1527 result = 1528 nativeNfcTag_makeMifareNdefFormat(e, o, mfc_key2, sizeof(mfc_key2)); 1529 } 1530 return result; 1531 } 1532 1533 sem_init(&sFormatSem, 0, 0); 1534 sFormatOk = false; 1535 status = NFA_RwFormatTag(); 1536 if (status == NFA_STATUS_OK) { 1537 DLOG_IF(INFO, nfc_debug_enabled) 1538 << StringPrintf("%s: wait for completion", __func__); 1539 sem_wait(&sFormatSem); 1540 status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED; 1541 } else 1542 LOG(ERROR) << StringPrintf("%s: error status=%u", __func__, status); 1543 sem_destroy(&sFormatSem); 1544 1545 if (sCurrentConnectedTargetProtocol == NFA_PROTOCOL_ISO_DEP) { 1546 int retCode = NFCSTATUS_SUCCESS; 1547 retCode = nativeNfcTag_doReconnect(e, o); 1548 } 1549 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", __func__); 1550 return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE; 1551 } 1552 1553 /******************************************************************************* 1554 ** 1555 ** Function: nativeNfcTag_doMakeReadonlyResult 1556 ** 1557 ** Description: Receive the result of making a tag read-only. Called by the 1558 ** NFA_SET_TAG_RO_EVT. 1559 ** status: Status of the operation. 1560 ** 1561 ** Returns: None 1562 ** 1563 *******************************************************************************/ 1564 void nativeNfcTag_doMakeReadonlyResult(tNFA_STATUS status) { 1565 if (sMakeReadonlyWaitingForComplete != JNI_FALSE) { 1566 sMakeReadonlyWaitingForComplete = JNI_FALSE; 1567 sMakeReadonlyStatus = status; 1568 1569 sem_post(&sMakeReadonlySem); 1570 } 1571 } 1572 1573 /******************************************************************************* 1574 ** 1575 ** Function: nativeNfcTag_makeMifareReadonly 1576 ** 1577 ** Description: Make the mifare classic tag read-only. 1578 ** e: JVM environment. 1579 ** o: Java object. 1580 ** key: Key to access the tag. 1581 ** keySize: size of Key. 1582 ** 1583 ** Returns: True if ok. 1584 ** 1585 *******************************************************************************/ 1586 static jboolean nativeNfcTag_makeMifareReadonly(JNIEnv* e, jobject o, 1587 uint8_t* key, int32_t keySize) { 1588 jboolean result = JNI_FALSE; 1589 tNFA_STATUS status = NFA_STATUS_OK; 1590 1591 sMakeReadonlyStatus = NFA_STATUS_FAILED; 1592 1593 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1594 1595 /* Create the make_readonly semaphore */ 1596 if (sem_init(&sMakeReadonlySem, 0, 0) == -1) { 1597 LOG(ERROR) << StringPrintf( 1598 "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__, 1599 errno); 1600 return JNI_FALSE; 1601 } 1602 1603 sMakeReadonlyWaitingForComplete = JNI_TRUE; 1604 1605 status = nativeNfcTag_doReconnect(e, o); 1606 if (status != NFA_STATUS_OK) { 1607 goto TheEnd; 1608 } 1609 1610 status = EXTNS_MfcSetReadOnly(key, keySize); 1611 if (status != NFA_STATUS_OK) { 1612 goto TheEnd; 1613 } 1614 sem_wait(&sMakeReadonlySem); 1615 1616 if (sMakeReadonlyStatus == NFA_STATUS_OK) { 1617 result = JNI_TRUE; 1618 } 1619 1620 TheEnd: 1621 /* Destroy semaphore */ 1622 if (sem_destroy(&sMakeReadonlySem)) { 1623 LOG(ERROR) << StringPrintf( 1624 "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__, 1625 errno); 1626 } 1627 sMakeReadonlyWaitingForComplete = JNI_FALSE; 1628 return result; 1629 } 1630 1631 /******************************************************************************* 1632 ** 1633 ** Function: nativeNfcTag_doMakeReadonly 1634 ** 1635 ** Description: Make the tag read-only. 1636 ** e: JVM environment. 1637 ** o: Java object. 1638 ** key: Key to access the tag. 1639 ** 1640 ** Returns: True if ok. 1641 ** 1642 *******************************************************************************/ 1643 static jboolean nativeNfcTag_doMakeReadonly(JNIEnv* e, jobject o, jbyteArray) { 1644 jboolean result = JNI_FALSE; 1645 tNFA_STATUS status; 1646 1647 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1648 1649 if (sCurrentConnectedTargetProtocol == NFC_PROTOCOL_MIFARE) { 1650 static uint8_t mfc_key1[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; 1651 static uint8_t mfc_key2[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; 1652 result = nativeNfcTag_makeMifareReadonly(e, o, mfc_key1, sizeof(mfc_key1)); 1653 if (result == JNI_FALSE) { 1654 result = 1655 nativeNfcTag_makeMifareReadonly(e, o, mfc_key2, sizeof(mfc_key2)); 1656 } 1657 return result; 1658 } 1659 1660 /* Create the make_readonly semaphore */ 1661 if (sem_init(&sMakeReadonlySem, 0, 0) == -1) { 1662 LOG(ERROR) << StringPrintf( 1663 "%s: Make readonly semaphore creation failed (errno=0x%08x)", __func__, 1664 errno); 1665 return JNI_FALSE; 1666 } 1667 1668 sMakeReadonlyWaitingForComplete = JNI_TRUE; 1669 1670 // Hard-lock the tag (cannot be reverted) 1671 status = NFA_RwSetTagReadOnly(TRUE); 1672 if (status == NFA_STATUS_REJECTED) { 1673 status = NFA_RwSetTagReadOnly(FALSE); // try soft lock 1674 if (status != NFA_STATUS_OK) { 1675 LOG(ERROR) << StringPrintf("%s: fail soft lock, status=%d", __func__, 1676 status); 1677 goto TheEnd; 1678 } 1679 } else if (status != NFA_STATUS_OK) { 1680 LOG(ERROR) << StringPrintf("%s: fail hard lock, status=%d", __func__, 1681 status); 1682 goto TheEnd; 1683 } 1684 1685 /* Wait for check NDEF completion status */ 1686 if (sem_wait(&sMakeReadonlySem)) { 1687 LOG(ERROR) << StringPrintf( 1688 "%s: Failed to wait for make_readonly semaphore (errno=0x%08x)", 1689 __func__, errno); 1690 goto TheEnd; 1691 } 1692 1693 if (sMakeReadonlyStatus == NFA_STATUS_OK) { 1694 result = JNI_TRUE; 1695 } 1696 1697 TheEnd: 1698 /* Destroy semaphore */ 1699 if (sem_destroy(&sMakeReadonlySem)) { 1700 LOG(ERROR) << StringPrintf( 1701 "%s: Failed to destroy read_only semaphore (errno=0x%08x)", __func__, 1702 errno); 1703 } 1704 sMakeReadonlyWaitingForComplete = JNI_FALSE; 1705 return result; 1706 } 1707 1708 /******************************************************************************* 1709 ** 1710 ** Function: nativeNfcTag_registerNdefTypeHandler 1711 ** 1712 ** Description: Register a callback to receive NDEF message from the tag 1713 ** from the NFA_NDEF_DATA_EVT. 1714 ** 1715 ** Returns: None 1716 ** 1717 *******************************************************************************/ 1718 // register a callback to receive NDEF message from the tag 1719 // from the NFA_NDEF_DATA_EVT; 1720 void nativeNfcTag_registerNdefTypeHandler() { 1721 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1722 sNdefTypeHandlerHandle = NFA_HANDLE_INVALID; 1723 NFA_RegisterNDefTypeHandler(TRUE, NFA_TNF_DEFAULT, (uint8_t*)"", 0, 1724 ndefHandlerCallback); 1725 EXTNS_MfcRegisterNDefTypeHandler(ndefHandlerCallback); 1726 } 1727 1728 /******************************************************************************* 1729 ** 1730 ** Function: nativeNfcTag_deregisterNdefTypeHandler 1731 ** 1732 ** Description: No longer need to receive NDEF message from the tag. 1733 ** 1734 ** Returns: None 1735 ** 1736 *******************************************************************************/ 1737 void nativeNfcTag_deregisterNdefTypeHandler() { 1738 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1739 NFA_DeregisterNDefTypeHandler(sNdefTypeHandlerHandle); 1740 sNdefTypeHandlerHandle = NFA_HANDLE_INVALID; 1741 } 1742 1743 /******************************************************************************* 1744 ** 1745 ** Function: nativeNfcTag_acquireRfInterfaceMutexLock 1746 ** 1747 ** Description: acquire sRfInterfaceMutex 1748 ** 1749 ** Returns: None 1750 ** 1751 *******************************************************************************/ 1752 void nativeNfcTag_acquireRfInterfaceMutexLock() { 1753 DLOG_IF(INFO, nfc_debug_enabled) 1754 << StringPrintf("%s: try to acquire lock", __func__); 1755 sRfInterfaceMutex.lock(); 1756 DLOG_IF(INFO, nfc_debug_enabled) 1757 << StringPrintf("%s: sRfInterfaceMutex lock", __func__); 1758 } 1759 1760 /******************************************************************************* 1761 ** 1762 ** Function: nativeNfcTag_releaseRfInterfaceMutexLock 1763 ** 1764 ** Description: release the sRfInterfaceMutex 1765 ** 1766 ** Returns: None 1767 ** 1768 *******************************************************************************/ 1769 void nativeNfcTag_releaseRfInterfaceMutexLock() { 1770 sRfInterfaceMutex.unlock(); 1771 DLOG_IF(INFO, nfc_debug_enabled) 1772 << StringPrintf("%s: sRfInterfaceMutex unlock", __func__); 1773 } 1774 1775 /***************************************************************************** 1776 ** 1777 ** JNI functions for Android 4.0.3 1778 ** 1779 *****************************************************************************/ 1780 static JNINativeMethod gMethods[] = { 1781 {"doConnect", "(I)I", (void*)nativeNfcTag_doConnect}, 1782 {"doDisconnect", "()Z", (void*)nativeNfcTag_doDisconnect}, 1783 {"doReconnect", "()I", (void*)nativeNfcTag_doReconnect}, 1784 {"doHandleReconnect", "(I)I", (void*)nativeNfcTag_doHandleReconnect}, 1785 {"doTransceive", "([BZ[I)[B", (void*)nativeNfcTag_doTransceive}, 1786 {"doGetNdefType", "(II)I", (void*)nativeNfcTag_doGetNdefType}, 1787 {"doCheckNdef", "([I)I", (void*)nativeNfcTag_doCheckNdef}, 1788 {"doRead", "()[B", (void*)nativeNfcTag_doRead}, 1789 {"doWrite", "([B)Z", (void*)nativeNfcTag_doWrite}, 1790 {"doPresenceCheck", "()Z", (void*)nativeNfcTag_doPresenceCheck}, 1791 {"doIsIsoDepNdefFormatable", "([B[B)Z", 1792 (void*)nativeNfcTag_doIsIsoDepNdefFormatable}, 1793 {"doNdefFormat", "([B)Z", (void*)nativeNfcTag_doNdefFormat}, 1794 {"doMakeReadonly", "([B)Z", (void*)nativeNfcTag_doMakeReadonly}, 1795 }; 1796 1797 /******************************************************************************* 1798 ** 1799 ** Function: register_com_android_nfc_NativeNfcTag 1800 ** 1801 ** Description: Regisgter JNI functions with Java Virtual Machine. 1802 ** e: Environment of JVM. 1803 ** 1804 ** Returns: Status of registration. 1805 ** 1806 *******************************************************************************/ 1807 int register_com_android_nfc_NativeNfcTag(JNIEnv* e) { 1808 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", __func__); 1809 return jniRegisterNativeMethods(e, gNativeNfcTagClassName, gMethods, 1810 NELEM(gMethods)); 1811 } 1812 1813 } /* namespace android */ 1814