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