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