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