• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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