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