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