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