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