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