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