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