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