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