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 /* 18 * Tag-reading, tag-writing operations. 19 */ 20 #include "NfcTag.h" 21 22 #include <android-base/stringprintf.h> 23 #include <base/logging.h> 24 #include <nativehelper/ScopedLocalRef.h> 25 #include <nativehelper/ScopedPrimitiveArray.h> 26 27 #include "JavaClassConstants.h" 28 #include "nfc_brcm_defs.h" 29 #include "nfc_config.h" 30 #include "phNxpExtns.h" 31 #include "rw_int.h" 32 33 using android::base::StringPrintf; 34 35 extern bool nfc_debug_enabled; 36 37 /******************************************************************************* 38 ** 39 ** Function: NfcTag 40 ** 41 ** Description: Initialize member variables. 42 ** 43 ** Returns: None 44 ** 45 *******************************************************************************/ 46 NfcTag::NfcTag() 47 : mNumTechList(0), 48 mTechnologyTimeoutsTable(MAX_NUM_TECHNOLOGY), 49 mNativeData(NULL), 50 mIsActivated(false), 51 mActivationState(Idle), 52 mProtocol(NFC_PROTOCOL_UNKNOWN), 53 mtT1tMaxMessageSize(0), 54 mReadCompletedStatus(NFA_STATUS_OK), 55 mLastKovioUidLen(0), 56 mNdefDetectionTimedOut(false), 57 mIsDynamicTagId(false), 58 mPresenceCheckAlgorithm(NFA_RW_PRES_CHK_DEFAULT), 59 mIsFelicaLite(false) { 60 memset(mTechList, 0, sizeof(mTechList)); 61 memset(mTechHandles, 0, sizeof(mTechHandles)); 62 memset(mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes)); 63 memset(mTechParams, 0, sizeof(mTechParams)); 64 memset(mLastKovioUid, 0, NFC_KOVIO_MAX_LEN); 65 } 66 67 /******************************************************************************* 68 ** 69 ** Function: getInstance 70 ** 71 ** Description: Get a reference to the singleton NfcTag object. 72 ** 73 ** Returns: Reference to NfcTag object. 74 ** 75 *******************************************************************************/ 76 NfcTag& NfcTag::getInstance() { 77 static NfcTag tag; 78 return tag; 79 } 80 81 /******************************************************************************* 82 ** 83 ** Function: initialize 84 ** 85 ** Description: Reset member variables. 86 ** native: Native data. 87 ** 88 ** Returns: None 89 ** 90 *******************************************************************************/ 91 void NfcTag::initialize(nfc_jni_native_data* native) { 92 mNativeData = native; 93 mIsActivated = false; 94 mActivationState = Idle; 95 mProtocol = NFC_PROTOCOL_UNKNOWN; 96 mNumTechList = 0; 97 mtT1tMaxMessageSize = 0; 98 mReadCompletedStatus = NFA_STATUS_OK; 99 resetTechnologies(); 100 if (NfcConfig::hasKey(NAME_PRESENCE_CHECK_ALGORITHM)) 101 mPresenceCheckAlgorithm = 102 NfcConfig::getUnsigned(NAME_PRESENCE_CHECK_ALGORITHM); 103 } 104 105 /******************************************************************************* 106 ** 107 ** Function: abort 108 ** 109 ** Description: Unblock all operations. 110 ** 111 ** Returns: None 112 ** 113 *******************************************************************************/ 114 void NfcTag::abort() { 115 SyncEventGuard g(mReadCompleteEvent); 116 mReadCompleteEvent.notifyOne(); 117 } 118 119 /******************************************************************************* 120 ** 121 ** Function: getActivationState 122 ** 123 ** Description: What is the current state: Idle, Sleep, or Activated. 124 ** 125 ** Returns: Idle, Sleep, or Activated. 126 ** 127 *******************************************************************************/ 128 NfcTag::ActivationState NfcTag::getActivationState() { 129 return mActivationState; 130 } 131 132 /******************************************************************************* 133 ** 134 ** Function: setDeactivationState 135 ** 136 ** Description: Set the current state: Idle or Sleep. 137 ** deactivated: state of deactivation. 138 ** 139 ** Returns: None. 140 ** 141 *******************************************************************************/ 142 void NfcTag::setDeactivationState(tNFA_DEACTIVATED& deactivated) { 143 static const char fn[] = "NfcTag::setDeactivationState"; 144 mActivationState = Idle; 145 mNdefDetectionTimedOut = false; 146 if (deactivated.type == NFA_DEACTIVATE_TYPE_SLEEP) mActivationState = Sleep; 147 DLOG_IF(INFO, nfc_debug_enabled) 148 << StringPrintf("%s: state=%u", fn, mActivationState); 149 } 150 151 /******************************************************************************* 152 ** 153 ** Function: setActivationState 154 ** 155 ** Description: Set the current state to Active. 156 ** 157 ** Returns: None. 158 ** 159 *******************************************************************************/ 160 void NfcTag::setActivationState() { 161 static const char fn[] = "NfcTag::setActivationState"; 162 mNdefDetectionTimedOut = false; 163 mActivationState = Active; 164 DLOG_IF(INFO, nfc_debug_enabled) 165 << StringPrintf("%s: state=%u", fn, mActivationState); 166 } 167 168 /******************************************************************************* 169 ** 170 ** Function: isActivated 171 ** 172 ** Description: Is tag activated? 173 ** 174 ** Returns: True if tag is activated. 175 ** 176 *******************************************************************************/ 177 bool NfcTag::isActivated() { return mIsActivated; } 178 179 /******************************************************************************* 180 ** 181 ** Function: getProtocol 182 ** 183 ** Description: Get the protocol of the current tag. 184 ** 185 ** Returns: Protocol number. 186 ** 187 *******************************************************************************/ 188 tNFC_PROTOCOL NfcTag::getProtocol() { return mProtocol; } 189 190 /******************************************************************************* 191 ** 192 ** Function TimeDiff 193 ** 194 ** Description Computes time difference in milliseconds. 195 ** 196 ** Returns Time difference in milliseconds 197 ** 198 *******************************************************************************/ 199 uint32_t TimeDiff(timespec start, timespec end) { 200 timespec temp; 201 if ((end.tv_nsec - start.tv_nsec) < 0) { 202 temp.tv_sec = end.tv_sec - start.tv_sec - 1; 203 temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; 204 } else { 205 temp.tv_sec = end.tv_sec - start.tv_sec; 206 temp.tv_nsec = end.tv_nsec - start.tv_nsec; 207 } 208 209 return (temp.tv_sec * 1000) + (temp.tv_nsec / 1000000); 210 } 211 212 /******************************************************************************* 213 ** 214 ** Function: IsSameKovio 215 ** 216 ** Description: Checks if tag activate is the same (UID) Kovio tag 217 *previously 218 ** activated. This is needed due to a problem with some Kovio 219 ** tags re-activating multiple times. 220 ** activationData: data from activation. 221 ** 222 ** Returns: true if the activation is from the same tag previously 223 ** activated, false otherwise 224 ** 225 *******************************************************************************/ 226 bool NfcTag::IsSameKovio(tNFA_ACTIVATED& activationData) { 227 static const char fn[] = "NfcTag::IsSameKovio"; 228 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); 229 tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf; 230 231 if (rfDetail.protocol != NFC_PROTOCOL_KOVIO) return false; 232 233 memcpy(&(mTechParams[0]), &(rfDetail.rf_tech_param), 234 sizeof(rfDetail.rf_tech_param)); 235 if (mTechParams[0].mode != NFC_DISCOVERY_TYPE_POLL_KOVIO) return false; 236 237 struct timespec now; 238 clock_gettime(CLOCK_REALTIME, &now); 239 240 bool rVal = false; 241 if (mTechParams[0].param.pk.uid_len == mLastKovioUidLen) { 242 if (memcmp(mLastKovioUid, &mTechParams[0].param.pk.uid, 243 mTechParams[0].param.pk.uid_len) == 0) { 244 // same tag 245 if (TimeDiff(mLastKovioTime, now) < 500) { 246 // same tag within 500 ms, ignore activation 247 rVal = true; 248 } 249 } 250 } 251 252 // save Kovio tag info 253 if (!rVal) { 254 if ((mLastKovioUidLen = mTechParams[0].param.pk.uid_len) > 255 NFC_KOVIO_MAX_LEN) 256 mLastKovioUidLen = NFC_KOVIO_MAX_LEN; 257 memcpy(mLastKovioUid, mTechParams[0].param.pk.uid, mLastKovioUidLen); 258 } 259 mLastKovioTime = now; 260 DLOG_IF(INFO, nfc_debug_enabled) 261 << StringPrintf("%s: exit, is same Kovio=%d", fn, rVal); 262 return rVal; 263 } 264 265 /******************************************************************************* 266 ** 267 ** Function: discoverTechnologies 268 ** 269 ** Description: Discover the technologies that NFC service needs by 270 *interpreting 271 ** the data structures from the stack. 272 ** activationData: data from activation. 273 ** 274 ** Returns: None 275 ** 276 *******************************************************************************/ 277 void NfcTag::discoverTechnologies(tNFA_ACTIVATED& activationData) { 278 static const char fn[] = "NfcTag::discoverTechnologies (activation)"; 279 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); 280 tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf; 281 282 mNumTechList = 0; 283 mTechHandles[mNumTechList] = rfDetail.rf_disc_id; 284 mTechLibNfcTypes[mNumTechList] = rfDetail.protocol; 285 286 // save the stack's data structure for interpretation later 287 memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), 288 sizeof(rfDetail.rf_tech_param)); 289 290 if (NFC_PROTOCOL_T1T == rfDetail.protocol) { 291 mTechList[mNumTechList] = 292 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 293 } else if (NFC_PROTOCOL_T2T == rfDetail.protocol) { 294 mTechList[mNumTechList] = 295 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 296 // could be MifFare UL or Classic or Kovio 297 { 298 // need to look at first byte of uid to find Manufacture Byte 299 tNFC_RF_TECH_PARAMS tech_params; 300 memcpy(&tech_params, &(rfDetail.rf_tech_param), 301 sizeof(rfDetail.rf_tech_param)); 302 303 if ((tech_params.param.pa.nfcid1[0] == 0x04 && 304 rfDetail.rf_tech_param.param.pa.sel_rsp == 0) || 305 rfDetail.rf_tech_param.param.pa.sel_rsp == 0x18 || 306 rfDetail.rf_tech_param.param.pa.sel_rsp == 0x08) { 307 if (rfDetail.rf_tech_param.param.pa.sel_rsp == 0) { 308 mNumTechList++; 309 mTechHandles[mNumTechList] = rfDetail.rf_disc_id; 310 mTechLibNfcTypes[mNumTechList] = rfDetail.protocol; 311 // save the stack's data structure for interpretation later 312 memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), 313 sizeof(rfDetail.rf_tech_param)); 314 mTechList[mNumTechList] = 315 TARGET_TYPE_MIFARE_UL; // is TagTechnology.MIFARE_ULTRALIGHT by 316 // Java API 317 } 318 } 319 } 320 } else if (NFC_PROTOCOL_T3T == rfDetail.protocol) { 321 uint8_t xx = 0; 322 323 mTechList[mNumTechList] = TARGET_TYPE_FELICA; 324 325 // see if it is Felica Lite. 326 while (xx < activationData.params.t3t.num_system_codes) { 327 if (activationData.params.t3t.p_system_codes[xx++] == 328 T3T_SYSTEM_CODE_FELICA_LITE) { 329 mIsFelicaLite = true; 330 break; 331 } 332 } 333 } else if (NFC_PROTOCOL_ISO_DEP == rfDetail.protocol) { 334 // type-4 tag uses technology ISO-DEP and technology A or B 335 mTechList[mNumTechList] = 336 TARGET_TYPE_ISO14443_4; // is TagTechnology.ISO_DEP by Java API 337 if ((rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) || 338 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) || 339 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A) || 340 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE)) { 341 mNumTechList++; 342 mTechHandles[mNumTechList] = rfDetail.rf_disc_id; 343 mTechLibNfcTypes[mNumTechList] = rfDetail.protocol; 344 mTechList[mNumTechList] = 345 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 346 // save the stack's data structure for interpretation later 347 memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), 348 sizeof(rfDetail.rf_tech_param)); 349 } else if ((rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B) || 350 (rfDetail.rf_tech_param.mode == 351 NFC_DISCOVERY_TYPE_POLL_B_PRIME) || 352 (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B) || 353 (rfDetail.rf_tech_param.mode == 354 NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)) { 355 mNumTechList++; 356 mTechHandles[mNumTechList] = rfDetail.rf_disc_id; 357 mTechLibNfcTypes[mNumTechList] = rfDetail.protocol; 358 mTechList[mNumTechList] = 359 TARGET_TYPE_ISO14443_3B; // is TagTechnology.NFC_B by Java API 360 // save the stack's data structure for interpretation later 361 memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), 362 sizeof(rfDetail.rf_tech_param)); 363 } 364 } else if (NFC_PROTOCOL_T5T == rfDetail.protocol) { 365 // is TagTechnology.NFC_V by Java API 366 mTechList[mNumTechList] = TARGET_TYPE_V; 367 } else if (NFC_PROTOCOL_KOVIO == rfDetail.protocol) { 368 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Kovio", fn); 369 mTechList[mNumTechList] = TARGET_TYPE_KOVIO_BARCODE; 370 } else if (NFC_PROTOCOL_MIFARE == rfDetail.protocol) { 371 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Mifare Classic", fn); 372 EXTNS_MfcInit(activationData); 373 mTechList[mNumTechList] = 374 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 375 mNumTechList++; 376 mTechHandles[mNumTechList] = rfDetail.rf_disc_id; 377 mTechLibNfcTypes[mNumTechList] = rfDetail.protocol; 378 // save the stack's data structure for interpretation later 379 memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param), 380 sizeof(rfDetail.rf_tech_param)); 381 mTechList[mNumTechList] = 382 TARGET_TYPE_MIFARE_CLASSIC; // is TagTechnology.MIFARE_CLASSIC by Java 383 // API 384 } else { 385 LOG(ERROR) << StringPrintf("%s: unknown protocol ????", fn); 386 mTechList[mNumTechList] = TARGET_TYPE_UNKNOWN; 387 } 388 389 mNumTechList++; 390 for (int i = 0; i < mNumTechList; i++) { 391 DLOG_IF(INFO, nfc_debug_enabled) 392 << StringPrintf("%s: index=%d; tech=%d; handle=%d; nfc type=%d", fn, i, 393 mTechList[i], mTechHandles[i], mTechLibNfcTypes[i]); 394 } 395 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); 396 } 397 398 /******************************************************************************* 399 ** 400 ** Function: discoverTechnologies 401 ** 402 ** Description: Discover the technologies that NFC service needs by 403 *interpreting 404 ** the data structures from the stack. 405 ** discoveryData: data from discovery events(s). 406 ** 407 ** Returns: None 408 ** 409 *******************************************************************************/ 410 void NfcTag::discoverTechnologies(tNFA_DISC_RESULT& discoveryData) { 411 static const char fn[] = "NfcTag::discoverTechnologies (discovery)"; 412 tNFC_RESULT_DEVT& discovery_ntf = discoveryData.discovery_ntf; 413 414 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 415 "%s: enter: rf disc. id=%u; protocol=%u, mNumTechList=%u", fn, 416 discovery_ntf.rf_disc_id, discovery_ntf.protocol, mNumTechList); 417 if (mNumTechList >= MAX_NUM_TECHNOLOGY) { 418 LOG(ERROR) << StringPrintf("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY); 419 goto TheEnd; 420 } 421 mTechHandles[mNumTechList] = discovery_ntf.rf_disc_id; 422 mTechLibNfcTypes[mNumTechList] = discovery_ntf.protocol; 423 424 // save the stack's data structure for interpretation later 425 memcpy(&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), 426 sizeof(discovery_ntf.rf_tech_param)); 427 428 if (NFC_PROTOCOL_T1T == discovery_ntf.protocol) { 429 mTechList[mNumTechList] = 430 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 431 } else if (NFC_PROTOCOL_T2T == discovery_ntf.protocol) { 432 mTechList[mNumTechList] = 433 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 434 // type-2 tags are identical to Mifare Ultralight, so Ultralight is also 435 // discovered 436 if ((discovery_ntf.rf_tech_param.param.pa.sel_rsp == 0) && 437 (mNumTechList < (MAX_NUM_TECHNOLOGY - 1))) { 438 // Mifare Ultralight 439 mNumTechList++; 440 mTechHandles[mNumTechList] = discovery_ntf.rf_disc_id; 441 mTechLibNfcTypes[mNumTechList] = discovery_ntf.protocol; 442 mTechList[mNumTechList] = 443 TARGET_TYPE_MIFARE_UL; // is TagTechnology.MIFARE_ULTRALIGHT by Java 444 // API 445 } 446 447 // save the stack's data structure for interpretation later 448 memcpy(&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), 449 sizeof(discovery_ntf.rf_tech_param)); 450 } else if (NFC_PROTOCOL_T3T == discovery_ntf.protocol) { 451 mTechList[mNumTechList] = TARGET_TYPE_FELICA; 452 } else if (NFC_PROTOCOL_ISO_DEP == discovery_ntf.protocol) { 453 // type-4 tag uses technology ISO-DEP and technology A or B 454 mTechList[mNumTechList] = 455 TARGET_TYPE_ISO14443_4; // is TagTechnology.ISO_DEP by Java API 456 if ((discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) || 457 (discovery_ntf.rf_tech_param.mode == 458 NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) || 459 (discovery_ntf.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A) || 460 (discovery_ntf.rf_tech_param.mode == 461 NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE)) { 462 if (mNumTechList < (MAX_NUM_TECHNOLOGY - 1)) { 463 mNumTechList++; 464 mTechHandles[mNumTechList] = discovery_ntf.rf_disc_id; 465 mTechLibNfcTypes[mNumTechList] = discovery_ntf.protocol; 466 mTechList[mNumTechList] = 467 TARGET_TYPE_ISO14443_3A; // is TagTechnology.NFC_A by Java API 468 // save the stack's data structure for interpretation later 469 memcpy(&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), 470 sizeof(discovery_ntf.rf_tech_param)); 471 } 472 } else if ((discovery_ntf.rf_tech_param.mode == 473 NFC_DISCOVERY_TYPE_POLL_B) || 474 (discovery_ntf.rf_tech_param.mode == 475 NFC_DISCOVERY_TYPE_POLL_B_PRIME) || 476 (discovery_ntf.rf_tech_param.mode == 477 NFC_DISCOVERY_TYPE_LISTEN_B) || 478 (discovery_ntf.rf_tech_param.mode == 479 NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)) { 480 if (mNumTechList < (MAX_NUM_TECHNOLOGY - 1)) { 481 mNumTechList++; 482 mTechHandles[mNumTechList] = discovery_ntf.rf_disc_id; 483 mTechLibNfcTypes[mNumTechList] = discovery_ntf.protocol; 484 mTechList[mNumTechList] = 485 TARGET_TYPE_ISO14443_3B; // is TagTechnology.NFC_B by Java API 486 // save the stack's data structure for interpretation later 487 memcpy(&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), 488 sizeof(discovery_ntf.rf_tech_param)); 489 } 490 } 491 } else if (NFC_PROTOCOL_T5T == discovery_ntf.protocol) { 492 // is TagTechnology.NFC_V by Java API 493 mTechList[mNumTechList] = TARGET_TYPE_V; 494 } else if (NFC_PROTOCOL_MIFARE == discovery_ntf.protocol) { 495 mTechList[mNumTechList] = TARGET_TYPE_MIFARE_CLASSIC; 496 if (mNumTechList < (MAX_NUM_TECHNOLOGY - 1)) { 497 mNumTechList++; 498 mTechHandles[mNumTechList] = discovery_ntf.rf_disc_id; 499 mTechLibNfcTypes[mNumTechList] = discovery_ntf.protocol; 500 mTechList[mNumTechList] = TARGET_TYPE_ISO14443_3A; 501 // save the stack's data structure for interpretation later 502 memcpy(&(mTechParams[mNumTechList]), &(discovery_ntf.rf_tech_param), 503 sizeof(discovery_ntf.rf_tech_param)); 504 } 505 } else { 506 LOG(ERROR) << StringPrintf("%s: unknown protocol ????", fn); 507 mTechList[mNumTechList] = TARGET_TYPE_UNKNOWN; 508 } 509 510 mNumTechList++; 511 if (discovery_ntf.more != NCI_DISCOVER_NTF_MORE) { 512 for (int i = 0; i < mNumTechList; i++) { 513 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 514 "%s: index=%d; tech=%d; handle=%d; nfc type=%d", fn, i, mTechList[i], 515 mTechHandles[i], mTechLibNfcTypes[i]); 516 } 517 } 518 519 TheEnd: 520 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); 521 } 522 523 /******************************************************************************* 524 ** 525 ** Function: createNativeNfcTag 526 ** 527 ** Description: Create a brand new Java NativeNfcTag object; 528 ** fill the objects's member variables with data; 529 ** notify NFC service; 530 ** activationData: data from activation. 531 ** 532 ** Returns: None 533 ** 534 *******************************************************************************/ 535 void NfcTag::createNativeNfcTag(tNFA_ACTIVATED& activationData) { 536 static const char fn[] = "NfcTag::createNativeNfcTag"; 537 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn); 538 539 JNIEnv* e = NULL; 540 ScopedAttach attach(mNativeData->vm, &e); 541 if (e == NULL) { 542 LOG(ERROR) << StringPrintf("%s: jni env is null", fn); 543 return; 544 } 545 546 ScopedLocalRef<jclass> tag_cls(e, 547 e->GetObjectClass(mNativeData->cached_NfcTag)); 548 if (e->ExceptionCheck()) { 549 e->ExceptionClear(); 550 LOG(ERROR) << StringPrintf("%s: failed to get class", fn); 551 return; 552 } 553 554 // create a new Java NativeNfcTag object 555 jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V"); 556 ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor)); 557 558 // fill NativeNfcTag's mProtocols, mTechList, mTechHandles, mTechLibNfcTypes 559 fillNativeNfcTagMembers1(e, tag_cls.get(), tag.get()); 560 561 // fill NativeNfcTag's members: mHandle, mConnectedTechnology 562 fillNativeNfcTagMembers2(e, tag_cls.get(), tag.get(), activationData); 563 564 // fill NativeNfcTag's members: mTechPollBytes 565 fillNativeNfcTagMembers3(e, tag_cls.get(), tag.get(), activationData); 566 567 // fill NativeNfcTag's members: mTechActBytes 568 fillNativeNfcTagMembers4(e, tag_cls.get(), tag.get(), activationData); 569 570 // fill NativeNfcTag's members: mUid 571 fillNativeNfcTagMembers5(e, tag_cls.get(), tag.get(), activationData); 572 573 if (mNativeData->tag != NULL) { 574 e->DeleteGlobalRef(mNativeData->tag); 575 } 576 mNativeData->tag = e->NewGlobalRef(tag.get()); 577 578 // notify NFC service about this new tag 579 DLOG_IF(INFO, nfc_debug_enabled) 580 << StringPrintf("%s: try notify nfc service", fn); 581 e->CallVoidMethod(mNativeData->manager, 582 android::gCachedNfcManagerNotifyNdefMessageListeners, 583 tag.get()); 584 if (e->ExceptionCheck()) { 585 e->ExceptionClear(); 586 LOG(ERROR) << StringPrintf("%s: fail notify nfc service", fn); 587 } 588 589 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: exit", fn); 590 } 591 592 /******************************************************************************* 593 ** 594 ** Function: fillNativeNfcTagMembers1 595 ** 596 ** Description: Fill NativeNfcTag's members: mProtocols, mTechList, 597 *mTechHandles, mTechLibNfcTypes. 598 ** e: JVM environment. 599 ** tag_cls: Java NativeNfcTag class. 600 ** tag: Java NativeNfcTag object. 601 ** 602 ** Returns: None 603 ** 604 *******************************************************************************/ 605 void NfcTag::fillNativeNfcTagMembers1(JNIEnv* e, jclass tag_cls, jobject tag) { 606 static const char fn[] = "NfcTag::fillNativeNfcTagMembers1"; 607 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", fn); 608 609 // create objects that represent NativeNfcTag's member variables 610 ScopedLocalRef<jintArray> techList(e, e->NewIntArray(mNumTechList)); 611 ScopedLocalRef<jintArray> handleList(e, e->NewIntArray(mNumTechList)); 612 ScopedLocalRef<jintArray> typeList(e, e->NewIntArray(mNumTechList)); 613 614 { 615 ScopedIntArrayRW technologies(e, techList.get()); 616 ScopedIntArrayRW handles(e, handleList.get()); 617 ScopedIntArrayRW types(e, typeList.get()); 618 for (int i = 0; i < mNumTechList; i++) { 619 mNativeData->tProtocols[i] = mTechLibNfcTypes[i]; 620 mNativeData->handles[i] = mTechHandles[i]; 621 technologies[i] = mTechList[i]; 622 handles[i] = mTechHandles[i]; 623 types[i] = mTechLibNfcTypes[i]; 624 } 625 } 626 627 jfieldID f = NULL; 628 629 f = e->GetFieldID(tag_cls, "mTechList", "[I"); 630 e->SetObjectField(tag, f, techList.get()); 631 632 f = e->GetFieldID(tag_cls, "mTechHandles", "[I"); 633 e->SetObjectField(tag, f, handleList.get()); 634 635 f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I"); 636 e->SetObjectField(tag, f, typeList.get()); 637 } 638 639 /******************************************************************************* 640 ** 641 ** Function: fillNativeNfcTagMembers2 642 ** 643 ** Description: Fill NativeNfcTag's members: mConnectedTechIndex or 644 *mConnectedTechnology. 645 ** The original Google's implementation is in 646 *set_target_pollBytes( 647 ** in com_android_nfc_NativeNfcTag.cpp; 648 ** e: JVM environment. 649 ** tag_cls: Java NativeNfcTag class. 650 ** tag: Java NativeNfcTag object. 651 ** activationData: data from activation. 652 ** 653 ** Returns: None 654 ** 655 *******************************************************************************/ 656 void NfcTag::fillNativeNfcTagMembers2(JNIEnv* e, jclass tag_cls, jobject tag, 657 tNFA_ACTIVATED& /*activationData*/) { 658 static const char fn[] = "NfcTag::fillNativeNfcTagMembers2"; 659 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", fn); 660 jfieldID f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I"); 661 e->SetIntField(tag, f, (jint)0); 662 } 663 664 /******************************************************************************* 665 ** 666 ** Function: fillNativeNfcTagMembers3 667 ** 668 ** Description: Fill NativeNfcTag's members: mTechPollBytes. 669 ** The original Google's implementation is in 670 *set_target_pollBytes( 671 ** in com_android_nfc_NativeNfcTag.cpp; 672 ** e: JVM environment. 673 ** tag_cls: Java NativeNfcTag class. 674 ** tag: Java NativeNfcTag object. 675 ** activationData: data from activation. 676 ** 677 ** Returns: None 678 ** 679 *******************************************************************************/ 680 void NfcTag::fillNativeNfcTagMembers3(JNIEnv* e, jclass tag_cls, jobject tag, 681 tNFA_ACTIVATED& activationData) { 682 static const char fn[] = "NfcTag::fillNativeNfcTagMembers3"; 683 ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0)); 684 ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get())); 685 ScopedLocalRef<jobjectArray> techPollBytes( 686 e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0)); 687 int len = 0; 688 689 for (int i = 0; i < mNumTechList; i++) { 690 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 691 "%s: index=%d; rf tech params mode=%u", fn, i, mTechParams[i].mode); 692 if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams[i].mode || 693 NFC_DISCOVERY_TYPE_POLL_A_ACTIVE == mTechParams[i].mode || 694 NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams[i].mode || 695 NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE == mTechParams[i].mode) { 696 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech A", fn); 697 pollBytes.reset(e->NewByteArray(2)); 698 e->SetByteArrayRegion(pollBytes.get(), 0, 2, 699 (jbyte*)mTechParams[i].param.pa.sens_res); 700 } else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams[i].mode || 701 NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams[i].mode || 702 NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams[i].mode || 703 NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams[i].mode) { 704 if (mTechList[i] == 705 TARGET_TYPE_ISO14443_3B) // is TagTechnology.NFC_B by Java API 706 { 707 /***************** 708 see NFC Forum Digital Protocol specification; section 5.6.2; 709 in SENSB_RES response, byte 6 through 9 is Application Data, byte 10-12 710 or 13 is Protocol Info; used by public API: NfcB.getApplicationData(), 711 NfcB.getProtocolInfo(); 712 *****************/ 713 DLOG_IF(INFO, nfc_debug_enabled) 714 << StringPrintf("%s: tech B; TARGET_TYPE_ISO14443_3B", fn); 715 len = mTechParams[i].param.pb.sensb_res_len; 716 len = len - 4; // subtract 4 bytes for NFCID0 at byte 2 through 5 717 pollBytes.reset(e->NewByteArray(len)); 718 e->SetByteArrayRegion(pollBytes.get(), 0, len, 719 (jbyte*)(mTechParams[i].param.pb.sensb_res + 4)); 720 } else { 721 pollBytes.reset(e->NewByteArray(0)); 722 } 723 } else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams[i].mode || 724 NFC_DISCOVERY_TYPE_POLL_F_ACTIVE == mTechParams[i].mode || 725 NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams[i].mode || 726 NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE == mTechParams[i].mode) { 727 /**************** 728 see NFC Forum Type 3 Tag Operation Specification; sections 2.3.2, 2.3.1.2; 729 see NFC Forum Digital Protocol Specification; sections 6.6.2; 730 PMm: manufacture parameter; 8 bytes; 731 System Code: 2 bytes; 732 ****************/ 733 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech F", fn); 734 uint8_t result[10]; // return result to NFC service 735 memset(result, 0, sizeof(result)); 736 len = 10; 737 738 /**** 739 for (int ii = 0; ii < mTechParams [i].param.pf.sensf_res_len; ii++) 740 { 741 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech F, 742 sendf_res[%d]=%d (0x%x)", fn, ii, mTechParams 743 [i].param.pf.sensf_res[ii],mTechParams [i].param.pf.sensf_res[ii]); 744 } 745 ***/ 746 memcpy(result, mTechParams[i].param.pf.sensf_res + 8, 8); // copy PMm 747 if (activationData.params.t3t.num_system_codes > 748 0) // copy the first System Code 749 { 750 uint16_t systemCode = *(activationData.params.t3t.p_system_codes); 751 result[8] = (uint8_t)(systemCode >> 8); 752 result[9] = (uint8_t)systemCode; 753 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 754 "%s: tech F; sys code=0x%X 0x%X", fn, result[8], result[9]); 755 } 756 pollBytes.reset(e->NewByteArray(len)); 757 e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*)result); 758 } else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams[i].mode || 759 NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams[i].mode) { 760 DLOG_IF(INFO, nfc_debug_enabled) 761 << StringPrintf("%s: tech iso 15693", fn); 762 // iso 15693 response flags: 1 octet 763 // iso 15693 Data Structure Format Identifier (DSF ID): 1 octet 764 // used by public API: NfcV.getDsfId(), NfcV.getResponseFlags(); 765 uint8_t data[2] = {activationData.params.i93.afi, 766 activationData.params.i93.dsfid}; 767 pollBytes.reset(e->NewByteArray(2)); 768 e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*)data); 769 } else { 770 LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn); 771 pollBytes.reset(e->NewByteArray(0)); 772 } // switch: every type of technology 773 e->SetObjectArrayElement(techPollBytes.get(), i, pollBytes.get()); 774 } // for: every technology in the array 775 jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B"); 776 e->SetObjectField(tag, f, techPollBytes.get()); 777 } 778 779 /******************************************************************************* 780 ** 781 ** Function: fillNativeNfcTagMembers4 782 ** 783 ** Description: Fill NativeNfcTag's members: mTechActBytes. 784 ** The original Google's implementation is in 785 *set_target_activationBytes() 786 ** in com_android_nfc_NativeNfcTag.cpp; 787 ** e: JVM environment. 788 ** tag_cls: Java NativeNfcTag class. 789 ** tag: Java NativeNfcTag object. 790 ** activationData: data from activation. 791 ** 792 ** Returns: None 793 ** 794 *******************************************************************************/ 795 void NfcTag::fillNativeNfcTagMembers4(JNIEnv* e, jclass tag_cls, jobject tag, 796 tNFA_ACTIVATED& activationData) { 797 static const char fn[] = "NfcTag::fillNativeNfcTagMembers4"; 798 ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0)); 799 ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get())); 800 ScopedLocalRef<jobjectArray> techActBytes( 801 e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0)); 802 803 for (int i = 0; i < mNumTechList; i++) { 804 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: index=%d", fn, i); 805 if (NFC_PROTOCOL_T1T == mTechLibNfcTypes[i] || 806 NFC_PROTOCOL_T2T == mTechLibNfcTypes[i]) { 807 if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T1T) 808 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: T1T; tech A", fn); 809 else if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T2T) 810 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: T2T; tech A", fn); 811 actBytes.reset(e->NewByteArray(1)); 812 e->SetByteArrayRegion(actBytes.get(), 0, 1, 813 (jbyte*)&mTechParams[i].param.pa.sel_rsp); 814 } else if (NFC_PROTOCOL_T3T == mTechLibNfcTypes[i]) { 815 // felica 816 DLOG_IF(INFO, nfc_debug_enabled) 817 << StringPrintf("%s: T3T; felica; tech F", fn); 818 // really, there is no data 819 actBytes.reset(e->NewByteArray(0)); 820 } else if (NFC_PROTOCOL_MIFARE == mTechLibNfcTypes[i]) { 821 DLOG_IF(INFO, nfc_debug_enabled) 822 << StringPrintf("%s: Mifare Classic; tech A", fn); 823 actBytes.reset(e->NewByteArray(1)); 824 e->SetByteArrayRegion(actBytes.get(), 0, 1, 825 (jbyte*)&mTechParams[i].param.pa.sel_rsp); 826 } else if (NFC_PROTOCOL_ISO_DEP == mTechLibNfcTypes[i]) { 827 // t4t 828 if (mTechList[i] == 829 TARGET_TYPE_ISO14443_4) // is TagTechnology.ISO_DEP by Java API 830 { 831 if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) || 832 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE) || 833 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A) || 834 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE)) { 835 // see NFC Forum Digital Protocol specification, section 11.6.2, "RATS 836 // Response"; search for "historical bytes"; copy historical bytes 837 // into Java object; the public API, IsoDep.getHistoricalBytes(), 838 // returns this data; 839 if (activationData.activate_ntf.intf_param.type == 840 NFC_INTERFACE_ISO_DEP) { 841 tNFC_INTF_PA_ISO_DEP& pa_iso = 842 activationData.activate_ntf.intf_param.intf_param.pa_iso; 843 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 844 "%s: T4T; ISO_DEP for tech A; copy historical bytes; len=%u", 845 fn, pa_iso.his_byte_len); 846 actBytes.reset(e->NewByteArray(pa_iso.his_byte_len)); 847 if (pa_iso.his_byte_len > 0) 848 e->SetByteArrayRegion(actBytes.get(), 0, pa_iso.his_byte_len, 849 (jbyte*)(pa_iso.his_byte)); 850 } else { 851 LOG(ERROR) << StringPrintf( 852 "%s: T4T; ISO_DEP for tech A; wrong interface=%u", fn, 853 activationData.activate_ntf.intf_param.type); 854 actBytes.reset(e->NewByteArray(0)); 855 } 856 } else if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B) || 857 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B_PRIME) || 858 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B) || 859 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)) { 860 // see NFC Forum Digital Protocol specification, section 12.6.2, 861 // "ATTRIB Response"; copy higher-layer response bytes into Java 862 // object; the public API, IsoDep.getHiLayerResponse(), returns this 863 // data; 864 if (activationData.activate_ntf.intf_param.type == 865 NFC_INTERFACE_ISO_DEP) { 866 tNFC_INTF_PB_ISO_DEP& pb_iso = 867 activationData.activate_ntf.intf_param.intf_param.pb_iso; 868 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 869 "%s: T4T; ISO_DEP for tech B; copy response bytes; len=%u", fn, 870 pb_iso.hi_info_len); 871 actBytes.reset(e->NewByteArray(pb_iso.hi_info_len)); 872 if (pb_iso.hi_info_len > 0) 873 e->SetByteArrayRegion(actBytes.get(), 0, pb_iso.hi_info_len, 874 (jbyte*)(pb_iso.hi_info)); 875 } else { 876 LOG(ERROR) << StringPrintf( 877 "%s: T4T; ISO_DEP for tech B; wrong interface=%u", fn, 878 activationData.activate_ntf.intf_param.type); 879 actBytes.reset(e->NewByteArray(0)); 880 } 881 } 882 } else if (mTechList[i] == 883 TARGET_TYPE_ISO14443_3A) // is TagTechnology.NFC_A by Java API 884 { 885 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: T4T; tech A", fn); 886 actBytes.reset(e->NewByteArray(1)); 887 e->SetByteArrayRegion(actBytes.get(), 0, 1, 888 (jbyte*)&mTechParams[i].param.pa.sel_rsp); 889 } else { 890 actBytes.reset(e->NewByteArray(0)); 891 } 892 } // case NFC_PROTOCOL_ISO_DEP: //t4t 893 else if (NFC_PROTOCOL_T5T == mTechLibNfcTypes[i]) { 894 DLOG_IF(INFO, nfc_debug_enabled) 895 << StringPrintf("%s: tech iso 15693", fn); 896 // iso 15693 response flags: 1 octet 897 // iso 15693 Data Structure Format Identifier (DSF ID): 1 octet 898 // used by public API: NfcV.getDsfId(), NfcV.getResponseFlags(); 899 uint8_t data[2] = {activationData.params.i93.afi, 900 activationData.params.i93.dsfid}; 901 actBytes.reset(e->NewByteArray(2)); 902 e->SetByteArrayRegion(actBytes.get(), 0, 2, (jbyte*)data); 903 } else { 904 DLOG_IF(INFO, nfc_debug_enabled) 905 << StringPrintf("%s: tech unknown ????", fn); 906 actBytes.reset(e->NewByteArray(0)); 907 } 908 e->SetObjectArrayElement(techActBytes.get(), i, actBytes.get()); 909 } // for: every technology in the array 910 jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B"); 911 e->SetObjectField(tag, f, techActBytes.get()); 912 } 913 914 /******************************************************************************* 915 ** 916 ** Function: fillNativeNfcTagMembers5 917 ** 918 ** Description: Fill NativeNfcTag's members: mUid. 919 ** The original Google's implementation is in 920 *nfc_jni_Discovery_notification_callback() 921 ** in com_android_nfc_NativeNfcManager.cpp; 922 ** e: JVM environment. 923 ** tag_cls: Java NativeNfcTag class. 924 ** tag: Java NativeNfcTag object. 925 ** activationData: data from activation. 926 ** 927 ** Returns: None 928 ** 929 *******************************************************************************/ 930 void NfcTag::fillNativeNfcTagMembers5(JNIEnv* e, jclass tag_cls, jobject tag, 931 tNFA_ACTIVATED& activationData) { 932 static const char fn[] = "NfcTag::fillNativeNfcTagMembers5"; 933 int len = 0; 934 ScopedLocalRef<jbyteArray> uid(e, NULL); 935 936 if (NFC_DISCOVERY_TYPE_POLL_KOVIO == mTechParams[0].mode) { 937 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: Kovio", fn); 938 len = mTechParams[0].param.pk.uid_len; 939 uid.reset(e->NewByteArray(len)); 940 e->SetByteArrayRegion(uid.get(), 0, len, 941 (jbyte*)&mTechParams[0].param.pk.uid); 942 } else if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams[0].mode || 943 NFC_DISCOVERY_TYPE_POLL_A_ACTIVE == mTechParams[0].mode || 944 NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams[0].mode || 945 NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE == mTechParams[0].mode) { 946 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech A", fn); 947 len = mTechParams[0].param.pa.nfcid1_len; 948 uid.reset(e->NewByteArray(len)); 949 e->SetByteArrayRegion(uid.get(), 0, len, 950 (jbyte*)&mTechParams[0].param.pa.nfcid1); 951 // a tag's NFCID1 can change dynamically at each activation; 952 // only the first byte (0x08) is constant; a dynamic NFCID1's length 953 // must be 4 bytes (see NFC Digitial Protocol, 954 // section 4.7.2 SDD_RES Response, Requirements 20). 955 mIsDynamicTagId = (mTechParams[0].param.pa.nfcid1_len == 4) && 956 (mTechParams[0].param.pa.nfcid1[0] == 0x08); 957 } else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams[0].mode || 958 NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams[0].mode || 959 NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams[0].mode || 960 NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams[0].mode) { 961 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech B", fn); 962 uid.reset(e->NewByteArray(NFC_NFCID0_MAX_LEN)); 963 e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID0_MAX_LEN, 964 (jbyte*)&mTechParams[0].param.pb.nfcid0); 965 } else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams[0].mode || 966 NFC_DISCOVERY_TYPE_POLL_F_ACTIVE == mTechParams[0].mode || 967 NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams[0].mode || 968 NFC_DISCOVERY_TYPE_LISTEN_F_ACTIVE == mTechParams[0].mode) { 969 uid.reset(e->NewByteArray(NFC_NFCID2_LEN)); 970 e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID2_LEN, 971 (jbyte*)&mTechParams[0].param.pf.nfcid2); 972 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech F", fn); 973 } else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams[0].mode || 974 NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams[0].mode) { 975 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: tech iso 15693", fn); 976 jbyte data[I93_UID_BYTE_LEN]; // 8 bytes 977 for (int i = 0; i < I93_UID_BYTE_LEN; ++i) // reverse the ID 978 data[i] = activationData.params.i93.uid[I93_UID_BYTE_LEN - i - 1]; 979 uid.reset(e->NewByteArray(I93_UID_BYTE_LEN)); 980 e->SetByteArrayRegion(uid.get(), 0, I93_UID_BYTE_LEN, data); 981 } else { 982 LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn); 983 uid.reset(e->NewByteArray(0)); 984 } 985 jfieldID f = e->GetFieldID(tag_cls, "mUid", "[B"); 986 e->SetObjectField(tag, f, uid.get()); 987 } 988 989 /******************************************************************************* 990 ** 991 ** Function: isP2pDiscovered 992 ** 993 ** Description: Does the peer support P2P? 994 ** 995 ** Returns: True if the peer supports P2P. 996 ** 997 *******************************************************************************/ 998 bool NfcTag::isP2pDiscovered() { 999 static const char fn[] = "NfcTag::isP2pDiscovered"; 1000 bool retval = false; 1001 1002 for (int i = 0; i < mNumTechList; i++) { 1003 if (mTechLibNfcTypes[i] == NFA_PROTOCOL_NFC_DEP) { 1004 // if remote device supports P2P 1005 DLOG_IF(INFO, nfc_debug_enabled) 1006 << StringPrintf("%s: discovered P2P", fn); 1007 retval = true; 1008 break; 1009 } 1010 } 1011 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return=%u", fn, retval); 1012 return retval; 1013 } 1014 1015 /******************************************************************************* 1016 ** 1017 ** Function: selectP2p 1018 ** 1019 ** Description: Select the preferred P2P technology if there is a choice. 1020 ** 1021 ** Returns: None 1022 ** 1023 *******************************************************************************/ 1024 void NfcTag::selectP2p() { 1025 static const char fn[] = "NfcTag::selectP2p"; 1026 uint8_t rfDiscoveryId = 0; 1027 1028 for (int i = 0; i < mNumTechList; i++) { 1029 // if remote device does not support P2P, just skip it 1030 if (mTechLibNfcTypes[i] != NFA_PROTOCOL_NFC_DEP) continue; 1031 1032 // if remote device supports tech F; 1033 // tech F is preferred because it is faster than tech A 1034 if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_F) || 1035 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_F_ACTIVE)) { 1036 rfDiscoveryId = mTechHandles[i]; 1037 break; // no need to search further 1038 } else if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) || 1039 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A_ACTIVE)) { 1040 // only choose tech A if tech F is unavailable 1041 if (rfDiscoveryId == 0) rfDiscoveryId = mTechHandles[i]; 1042 } 1043 } 1044 1045 if (rfDiscoveryId > 0) { 1046 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf( 1047 "%s: select P2P; target rf discov id=0x%X", fn, rfDiscoveryId); 1048 tNFA_STATUS stat = 1049 NFA_Select(rfDiscoveryId, NFA_PROTOCOL_NFC_DEP, NFA_INTERFACE_NFC_DEP); 1050 if (stat != NFA_STATUS_OK) 1051 LOG(ERROR) << StringPrintf("%s: fail select P2P; error=0x%X", fn, stat); 1052 } else 1053 LOG(ERROR) << StringPrintf("%s: cannot find P2P", fn); 1054 resetTechnologies(); 1055 } 1056 1057 /******************************************************************************* 1058 ** 1059 ** Function: resetTechnologies 1060 ** 1061 ** Description: Clear all data related to the technology, protocol of the 1062 *tag. 1063 ** 1064 ** Returns: None 1065 ** 1066 *******************************************************************************/ 1067 void NfcTag::resetTechnologies() { 1068 static const char fn[] = "NfcTag::resetTechnologies"; 1069 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", fn); 1070 mNumTechList = 0; 1071 memset(mTechList, 0, sizeof(mTechList)); 1072 memset(mTechHandles, 0, sizeof(mTechHandles)); 1073 memset(mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes)); 1074 memset(mTechParams, 0, sizeof(mTechParams)); 1075 mIsDynamicTagId = false; 1076 mIsFelicaLite = false; 1077 resetAllTransceiveTimeouts(); 1078 } 1079 1080 /******************************************************************************* 1081 ** 1082 ** Function: selectFirstTag 1083 ** 1084 ** Description: When multiple tags are discovered, just select the first one 1085 *to activate. 1086 ** 1087 ** Returns: None 1088 ** 1089 *******************************************************************************/ 1090 void NfcTag::selectFirstTag() { 1091 static const char fn[] = "NfcTag::selectFirstTag"; 1092 int foundIdx = -1; 1093 tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME; 1094 1095 for (int i = 0; i < mNumTechList; i++) { 1096 DLOG_IF(INFO, nfc_debug_enabled) 1097 << StringPrintf("%s: nfa target idx=%d h=0x%X; protocol=0x%X", fn, i, 1098 mTechHandles[i], mTechLibNfcTypes[i]); 1099 if (mTechLibNfcTypes[i] != NFA_PROTOCOL_NFC_DEP) { 1100 foundIdx = i; 1101 break; 1102 } 1103 } 1104 1105 if (foundIdx != -1) { 1106 if (mTechLibNfcTypes[foundIdx] == NFA_PROTOCOL_ISO_DEP) { 1107 rf_intf = NFA_INTERFACE_ISO_DEP; 1108 } else if (mTechLibNfcTypes[foundIdx] == NFC_PROTOCOL_MIFARE) { 1109 rf_intf = NFA_INTERFACE_MIFARE; 1110 } else 1111 rf_intf = NFA_INTERFACE_FRAME; 1112 1113 tNFA_STATUS stat = 1114 NFA_Select(mTechHandles[foundIdx], mTechLibNfcTypes[foundIdx], rf_intf); 1115 if (stat != NFA_STATUS_OK) 1116 LOG(ERROR) << StringPrintf("%s: fail select; error=0x%X", fn, stat); 1117 } else 1118 LOG(ERROR) << StringPrintf("%s: only found NFC-DEP technology.", fn); 1119 } 1120 1121 /******************************************************************************* 1122 ** 1123 ** Function: getT1tMaxMessageSize 1124 ** 1125 ** Description: Get the maximum size (octet) that a T1T can store. 1126 ** 1127 ** Returns: Maximum size in octets. 1128 ** 1129 *******************************************************************************/ 1130 int NfcTag::getT1tMaxMessageSize() { 1131 static const char fn[] = "NfcTag::getT1tMaxMessageSize"; 1132 1133 if (mProtocol != NFC_PROTOCOL_T1T) { 1134 LOG(ERROR) << StringPrintf("%s: wrong protocol %u", fn, mProtocol); 1135 return 0; 1136 } 1137 return mtT1tMaxMessageSize; 1138 } 1139 1140 /******************************************************************************* 1141 ** 1142 ** Function: calculateT1tMaxMessageSize 1143 ** 1144 ** Description: Calculate type-1 tag's max message size based on header ROM 1145 *bytes. 1146 ** activate: reference to activation data. 1147 ** 1148 ** Returns: None 1149 ** 1150 *******************************************************************************/ 1151 void NfcTag::calculateT1tMaxMessageSize(tNFA_ACTIVATED& activate) { 1152 static const char fn[] = "NfcTag::calculateT1tMaxMessageSize"; 1153 1154 // make sure the tag is type-1 1155 if (activate.activate_ntf.protocol != NFC_PROTOCOL_T1T) { 1156 mtT1tMaxMessageSize = 0; 1157 return; 1158 } 1159 1160 // examine the first byte of header ROM bytes 1161 switch (activate.params.t1t.hr[0]) { 1162 case RW_T1T_IS_TOPAZ96: 1163 mtT1tMaxMessageSize = 90; 1164 break; 1165 case RW_T1T_IS_TOPAZ512: 1166 mtT1tMaxMessageSize = 462; 1167 break; 1168 default: 1169 LOG(ERROR) << StringPrintf("%s: unknown T1T HR0=%u", fn, 1170 activate.params.t1t.hr[0]); 1171 mtT1tMaxMessageSize = 0; 1172 break; 1173 } 1174 } 1175 1176 /******************************************************************************* 1177 ** 1178 ** Function: isMifareUltralight 1179 ** 1180 ** Description: Whether the currently activated tag is Mifare Ultralight. 1181 ** 1182 ** Returns: True if tag is Mifare Ultralight. 1183 ** 1184 *******************************************************************************/ 1185 bool NfcTag::isMifareUltralight() { 1186 static const char fn[] = "NfcTag::isMifareUltralight"; 1187 bool retval = false; 1188 1189 for (int i = 0; i < mNumTechList; i++) { 1190 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) { 1191 // see NFC Digital Protocol, section 4.6.3 (SENS_RES); section 4.8.2 1192 // (SEL_RES). see "MF0ICU1 Functional specification MIFARE Ultralight", 1193 // Rev. 3.4 - 4 February 2008, section 6.7. 1194 if ((mTechParams[i].param.pa.sens_res[0] == 0x44) && 1195 (mTechParams[i].param.pa.sens_res[1] == 0) && 1196 ((mTechParams[i].param.pa.sel_rsp == 0) || 1197 (mTechParams[i].param.pa.sel_rsp == 0x04)) && 1198 (mTechParams[i].param.pa.nfcid1[0] == 0x04)) { 1199 retval = true; 1200 } 1201 break; 1202 } 1203 } 1204 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return=%u", fn, retval); 1205 return retval; 1206 } 1207 1208 /******************************************************************************* 1209 ** 1210 ** Function: isMifareDESFire 1211 ** 1212 ** Description: Whether the currently activated tag is Mifare DESFire. 1213 ** 1214 ** Returns: True if tag is Mifare DESFire. 1215 ** 1216 *******************************************************************************/ 1217 bool NfcTag::isMifareDESFire() { 1218 static const char fn[] = "NfcTag::isMifareDESFire"; 1219 bool retval = false; 1220 1221 for (int i = 0; i < mNumTechList; i++) { 1222 if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) || 1223 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A) || 1224 (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE)) { 1225 /* DESfire has one sak byte and 2 ATQA bytes */ 1226 if ((mTechParams[i].param.pa.sens_res[0] == 0x44) && 1227 (mTechParams[i].param.pa.sens_res[1] == 0x03) && 1228 (mTechParams[i].param.pa.sel_rsp == 0x20)) { 1229 retval = true; 1230 } 1231 break; 1232 } 1233 } 1234 1235 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return=%u", fn, retval); 1236 return retval; 1237 } 1238 1239 /******************************************************************************* 1240 ** 1241 ** Function: isFelicaLite 1242 ** 1243 ** Description: Whether the currently activated tag is Felica Lite. 1244 ** 1245 ** Returns: True if tag is Felica Lite. 1246 ** 1247 *******************************************************************************/ 1248 1249 bool NfcTag::isFelicaLite() { return mIsFelicaLite; } 1250 1251 /******************************************************************************* 1252 ** 1253 ** Function: isT2tNackResponse 1254 ** 1255 ** Description: Whether the response is a T2T NACK response. 1256 ** See NFC Digital Protocol Technical Specification 1257 *(2010-11-17). 1258 ** Chapter 9 (Type 2 Tag Platform), section 9.6 (READ). 1259 ** response: buffer contains T2T response. 1260 ** responseLen: length of the response. 1261 ** 1262 ** Returns: True if the response is NACK 1263 ** 1264 *******************************************************************************/ 1265 bool NfcTag::isT2tNackResponse(const uint8_t* response, uint32_t responseLen) { 1266 static const char fn[] = "NfcTag::isT2tNackResponse"; 1267 bool isNack = false; 1268 1269 if (responseLen == 1) { 1270 if (response[0] == 0xA) 1271 isNack = false; // an ACK response, so definitely not a NACK 1272 else 1273 isNack = true; // assume every value is a NACK 1274 } 1275 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return %u", fn, isNack); 1276 return isNack; 1277 } 1278 1279 /******************************************************************************* 1280 ** 1281 ** Function: isNdefDetectionTimedOut 1282 ** 1283 ** Description: Whether NDEF-detection algorithm timed out. 1284 ** 1285 ** Returns: True if NDEF-detection algorithm timed out. 1286 ** 1287 *******************************************************************************/ 1288 bool NfcTag::isNdefDetectionTimedOut() { return mNdefDetectionTimedOut; } 1289 1290 /******************************************************************************* 1291 ** 1292 ** Function: connectionEventHandler 1293 ** 1294 ** Description: Handle connection-related events. 1295 ** event: event code. 1296 ** data: pointer to event data. 1297 ** 1298 ** Returns: None 1299 ** 1300 *******************************************************************************/ 1301 void NfcTag::connectionEventHandler(uint8_t event, tNFA_CONN_EVT_DATA* data) { 1302 static const char fn[] = "NfcTag::connectionEventHandler"; 1303 1304 switch (event) { 1305 case NFA_DISC_RESULT_EVT: { 1306 tNFA_DISC_RESULT& disc_result = data->disc_result; 1307 if (disc_result.status == NFA_STATUS_OK) { 1308 discoverTechnologies(disc_result); 1309 } 1310 } break; 1311 1312 case NFA_ACTIVATED_EVT: 1313 // Only do tag detection if we are polling and it is not 'EE Direct RF' 1314 // activation (which may happen when we are activated as a tag). 1315 if (data->activated.activate_ntf.rf_tech_param.mode < 1316 NCI_DISCOVERY_TYPE_LISTEN_A && 1317 data->activated.activate_ntf.intf_param.type != 1318 NFC_INTERFACE_EE_DIRECT_RF) { 1319 tNFA_ACTIVATED& activated = data->activated; 1320 if (IsSameKovio(activated)) break; 1321 mIsActivated = true; 1322 mProtocol = activated.activate_ntf.protocol; 1323 calculateT1tMaxMessageSize(activated); 1324 discoverTechnologies(activated); 1325 createNativeNfcTag(activated); 1326 } 1327 break; 1328 1329 case NFA_DEACTIVATED_EVT: 1330 mIsActivated = false; 1331 mProtocol = NFC_PROTOCOL_UNKNOWN; 1332 resetTechnologies(); 1333 break; 1334 1335 case NFA_READ_CPLT_EVT: { 1336 SyncEventGuard g(mReadCompleteEvent); 1337 mReadCompletedStatus = data->status; 1338 mNdefDetectionTimedOut = data->status != NFA_STATUS_OK; 1339 if (mNdefDetectionTimedOut) 1340 LOG(ERROR) << StringPrintf("%s: NDEF detection timed out", fn); 1341 mReadCompleteEvent.notifyOne(); 1342 } break; 1343 1344 case NFA_NDEF_DETECT_EVT: { 1345 tNFA_NDEF_DETECT& ndef_detect = data->ndef_detect; 1346 mNdefDetectionTimedOut = ndef_detect.status == NFA_STATUS_TIMEOUT; 1347 if (mNdefDetectionTimedOut) 1348 LOG(ERROR) << StringPrintf("%s: NDEF detection timed out", fn); 1349 } 1350 } 1351 } 1352 1353 /******************************************************************************* 1354 ** 1355 ** Function setActive 1356 ** 1357 ** Description Sets the active state for the object 1358 ** 1359 ** Returns None. 1360 ** 1361 *******************************************************************************/ 1362 void NfcTag::setActive(bool active) { mIsActivated = active; } 1363 1364 /******************************************************************************* 1365 ** 1366 ** Function: isDynamicTagId 1367 ** 1368 ** Description: Whether a tag has a dynamic tag ID. 1369 ** 1370 ** Returns: True if ID is dynamic. 1371 ** 1372 *******************************************************************************/ 1373 bool NfcTag::isDynamicTagId() { 1374 return mIsDynamicTagId && 1375 (mTechList[0] == TARGET_TYPE_ISO14443_4) && // type-4 tag 1376 (mTechList[1] == TARGET_TYPE_ISO14443_3A); // tech A 1377 } 1378 1379 /******************************************************************************* 1380 ** 1381 ** Function: resetAllTransceiveTimeouts 1382 ** 1383 ** Description: Reset all timeouts for all technologies to default values. 1384 ** 1385 ** Returns: none 1386 ** 1387 *******************************************************************************/ 1388 void NfcTag::resetAllTransceiveTimeouts() { 1389 mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3A] = 618; // NfcA 1390 mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3B] = 1000; // NfcB 1391 mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_4] = 618; // ISO-DEP 1392 mTechnologyTimeoutsTable[TARGET_TYPE_FELICA] = 255; // Felica 1393 mTechnologyTimeoutsTable[TARGET_TYPE_V] = 1000; // NfcV 1394 mTechnologyTimeoutsTable[TARGET_TYPE_NDEF] = 1000; 1395 mTechnologyTimeoutsTable[TARGET_TYPE_NDEF_FORMATABLE] = 1000; 1396 mTechnologyTimeoutsTable[TARGET_TYPE_MIFARE_CLASSIC] = 618; // MifareClassic 1397 mTechnologyTimeoutsTable[TARGET_TYPE_MIFARE_UL] = 618; // MifareUltralight 1398 mTechnologyTimeoutsTable[TARGET_TYPE_KOVIO_BARCODE] = 1000; // NfcBarcode 1399 } 1400 1401 /******************************************************************************* 1402 ** 1403 ** Function: getTransceiveTimeout 1404 ** 1405 ** Description: Get the timeout value for one technology. 1406 ** techId: one of the values in TARGET_TYPE_* defined in 1407 *NfcJniUtil.h 1408 ** 1409 ** Returns: Timeout value in millisecond. 1410 ** 1411 *******************************************************************************/ 1412 int NfcTag::getTransceiveTimeout(int techId) { 1413 static const char fn[] = "NfcTag::getTransceiveTimeout"; 1414 int retval = 1000; 1415 if ((techId > 0) && (techId < (int)mTechnologyTimeoutsTable.size())) 1416 retval = mTechnologyTimeoutsTable[techId]; 1417 else 1418 LOG(ERROR) << StringPrintf("%s: invalid tech=%d", fn, techId); 1419 return retval; 1420 } 1421 1422 /******************************************************************************* 1423 ** 1424 ** Function: setTransceiveTimeout 1425 ** 1426 ** Description: Set the timeout value for one technology. 1427 ** techId: one of the values in TARGET_TYPE_* defined in 1428 *NfcJniUtil.h 1429 ** timeout: timeout value in millisecond. 1430 ** 1431 ** Returns: Timeout value. 1432 ** 1433 *******************************************************************************/ 1434 void NfcTag::setTransceiveTimeout(int techId, int timeout) { 1435 static const char fn[] = "NfcTag::setTransceiveTimeout"; 1436 if ((techId >= 0) && (techId < (int)mTechnologyTimeoutsTable.size())) 1437 mTechnologyTimeoutsTable[techId] = timeout; 1438 else 1439 LOG(ERROR) << StringPrintf("%s: invalid tech=%d", fn, techId); 1440 } 1441 1442 /******************************************************************************* 1443 ** 1444 ** Function: getPresenceCheckAlgorithm 1445 ** 1446 ** Description: Get presence-check algorithm from .conf file. 1447 ** 1448 ** Returns: Presence-check algorithm. 1449 ** 1450 *******************************************************************************/ 1451 tNFA_RW_PRES_CHK_OPTION NfcTag::getPresenceCheckAlgorithm() { 1452 return mPresenceCheckAlgorithm; 1453 } 1454 1455 /******************************************************************************* 1456 ** 1457 ** Function: isInfineonMyDMove 1458 ** 1459 ** Description: Whether the currently activated tag is Infineon My-D Move. 1460 ** 1461 ** Returns: True if tag is Infineon My-D Move. 1462 ** 1463 *******************************************************************************/ 1464 bool NfcTag::isInfineonMyDMove() { 1465 static const char fn[] = "NfcTag::isInfineonMyDMove"; 1466 bool retval = false; 1467 1468 for (int i = 0; i < mNumTechList; i++) { 1469 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) { 1470 // see Infineon my-d move, my-d move NFC, SLE 66R01P, SLE 66R01PN, 1471 // Short Product Information, 2011-11-24, section 3.5 1472 if (mTechParams[i].param.pa.nfcid1[0] == 0x05) { 1473 uint8_t highNibble = mTechParams[i].param.pa.nfcid1[1] & 0xF0; 1474 if (highNibble == 0x30) retval = true; 1475 } 1476 break; 1477 } 1478 } 1479 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return=%u", fn, retval); 1480 return retval; 1481 } 1482 1483 /******************************************************************************* 1484 ** 1485 ** Function: isKovioType2Tag 1486 ** 1487 ** Description: Whether the currently activated tag is Kovio Type-2 tag. 1488 ** 1489 ** Returns: True if tag is Kovio Type-2 tag. 1490 ** 1491 *******************************************************************************/ 1492 bool NfcTag::isKovioType2Tag() { 1493 static const char fn[] = "NfcTag::isKovioType2Tag"; 1494 bool retval = false; 1495 1496 for (int i = 0; i < mNumTechList; i++) { 1497 if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) { 1498 // Kovio 2Kb RFID Tag, Functional Specification, 1499 // March 2, 2012, v2.0, section 8.3. 1500 if (mTechParams[i].param.pa.nfcid1[0] == 0x37) retval = true; 1501 break; 1502 } 1503 } 1504 DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: return=%u", fn, retval); 1505 return retval; 1506 } 1507