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