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