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