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