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