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