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