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#include <semaphore.h>
18#include <errno.h>
19#include <time.h>
20#include <signal.h>
21#include "OverrideLog.h"
22#include "NfcJniUtil.h"
23#include "NfcTag.h"
24#include "config.h"
25#include "Mutex.h"
26#include "IntervalTimer.h"
27#include "JavaClassConstants.h"
28#include "Pn544Interop.h"
29#include <ScopedLocalRef.h>
30#include <ScopedPrimitiveArray.h>
31#include <string>
32
33extern "C"
34{
35    #include "nfa_api.h"
36    #include "nfa_rw_api.h"
37    #include "ndef_utils.h"
38    #include "rw_api.h"
39}
40namespace android
41{
42    extern nfc_jni_native_data* getNative(JNIEnv *e, jobject o);
43    extern bool nfcManager_isNfcActive();
44}
45
46extern bool         gActivated;
47extern SyncEvent    gDeactivatedEvent;
48
49/*****************************************************************************
50**
51** public variables and functions
52**
53*****************************************************************************/
54namespace android
55{
56    bool    gIsTagDeactivating = false;    // flag for nfa callback indicating we are deactivating for RF interface switch
57    bool    gIsSelectingRfInterface = false; // flag for nfa callback indicating we are selecting for RF interface switch
58}
59
60
61/*****************************************************************************
62**
63** private variables and functions
64**
65*****************************************************************************/
66namespace android
67{
68
69
70// Pre-defined tag type values. These must match the values in
71// framework Ndef.java for Google public NFC API.
72#define NDEF_UNKNOWN_TYPE          -1
73#define NDEF_TYPE1_TAG             1
74#define NDEF_TYPE2_TAG             2
75#define NDEF_TYPE3_TAG             3
76#define NDEF_TYPE4_TAG             4
77#define NDEF_MIFARE_CLASSIC_TAG    101
78
79#define STATUS_CODE_TARGET_LOST    146	// this error code comes from the service
80
81static uint32_t     sCheckNdefCurrentSize = 0;
82static tNFA_STATUS  sCheckNdefStatus = 0; //whether tag already contains a NDEF message
83static bool         sCheckNdefCapable = false; //whether tag has NDEF capability
84static tNFA_HANDLE  sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
85static tNFA_INTF_TYPE   sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
86static std::basic_string<UINT8> sRxDataBuffer;
87static tNFA_STATUS  sRxDataStatus = NFA_STATUS_OK;
88static bool         sWaitingForTransceive = false;
89static bool         sTransceiveRfTimeout = false;
90static Mutex        sRfInterfaceMutex;
91static uint32_t     sReadDataLen = 0;
92static uint8_t*     sReadData = NULL;
93static bool         sIsReadingNdefMessage = false;
94static SyncEvent    sReadEvent;
95static sem_t        sWriteSem;
96static sem_t        sFormatSem;
97static SyncEvent    sTransceiveEvent;
98static SyncEvent    sReconnectEvent;
99static sem_t        sCheckNdefSem;
100static SyncEvent    sPresenceCheckEvent;
101static sem_t        sMakeReadonlySem;
102static IntervalTimer sSwitchBackTimer; // timer used to tell us to switch back to ISO_DEP frame interface
103static jboolean     sWriteOk = JNI_FALSE;
104static jboolean     sWriteWaitingForComplete = JNI_FALSE;
105static bool         sFormatOk = false;
106static jboolean     sConnectOk = JNI_FALSE;
107static jboolean     sConnectWaitingForComplete = JNI_FALSE;
108static bool         sGotDeactivate = false;
109static uint32_t     sCheckNdefMaxSize = 0;
110static bool         sCheckNdefCardReadOnly = false;
111static jboolean     sCheckNdefWaitingForComplete = JNI_FALSE;
112static bool         sIsTagPresent = true;
113static tNFA_STATUS  sMakeReadonlyStatus = NFA_STATUS_FAILED;
114static jboolean     sMakeReadonlyWaitingForComplete = JNI_FALSE;
115static int          sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
116
117static int reSelect (tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded);
118static bool switchRfInterface(tNFA_INTF_TYPE rfInterface);
119
120
121/*******************************************************************************
122**
123** Function:        nativeNfcTag_abortWaits
124**
125** Description:     Unblock all thread synchronization objects.
126**
127** Returns:         None
128**
129*******************************************************************************/
130void nativeNfcTag_abortWaits ()
131{
132    ALOGD ("%s", __FUNCTION__);
133    {
134        SyncEventGuard g (sReadEvent);
135        sReadEvent.notifyOne ();
136    }
137    sem_post (&sWriteSem);
138    sem_post (&sFormatSem);
139    {
140        SyncEventGuard g (sTransceiveEvent);
141        sTransceiveEvent.notifyOne ();
142    }
143    {
144        SyncEventGuard g (sReconnectEvent);
145        sReconnectEvent.notifyOne ();
146    }
147
148    sem_post (&sCheckNdefSem);
149    {
150        SyncEventGuard guard (sPresenceCheckEvent);
151        sPresenceCheckEvent.notifyOne ();
152    }
153    sem_post (&sMakeReadonlySem);
154    sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
155    sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
156}
157
158/*******************************************************************************
159**
160** Function:        nativeNfcTag_doReadCompleted
161**
162** Description:     Receive the completion status of read operation.  Called by
163**                  NFA_READ_CPLT_EVT.
164**                  status: Status of operation.
165**
166** Returns:         None
167**
168*******************************************************************************/
169void nativeNfcTag_doReadCompleted (tNFA_STATUS status)
170{
171    ALOGD ("%s: status=0x%X; is reading=%u", __FUNCTION__, status, sIsReadingNdefMessage);
172
173    if (sIsReadingNdefMessage == false)
174        return; //not reading NDEF message right now, so just return
175
176    if (status != NFA_STATUS_OK)
177    {
178        sReadDataLen = 0;
179        if (sReadData)
180            free (sReadData);
181        sReadData = NULL;
182    }
183    SyncEventGuard g (sReadEvent);
184    sReadEvent.notifyOne ();
185}
186
187
188/*******************************************************************************
189**
190** Function:        ndefHandlerCallback
191**
192** Description:     Receive NDEF-message related events from stack.
193**                  event: Event code.
194**                  p_data: Event data.
195**
196** Returns:         None
197**
198*******************************************************************************/
199static void ndefHandlerCallback (tNFA_NDEF_EVT event, tNFA_NDEF_EVT_DATA *eventData)
200{
201    ALOGD ("%s: event=%u, eventData=%p", __FUNCTION__, event, eventData);
202
203    switch (event)
204    {
205    case NFA_NDEF_REGISTER_EVT:
206        {
207            tNFA_NDEF_REGISTER& ndef_reg = eventData->ndef_reg;
208            ALOGD ("%s: NFA_NDEF_REGISTER_EVT; status=0x%X; h=0x%X", __FUNCTION__, ndef_reg.status, ndef_reg.ndef_type_handle);
209            sNdefTypeHandlerHandle = ndef_reg.ndef_type_handle;
210        }
211        break;
212
213    case NFA_NDEF_DATA_EVT:
214        {
215            ALOGD ("%s: NFA_NDEF_DATA_EVT; data_len = %lu", __FUNCTION__, eventData->ndef_data.len);
216            sReadDataLen = eventData->ndef_data.len;
217            sReadData = (uint8_t*) malloc (sReadDataLen);
218            memcpy (sReadData, eventData->ndef_data.p_data, eventData->ndef_data.len);
219        }
220        break;
221
222    default:
223        ALOGE ("%s: Unknown event %u ????", __FUNCTION__, event);
224        break;
225    }
226}
227
228
229/*******************************************************************************
230**
231** Function:        nativeNfcTag_doRead
232**
233** Description:     Read the NDEF message on the tag.
234**                  e: JVM environment.
235**                  o: Java object.
236**
237** Returns:         NDEF message.
238**
239*******************************************************************************/
240static jbyteArray nativeNfcTag_doRead (JNIEnv* e, jobject)
241{
242    ALOGD ("%s: enter", __FUNCTION__);
243    tNFA_STATUS status = NFA_STATUS_FAILED;
244    jbyteArray buf = NULL;
245
246    sReadDataLen = 0;
247    if (sReadData != NULL)
248    {
249        free (sReadData);
250        sReadData = NULL;
251    }
252
253    if (sCheckNdefCurrentSize > 0)
254    {
255        {
256            SyncEventGuard g (sReadEvent);
257            sIsReadingNdefMessage = true;
258            status = NFA_RwReadNDef ();
259            sReadEvent.wait (); //wait for NFA_READ_CPLT_EVT
260        }
261        sIsReadingNdefMessage = false;
262
263        if (sReadDataLen > 0) //if stack actually read data from the tag
264        {
265            ALOGD ("%s: read %u bytes", __FUNCTION__, sReadDataLen);
266            buf = e->NewByteArray (sReadDataLen);
267            e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
268        }
269    }
270    else
271    {
272        ALOGD ("%s: create empty buffer", __FUNCTION__);
273        sReadDataLen = 0;
274        sReadData = (uint8_t*) malloc (1);
275        buf = e->NewByteArray (sReadDataLen);
276        e->SetByteArrayRegion (buf, 0, sReadDataLen, (jbyte*) sReadData);
277    }
278
279    if (sReadData)
280    {
281        free (sReadData);
282        sReadData = NULL;
283    }
284    sReadDataLen = 0;
285
286    ALOGD ("%s: exit", __FUNCTION__);
287    return buf;
288}
289
290
291/*******************************************************************************
292**
293** Function:        nativeNfcTag_doWriteStatus
294**
295** Description:     Receive the completion status of write operation.  Called
296**                  by NFA_WRITE_CPLT_EVT.
297**                  isWriteOk: Status of operation.
298**
299** Returns:         None
300**
301*******************************************************************************/
302void nativeNfcTag_doWriteStatus (jboolean isWriteOk)
303{
304    if (sWriteWaitingForComplete != JNI_FALSE)
305    {
306        sWriteWaitingForComplete = JNI_FALSE;
307        sWriteOk = isWriteOk;
308        sem_post (&sWriteSem);
309    }
310}
311
312
313/*******************************************************************************
314**
315** Function:        nativeNfcTag_formatStatus
316**
317** Description:     Receive the completion status of format operation.  Called
318**                  by NFA_FORMAT_CPLT_EVT.
319**                  isOk: Status of operation.
320**
321** Returns:         None
322**
323*******************************************************************************/
324void nativeNfcTag_formatStatus (bool isOk)
325{
326    sFormatOk = isOk;
327    sem_post (&sFormatSem);
328}
329
330
331/*******************************************************************************
332**
333** Function:        nativeNfcTag_doWrite
334**
335** Description:     Write a NDEF message to the tag.
336**                  e: JVM environment.
337**                  o: Java object.
338**                  buf: Contains a NDEF message.
339**
340** Returns:         True if ok.
341**
342*******************************************************************************/
343static jboolean nativeNfcTag_doWrite (JNIEnv* e, jobject, jbyteArray buf)
344{
345    jboolean result = JNI_FALSE;
346    tNFA_STATUS status = 0;
347    const int maxBufferSize = 1024;
348    UINT8 buffer[maxBufferSize] = { 0 };
349    UINT32 curDataSize = 0;
350
351    ScopedByteArrayRO bytes(e, buf);
352    UINT8* p_data = const_cast<UINT8*>(reinterpret_cast<const UINT8*>(&bytes[0])); // TODO: const-ness API bug in NFA_RwWriteNDef!
353
354    ALOGD ("%s: enter; len = %zu", __FUNCTION__, bytes.size());
355
356    /* Create the write semaphore */
357    if (sem_init (&sWriteSem, 0, 0) == -1)
358    {
359        ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
360        return JNI_FALSE;
361    }
362
363    sWriteWaitingForComplete = JNI_TRUE;
364    if (sCheckNdefStatus == NFA_STATUS_FAILED)
365    {
366        //if tag does not contain a NDEF message
367        //and tag is capable of storing NDEF message
368        if (sCheckNdefCapable)
369        {
370            ALOGD ("%s: try format", __FUNCTION__);
371            sem_init (&sFormatSem, 0, 0);
372            sFormatOk = false;
373            status = NFA_RwFormatTag ();
374            sem_wait (&sFormatSem);
375            sem_destroy (&sFormatSem);
376            if (sFormatOk == false) //if format operation failed
377                goto TheEnd;
378        }
379        ALOGD ("%s: try write", __FUNCTION__);
380        status = NFA_RwWriteNDef (p_data, bytes.size());
381    }
382    else if (bytes.size() == 0)
383    {
384        //if (NXP TagWriter wants to erase tag) then create and write an empty ndef message
385        NDEF_MsgInit (buffer, maxBufferSize, &curDataSize);
386        status = NDEF_MsgAddRec (buffer, maxBufferSize, &curDataSize, NDEF_TNF_EMPTY, NULL, 0, NULL, 0, NULL, 0);
387        ALOGD ("%s: create empty ndef msg; status=%u; size=%lu", __FUNCTION__, status, curDataSize);
388        status = NFA_RwWriteNDef (buffer, curDataSize);
389    }
390    else
391    {
392        ALOGD ("%s: NFA_RwWriteNDef", __FUNCTION__);
393        status = NFA_RwWriteNDef (p_data, bytes.size());
394    }
395
396    if (status != NFA_STATUS_OK)
397    {
398        ALOGE ("%s: write/format error=%d", __FUNCTION__, status);
399        goto TheEnd;
400    }
401
402    /* Wait for write completion status */
403    sWriteOk = false;
404    if (sem_wait (&sWriteSem))
405    {
406        ALOGE ("%s: wait semaphore (errno=0x%08x)", __FUNCTION__, errno);
407        goto TheEnd;
408    }
409
410    result = sWriteOk;
411
412TheEnd:
413    /* Destroy semaphore */
414    if (sem_destroy (&sWriteSem))
415    {
416        ALOGE ("%s: failed destroy semaphore (errno=0x%08x)", __FUNCTION__, errno);
417    }
418    sWriteWaitingForComplete = JNI_FALSE;
419    ALOGD ("%s: exit; result=%d", __FUNCTION__, result);
420    return result;
421}
422
423
424/*******************************************************************************
425**
426** Function:        nativeNfcTag_doConnectStatus
427**
428** Description:     Receive the completion status of connect operation.
429**                  isConnectOk: Status of the operation.
430**
431** Returns:         None
432**
433*******************************************************************************/
434void nativeNfcTag_doConnectStatus (jboolean isConnectOk)
435{
436    if (sConnectWaitingForComplete != JNI_FALSE)
437    {
438        sConnectWaitingForComplete = JNI_FALSE;
439        sConnectOk = isConnectOk;
440        SyncEventGuard g (sReconnectEvent);
441        sReconnectEvent.notifyOne ();
442    }
443}
444
445
446/*******************************************************************************
447**
448** Function:        nativeNfcTag_doDeactivateStatus
449**
450** Description:     Receive the completion status of deactivate operation.
451**
452** Returns:         None
453**
454*******************************************************************************/
455void nativeNfcTag_doDeactivateStatus (int status)
456{
457    sGotDeactivate = (status == 0);
458
459    SyncEventGuard g (sReconnectEvent);
460    sReconnectEvent.notifyOne ();
461}
462
463
464/*******************************************************************************
465**
466** Function:        nativeNfcTag_doConnect
467**
468** Description:     Connect to the tag in RF field.
469**                  e: JVM environment.
470**                  o: Java object.
471**                  targetHandle: Handle of the tag.
472**
473** Returns:         Must return NXP status code, which NFC service expects.
474**
475*******************************************************************************/
476static jint nativeNfcTag_doConnect (JNIEnv*, jobject, jint targetHandle)
477{
478    ALOGD ("%s: targetHandle = %d", __FUNCTION__, targetHandle);
479    int i = targetHandle;
480    NfcTag& natTag = NfcTag::getInstance ();
481    int retCode = NFCSTATUS_SUCCESS;
482
483    if (i >= NfcTag::MAX_NUM_TECHNOLOGY)
484    {
485        ALOGE ("%s: Handle not found", __FUNCTION__);
486        retCode = NFCSTATUS_FAILED;
487        goto TheEnd;
488    }
489
490    if (natTag.getActivationState() != NfcTag::Active)
491    {
492        ALOGE ("%s: tag already deactivated", __FUNCTION__);
493        retCode = NFCSTATUS_FAILED;
494        goto TheEnd;
495    }
496
497    sCurrentConnectedTargetType = natTag.mTechList[i];
498    if (natTag.mTechLibNfcTypes[i] != NFC_PROTOCOL_ISO_DEP)
499    {
500        ALOGD ("%s() Nfc type = %d, do nothing for non ISO_DEP", __FUNCTION__, natTag.mTechLibNfcTypes[i]);
501        retCode = NFCSTATUS_SUCCESS;
502        goto TheEnd;
503    }
504
505    if (natTag.mTechList[i] == TARGET_TYPE_ISO14443_3A || natTag.mTechList[i] == TARGET_TYPE_ISO14443_3B)
506    {
507        ALOGD ("%s: switching to tech: %d need to switch rf intf to frame", __FUNCTION__, natTag.mTechList[i]);
508        retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
509    }
510    else
511    {
512        retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
513    }
514
515TheEnd:
516    ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode);
517    return retCode;
518}
519
520/*******************************************************************************
521**
522** Function:        reSelect
523**
524** Description:     Deactivates the tag and re-selects it with the specified
525**                  rf interface.
526**
527** Returns:         status code, 0 on success, 1 on failure,
528**                  146 (defined in service) on tag lost
529**
530*******************************************************************************/
531static int reSelect (tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded)
532{
533    ALOGD ("%s: enter; rf intf = %d, current intf = %d", __FUNCTION__, rfInterface, sCurrentRfInterface);
534
535    sRfInterfaceMutex.lock ();
536
537    if (fSwitchIfNeeded && (rfInterface == sCurrentRfInterface))
538    {
539        // already in the requested interface
540        sRfInterfaceMutex.unlock ();
541        return 0;   // success
542    }
543
544    NfcTag& natTag = NfcTag::getInstance ();
545
546    tNFA_STATUS status;
547    int rVal = 1;
548
549    do
550    {
551        //if tag has shutdown, abort this method
552        if (NfcTag::getInstance ().isNdefDetectionTimedOut())
553        {
554            ALOGD ("%s: ndef detection timeout; break", __FUNCTION__);
555            rVal = STATUS_CODE_TARGET_LOST;
556            break;
557        }
558
559        {
560            SyncEventGuard g (sReconnectEvent);
561            gIsTagDeactivating = true;
562            sGotDeactivate = false;
563            ALOGD ("%s: deactivate to sleep", __FUNCTION__);
564            if (NFA_STATUS_OK != (status = NFA_Deactivate (TRUE))) //deactivate to sleep state
565            {
566                ALOGE ("%s: deactivate failed, status = %d", __FUNCTION__, status);
567                break;
568            }
569
570            if (sReconnectEvent.wait (1000) == false) //if timeout occurred
571            {
572                ALOGE ("%s: timeout waiting for deactivate", __FUNCTION__);
573            }
574        }
575
576        if (!sGotDeactivate)
577        {
578            rVal = STATUS_CODE_TARGET_LOST;
579            break;
580        }
581
582        if (NfcTag::getInstance ().getActivationState () != NfcTag::Sleep)
583        {
584            ALOGE ("%s: tag is not in sleep", __FUNCTION__);
585            rVal = STATUS_CODE_TARGET_LOST;
586            break;
587        }
588
589        gIsTagDeactivating = false;
590
591        {
592            SyncEventGuard g2 (sReconnectEvent);
593
594            sConnectWaitingForComplete = JNI_TRUE;
595            ALOGD ("%s: select interface %u", __FUNCTION__, rfInterface);
596            gIsSelectingRfInterface = true;
597            if (NFA_STATUS_OK != (status = NFA_Select (natTag.mTechHandles[0], natTag.mTechLibNfcTypes[0], rfInterface)))
598            {
599                ALOGE ("%s: NFA_Select failed, status = %d", __FUNCTION__, status);
600                break;
601            }
602
603            sConnectOk = false;
604            if (sReconnectEvent.wait (1000) == false) //if timeout occured
605            {
606                ALOGE ("%s: timeout waiting for select", __FUNCTION__);
607                break;
608            }
609        }
610
611        ALOGD("%s: select completed; sConnectOk=%d", __FUNCTION__, sConnectOk);
612        if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
613        {
614            ALOGE("%s: tag is not active", __FUNCTION__);
615            rVal = STATUS_CODE_TARGET_LOST;
616            break;
617        }
618        if (sConnectOk)
619        {
620            rVal = 0;   // success
621            sCurrentRfInterface = rfInterface;
622        }
623        else
624        {
625            rVal = 1;
626        }
627    } while (0);
628
629    sConnectWaitingForComplete = JNI_FALSE;
630    gIsTagDeactivating = false;
631    gIsSelectingRfInterface = false;
632    sRfInterfaceMutex.unlock ();
633    ALOGD ("%s: exit; status=%d", __FUNCTION__, rVal);
634    return rVal;
635}
636
637/*******************************************************************************
638**
639** Function:        switchRfInterface
640**
641** Description:     Switch controller's RF interface to frame, ISO-DEP, or NFC-DEP.
642**                  rfInterface: Type of RF interface.
643**
644** Returns:         True if ok.
645**
646*******************************************************************************/
647static bool switchRfInterface (tNFA_INTF_TYPE rfInterface)
648{
649    NfcTag& natTag = NfcTag::getInstance ();
650
651    if (natTag.mTechLibNfcTypes[0] != NFC_PROTOCOL_ISO_DEP)
652    {
653        ALOGD ("%s: protocol: %d not ISO_DEP, do nothing", __FUNCTION__, natTag.mTechLibNfcTypes[0]);
654        return true;
655    }
656
657    ALOGD ("%s: new rf intf = %d, cur rf intf = %d", __FUNCTION__, rfInterface, sCurrentRfInterface);
658
659    return (0 == reSelect(rfInterface, true));
660}
661
662
663/*******************************************************************************
664**
665** Function:        nativeNfcTag_doReconnect
666**
667** Description:     Re-connect to the tag in RF field.
668**                  e: JVM environment.
669**                  o: Java object.
670**
671** Returns:         Status code.
672**
673*******************************************************************************/
674static jint nativeNfcTag_doReconnect (JNIEnv*, jobject)
675{
676    ALOGD ("%s: enter", __FUNCTION__);
677    int retCode = NFCSTATUS_SUCCESS;
678    NfcTag& natTag = NfcTag::getInstance ();
679
680    if (natTag.getActivationState() != NfcTag::Active)
681    {
682        ALOGE ("%s: tag already deactivated", __FUNCTION__);
683        retCode = NFCSTATUS_FAILED;
684        goto TheEnd;
685    }
686
687    // special case for Kovio
688    if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE)
689    {
690        ALOGD ("%s: fake out reconnect for Kovio", __FUNCTION__);
691        goto TheEnd;
692    }
693
694     // this is only supported for type 2 or 4 (ISO_DEP) tags
695    if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_ISO_DEP)
696        retCode = reSelect(NFA_INTERFACE_ISO_DEP, false);
697    else if (natTag.mTechLibNfcTypes[0] == NFA_PROTOCOL_T2T)
698        retCode = reSelect(NFA_INTERFACE_FRAME, false);
699
700TheEnd:
701    ALOGD ("%s: exit 0x%X", __FUNCTION__, retCode);
702    return retCode;
703}
704
705
706/*******************************************************************************
707**
708** Function:        nativeNfcTag_doHandleReconnect
709**
710** Description:     Re-connect to the tag in RF field.
711**                  e: JVM environment.
712**                  o: Java object.
713**                  targetHandle: Handle of the tag.
714**
715** Returns:         Status code.
716**
717*******************************************************************************/
718static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHandle)
719{
720    ALOGD ("%s: targetHandle = %d", __FUNCTION__, targetHandle);
721    return nativeNfcTag_doConnect (e, o, targetHandle);
722}
723
724
725/*******************************************************************************
726**
727** Function:        nativeNfcTag_doDisconnect
728**
729** Description:     Deactivate the RF field.
730**                  e: JVM environment.
731**                  o: Java object.
732**
733** Returns:         True if ok.
734**
735*******************************************************************************/
736static jboolean nativeNfcTag_doDisconnect (JNIEnv*, jobject)
737{
738    ALOGD ("%s: enter", __FUNCTION__);
739    tNFA_STATUS nfaStat = NFA_STATUS_OK;
740
741    NfcTag::getInstance().resetAllTransceiveTimeouts ();
742
743    if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
744    {
745        ALOGE ("%s: tag already deactivated", __FUNCTION__);
746        goto TheEnd;
747    }
748
749    nfaStat = NFA_Deactivate (FALSE);
750    if (nfaStat != NFA_STATUS_OK)
751        ALOGE ("%s: deactivate failed; error=0x%X", __FUNCTION__, nfaStat);
752
753TheEnd:
754    ALOGD ("%s: exit", __FUNCTION__);
755    return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
756}
757
758
759/*******************************************************************************
760**
761** Function:        nativeNfcTag_doTransceiveStatus
762**
763** Description:     Receive the completion status of transceive operation.
764**                  status: operation status.
765**                  buf: Contains tag's response.
766**                  bufLen: Length of buffer.
767**
768** Returns:         None
769**
770*******************************************************************************/
771void nativeNfcTag_doTransceiveStatus (tNFA_STATUS status, uint8_t* buf, uint32_t bufLen)
772{
773    SyncEventGuard g (sTransceiveEvent);
774    ALOGD ("%s: data len=%d", __FUNCTION__, bufLen);
775    if (!sWaitingForTransceive)
776    {
777        ALOGE ("%s: drop data", __FUNCTION__);
778        return;
779    }
780    sRxDataStatus = status;
781    if (sRxDataStatus == NFA_STATUS_OK || sRxDataStatus == NFA_STATUS_CONTINUE)
782        sRxDataBuffer.append (buf, bufLen);
783
784    if (sRxDataStatus == NFA_STATUS_OK)
785        sTransceiveEvent.notifyOne ();
786}
787
788
789void nativeNfcTag_notifyRfTimeout ()
790{
791    SyncEventGuard g (sTransceiveEvent);
792    ALOGD ("%s: waiting for transceive: %d", __FUNCTION__, sWaitingForTransceive);
793    if (!sWaitingForTransceive)
794        return;
795
796    sTransceiveRfTimeout = true;
797
798    sTransceiveEvent.notifyOne ();
799}
800
801
802/*******************************************************************************
803**
804** Function:        nativeNfcTag_doTransceive
805**
806** Description:     Send raw data to the tag; receive tag's response.
807**                  e: JVM environment.
808**                  o: Java object.
809**                  raw: Not used.
810**                  statusTargetLost: Whether tag responds or times out.
811**
812** Returns:         Response from tag.
813**
814*******************************************************************************/
815static jbyteArray nativeNfcTag_doTransceive (JNIEnv* e, jobject, jbyteArray data, jboolean raw, jintArray statusTargetLost)
816{
817    int timeout = NfcTag::getInstance ().getTransceiveTimeout (sCurrentConnectedTargetType);
818    ALOGD ("%s: enter; raw=%u; timeout = %d", __FUNCTION__, raw, timeout);
819    bool waitOk = false;
820    bool isNack = false;
821    jint *targetLost = NULL;
822
823    if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
824    {
825        if (statusTargetLost)
826        {
827            targetLost = e->GetIntArrayElements (statusTargetLost, 0);
828            if (targetLost)
829                *targetLost = 1; //causes NFC service to throw TagLostException
830            e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
831        }
832        ALOGD ("%s: tag not active", __FUNCTION__);
833        return NULL;
834    }
835
836    NfcTag& natTag = NfcTag::getInstance ();
837
838    // get input buffer and length from java call
839    ScopedByteArrayRO bytes(e, data);
840    uint8_t* buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0])); // TODO: API bug; NFA_SendRawFrame should take const*!
841    size_t bufLen = bytes.size();
842
843    if (statusTargetLost)
844    {
845        targetLost = e->GetIntArrayElements (statusTargetLost, 0);
846        if (targetLost)
847            *targetLost = 0; //success, tag is still present
848    }
849
850    sSwitchBackTimer.kill ();
851    ScopedLocalRef<jbyteArray> result(e, NULL);
852    do
853    {
854        {
855            SyncEventGuard g (sTransceiveEvent);
856            sTransceiveRfTimeout = false;
857            sWaitingForTransceive = true;
858            sRxDataStatus = NFA_STATUS_OK;
859            sRxDataBuffer.clear ();
860            tNFA_STATUS status = NFA_SendRawFrame (buf, bufLen,
861                    NFA_DM_DEFAULT_PRESENCE_CHECK_START_DELAY);
862            if (status != NFA_STATUS_OK)
863            {
864                ALOGE ("%s: fail send; error=%d", __FUNCTION__, status);
865                break;
866            }
867            waitOk = sTransceiveEvent.wait (timeout);
868        }
869
870        if (waitOk == false || sTransceiveRfTimeout) //if timeout occurred
871        {
872            ALOGE ("%s: wait response timeout", __FUNCTION__);
873            if (targetLost)
874                *targetLost = 1; //causes NFC service to throw TagLostException
875            break;
876        }
877
878        if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
879        {
880            ALOGE ("%s: already deactivated", __FUNCTION__);
881            if (targetLost)
882                *targetLost = 1; //causes NFC service to throw TagLostException
883            break;
884        }
885
886        ALOGD ("%s: response %d bytes", __FUNCTION__, sRxDataBuffer.size());
887
888        if ((natTag.getProtocol () == NFA_PROTOCOL_T2T) &&
889            natTag.isT2tNackResponse (sRxDataBuffer.data(), sRxDataBuffer.size()))
890        {
891            isNack = true;
892        }
893
894        if (sRxDataBuffer.size() > 0)
895        {
896            if (isNack)
897            {
898                //Some Mifare Ultralight C tags enter the HALT state after it
899                //responds with a NACK.  Need to perform a "reconnect" operation
900                //to wake it.
901                ALOGD ("%s: try reconnect", __FUNCTION__);
902                nativeNfcTag_doReconnect (NULL, NULL);
903                ALOGD ("%s: reconnect finish", __FUNCTION__);
904            }
905            else
906            {
907                // marshall data to java for return
908                result.reset(e->NewByteArray(sRxDataBuffer.size()));
909                if (result.get() != NULL)
910                {
911                    e->SetByteArrayRegion(result.get(), 0, sRxDataBuffer.size(), (const jbyte *) sRxDataBuffer.data());
912                }
913                else
914                    ALOGE ("%s: Failed to allocate java byte array", __FUNCTION__);
915            } // else a nack is treated as a transceive failure to the upper layers
916
917            sRxDataBuffer.clear();
918        }
919    } while (0);
920
921    sWaitingForTransceive = false;
922    if (targetLost)
923        e->ReleaseIntArrayElements (statusTargetLost, targetLost, 0);
924
925    ALOGD ("%s: exit", __FUNCTION__);
926    return result.release();
927}
928
929
930/*******************************************************************************
931**
932** Function:        nativeNfcTag_doGetNdefType
933**
934** Description:     Retrieve the type of tag.
935**                  e: JVM environment.
936**                  o: Java object.
937**                  libnfcType: Type of tag represented by JNI.
938**                  javaType: Not used.
939**
940** Returns:         Type of tag represented by NFC Service.
941**
942*******************************************************************************/
943static jint nativeNfcTag_doGetNdefType (JNIEnv*, jobject, jint libnfcType, jint javaType)
944{
945    ALOGD ("%s: enter; libnfc type=%d; java type=%d", __FUNCTION__, libnfcType, javaType);
946    jint ndefType = NDEF_UNKNOWN_TYPE;
947
948    // For NFA, libnfcType is mapped to the protocol value received
949    // in the NFA_ACTIVATED_EVT and NFA_DISC_RESULT_EVT event.
950    switch (libnfcType) {
951    case NFA_PROTOCOL_T1T:
952        ndefType = NDEF_TYPE1_TAG;
953        break;
954    case NFA_PROTOCOL_T2T:
955        ndefType = NDEF_TYPE2_TAG;;
956        break;
957    case NFA_PROTOCOL_T3T:
958        ndefType = NDEF_TYPE3_TAG;
959        break;
960    case NFA_PROTOCOL_ISO_DEP:
961        ndefType = NDEF_TYPE4_TAG;
962        break;
963    case NFA_PROTOCOL_ISO15693:
964        ndefType = NDEF_UNKNOWN_TYPE;
965        break;
966    case NFA_PROTOCOL_INVALID:
967        ndefType = NDEF_UNKNOWN_TYPE;
968        break;
969    default:
970        ndefType = NDEF_UNKNOWN_TYPE;
971        break;
972    }
973    ALOGD ("%s: exit; ndef type=%d", __FUNCTION__, ndefType);
974    return ndefType;
975}
976
977
978/*******************************************************************************
979**
980** Function:        nativeNfcTag_doCheckNdefResult
981**
982** Description:     Receive the result of checking whether the tag contains a NDEF
983**                  message.  Called by the NFA_NDEF_DETECT_EVT.
984**                  status: Status of the operation.
985**                  maxSize: Maximum size of NDEF message.
986**                  currentSize: Current size of NDEF message.
987**                  flags: Indicate various states.
988**
989** Returns:         None
990**
991*******************************************************************************/
992void nativeNfcTag_doCheckNdefResult (tNFA_STATUS status, uint32_t maxSize, uint32_t currentSize, uint8_t flags)
993{
994    //this function's flags parameter is defined using the following macros
995    //in nfc/include/rw_api.h;
996    //#define RW_NDEF_FL_READ_ONLY  0x01    /* Tag is read only              */
997    //#define RW_NDEF_FL_FORMATED   0x02    /* Tag formated for NDEF         */
998    //#define RW_NDEF_FL_SUPPORTED  0x04    /* NDEF supported by the tag     */
999    //#define RW_NDEF_FL_UNKNOWN    0x08    /* Unable to find if tag is ndef capable/formated/read only */
1000    //#define RW_NDEF_FL_FORMATABLE 0x10    /* Tag supports format operation */
1001
1002    if (!sCheckNdefWaitingForComplete)
1003    {
1004        ALOGE ("%s: not waiting", __FUNCTION__);
1005        return;
1006    }
1007
1008    if (flags & RW_NDEF_FL_READ_ONLY)
1009        ALOGD ("%s: flag read-only", __FUNCTION__);
1010    if (flags & RW_NDEF_FL_FORMATED)
1011        ALOGD ("%s: flag formatted for ndef", __FUNCTION__);
1012    if (flags & RW_NDEF_FL_SUPPORTED)
1013        ALOGD ("%s: flag ndef supported", __FUNCTION__);
1014    if (flags & RW_NDEF_FL_UNKNOWN)
1015        ALOGD ("%s: flag all unknown", __FUNCTION__);
1016    if (flags & RW_NDEF_FL_FORMATABLE)
1017        ALOGD ("%s: flag formattable", __FUNCTION__);
1018
1019    sCheckNdefWaitingForComplete = JNI_FALSE;
1020    sCheckNdefStatus = status;
1021    if (sCheckNdefStatus != NFA_STATUS_OK && sCheckNdefStatus != NFA_STATUS_TIMEOUT)
1022        sCheckNdefStatus = NFA_STATUS_FAILED;
1023    sCheckNdefCapable = false; //assume tag is NOT ndef capable
1024    if (sCheckNdefStatus == NFA_STATUS_OK)
1025    {
1026        //NDEF content is on the tag
1027        sCheckNdefMaxSize = maxSize;
1028        sCheckNdefCurrentSize = currentSize;
1029        sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1030        sCheckNdefCapable = true;
1031    }
1032    else if (sCheckNdefStatus == NFA_STATUS_FAILED)
1033    {
1034        //no NDEF content on the tag
1035        sCheckNdefMaxSize = 0;
1036        sCheckNdefCurrentSize = 0;
1037        sCheckNdefCardReadOnly = flags & RW_NDEF_FL_READ_ONLY;
1038        if ((flags & RW_NDEF_FL_UNKNOWN) == 0) //if stack understands the tag
1039        {
1040            if (flags & RW_NDEF_FL_SUPPORTED) //if tag is ndef capable
1041                sCheckNdefCapable = true;
1042        }
1043    }
1044    else
1045    {
1046        ALOGE ("%s: unknown status=0x%X", __FUNCTION__, status);
1047        sCheckNdefMaxSize = 0;
1048        sCheckNdefCurrentSize = 0;
1049        sCheckNdefCardReadOnly = false;
1050    }
1051    sem_post (&sCheckNdefSem);
1052}
1053
1054
1055/*******************************************************************************
1056**
1057** Function:        nativeNfcTag_doCheckNdef
1058**
1059** Description:     Does the tag contain a NDEF message?
1060**                  e: JVM environment.
1061**                  o: Java object.
1062**                  ndefInfo: NDEF info.
1063**
1064** Returns:         Status code; 0 is success.
1065**
1066*******************************************************************************/
1067static jint nativeNfcTag_doCheckNdef (JNIEnv* e, jobject, jintArray ndefInfo)
1068{
1069    tNFA_STATUS status = NFA_STATUS_FAILED;
1070    jint* ndef = NULL;
1071
1072    ALOGD ("%s: enter", __FUNCTION__);
1073
1074    // special case for Kovio
1075    if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE)
1076    {
1077        ALOGD ("%s: Kovio tag, no NDEF", __FUNCTION__);
1078        ndef = e->GetIntArrayElements (ndefInfo, 0);
1079        ndef[0] = 0;
1080        ndef[1] = NDEF_MODE_READ_ONLY;
1081        e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
1082        return NFA_STATUS_FAILED;
1083    }
1084
1085    /* Create the write semaphore */
1086    if (sem_init (&sCheckNdefSem, 0, 0) == -1)
1087    {
1088        ALOGE ("%s: Check NDEF semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
1089        return JNI_FALSE;
1090    }
1091
1092    if (NfcTag::getInstance ().getActivationState () != NfcTag::Active)
1093    {
1094        ALOGE ("%s: tag already deactivated", __FUNCTION__);
1095        goto TheEnd;
1096    }
1097
1098    ALOGD ("%s: try NFA_RwDetectNDef", __FUNCTION__);
1099    sCheckNdefWaitingForComplete = JNI_TRUE;
1100    status = NFA_RwDetectNDef ();
1101
1102    if (status != NFA_STATUS_OK)
1103    {
1104        ALOGE ("%s: NFA_RwDetectNDef failed, status = 0x%X", __FUNCTION__, status);
1105        goto TheEnd;
1106    }
1107
1108    /* Wait for check NDEF completion status */
1109    if (sem_wait (&sCheckNdefSem))
1110    {
1111        ALOGE ("%s: Failed to wait for check NDEF semaphore (errno=0x%08x)", __FUNCTION__, errno);
1112        goto TheEnd;
1113    }
1114
1115    if (sCheckNdefStatus == NFA_STATUS_OK)
1116    {
1117        //stack found a NDEF message on the tag
1118        ndef = e->GetIntArrayElements (ndefInfo, 0);
1119        if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
1120            ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
1121        else
1122            ndef[0] = sCheckNdefMaxSize;
1123        if (sCheckNdefCardReadOnly)
1124            ndef[1] = NDEF_MODE_READ_ONLY;
1125        else
1126            ndef[1] = NDEF_MODE_READ_WRITE;
1127        e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
1128        status = NFA_STATUS_OK;
1129    }
1130    else if (sCheckNdefStatus == NFA_STATUS_FAILED)
1131    {
1132        //stack did not find a NDEF message on the tag;
1133        ndef = e->GetIntArrayElements (ndefInfo, 0);
1134        if (NfcTag::getInstance ().getProtocol () == NFA_PROTOCOL_T1T)
1135            ndef[0] = NfcTag::getInstance ().getT1tMaxMessageSize ();
1136        else
1137            ndef[0] = sCheckNdefMaxSize;
1138        if (sCheckNdefCardReadOnly)
1139            ndef[1] = NDEF_MODE_READ_ONLY;
1140        else
1141            ndef[1] = NDEF_MODE_READ_WRITE;
1142        e->ReleaseIntArrayElements (ndefInfo, ndef, 0);
1143        status = NFA_STATUS_FAILED;
1144    }
1145    else if ((sCheckNdefStatus == NFA_STATUS_TIMEOUT) && (NfcTag::getInstance ().getProtocol() == NFC_PROTOCOL_ISO_DEP))
1146    {
1147        pn544InteropStopPolling ();
1148        status = sCheckNdefStatus;
1149    }
1150    else
1151    {
1152        ALOGD ("%s: unknown status 0x%X", __FUNCTION__, sCheckNdefStatus);
1153        status = sCheckNdefStatus;
1154    }
1155
1156TheEnd:
1157    /* Destroy semaphore */
1158    if (sem_destroy (&sCheckNdefSem))
1159    {
1160        ALOGE ("%s: Failed to destroy check NDEF semaphore (errno=0x%08x)", __FUNCTION__, errno);
1161    }
1162    sCheckNdefWaitingForComplete = JNI_FALSE;
1163    ALOGD ("%s: exit; status=0x%X", __FUNCTION__, status);
1164    return status;
1165}
1166
1167
1168/*******************************************************************************
1169**
1170** Function:        nativeNfcTag_resetPresenceCheck
1171**
1172** Description:     Reset variables related to presence-check.
1173**
1174** Returns:         None
1175**
1176*******************************************************************************/
1177void nativeNfcTag_resetPresenceCheck ()
1178{
1179    sIsTagPresent = true;
1180}
1181
1182
1183/*******************************************************************************
1184**
1185** Function:        nativeNfcTag_doPresenceCheckResult
1186**
1187** Description:     Receive the result of presence-check.
1188**                  status: Result of presence-check.
1189**
1190** Returns:         None
1191**
1192*******************************************************************************/
1193void nativeNfcTag_doPresenceCheckResult (tNFA_STATUS status)
1194{
1195    SyncEventGuard guard (sPresenceCheckEvent);
1196    sIsTagPresent = status == NFA_STATUS_OK;
1197    sPresenceCheckEvent.notifyOne ();
1198}
1199
1200
1201/*******************************************************************************
1202**
1203** Function:        nativeNfcTag_doPresenceCheck
1204**
1205** Description:     Check if the tag is in the RF field.
1206**                  e: JVM environment.
1207**                  o: Java object.
1208**
1209** Returns:         True if tag is in RF field.
1210**
1211*******************************************************************************/
1212static jboolean nativeNfcTag_doPresenceCheck (JNIEnv*, jobject)
1213{
1214    ALOGD ("%s", __FUNCTION__);
1215    tNFA_STATUS status = NFA_STATUS_OK;
1216    jboolean isPresent = JNI_FALSE;
1217
1218    // Special case for Kovio.  The deactivation would have already occurred
1219    // but was ignored so that normal tag opertions could complete.  Now we
1220    // want to process as if the deactivate just happened.
1221    if (NfcTag::getInstance ().mTechList [0] == TARGET_TYPE_KOVIO_BARCODE)
1222    {
1223        ALOGD ("%s: Kovio, force deactivate handling", __FUNCTION__);
1224        tNFA_DEACTIVATED deactivated = {NFA_DEACTIVATE_TYPE_IDLE};
1225        {
1226            SyncEventGuard g (gDeactivatedEvent);
1227            gActivated = false; //guard this variable from multi-threaded access
1228            gDeactivatedEvent.notifyOne ();
1229        }
1230
1231        NfcTag::getInstance().setDeactivationState (deactivated);
1232        nativeNfcTag_resetPresenceCheck();
1233        NfcTag::getInstance().connectionEventHandler (NFA_DEACTIVATED_EVT, NULL);
1234        nativeNfcTag_abortWaits();
1235        NfcTag::getInstance().abort ();
1236
1237        return JNI_FALSE;
1238    }
1239
1240    if (nfcManager_isNfcActive() == false)
1241    {
1242        ALOGD ("%s: NFC is no longer active.", __FUNCTION__);
1243        return JNI_FALSE;
1244    }
1245
1246    if (!sRfInterfaceMutex.tryLock())
1247    {
1248        ALOGD ("%s: tag is being reSelected assume it is present", __FUNCTION__);
1249        return JNI_TRUE;
1250    }
1251
1252    sRfInterfaceMutex.unlock();
1253
1254    if (NfcTag::getInstance ().isActivated () == false)
1255    {
1256        ALOGD ("%s: tag already deactivated", __FUNCTION__);
1257        return JNI_FALSE;
1258    }
1259
1260    {
1261        SyncEventGuard guard (sPresenceCheckEvent);
1262        status = NFA_RwPresenceCheck (NfcTag::getInstance().getPresenceCheckAlgorithm());
1263        if (status == NFA_STATUS_OK)
1264        {
1265            sPresenceCheckEvent.wait ();
1266            isPresent = sIsTagPresent ? JNI_TRUE : JNI_FALSE;
1267        }
1268    }
1269
1270    if (isPresent == JNI_FALSE)
1271        ALOGD ("%s: tag absent", __FUNCTION__);
1272    return isPresent;
1273}
1274
1275
1276/*******************************************************************************
1277**
1278** Function:        nativeNfcTag_doIsNdefFormatable
1279**
1280** Description:     Can tag be formatted to store NDEF message?
1281**                  e: JVM environment.
1282**                  o: Java object.
1283**                  libNfcType: Type of tag.
1284**                  uidBytes: Tag's unique ID.
1285**                  pollBytes: Data from activation.
1286**                  actBytes: Data from activation.
1287**
1288** Returns:         True if formattable.
1289**
1290*******************************************************************************/
1291static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv*,
1292        jobject, jint /*libNfcType*/, jbyteArray, jbyteArray,
1293        jbyteArray)
1294{
1295    jboolean isFormattable = JNI_FALSE;
1296
1297    switch (NfcTag::getInstance().getProtocol())
1298    {
1299    case NFA_PROTOCOL_T1T:
1300    case NFA_PROTOCOL_ISO15693:
1301        isFormattable = JNI_TRUE;
1302        break;
1303
1304    case NFA_PROTOCOL_T3T:
1305        isFormattable = NfcTag::getInstance().isFelicaLite() ? JNI_TRUE : JNI_FALSE;
1306        break;
1307
1308    case NFA_PROTOCOL_T2T:
1309        isFormattable = ( NfcTag::getInstance().isMifareUltralight() |
1310                          NfcTag::getInstance().isInfineonMyDMove() |
1311                          NfcTag::getInstance().isKovioType2Tag() )
1312                        ? JNI_TRUE : JNI_FALSE;
1313        break;
1314    }
1315    ALOGD("%s: is formattable=%u", __FUNCTION__, isFormattable);
1316    return isFormattable;
1317}
1318
1319
1320/*******************************************************************************
1321**
1322** Function:        nativeNfcTag_doIsIsoDepNdefFormatable
1323**
1324** Description:     Is ISO-DEP tag formattable?
1325**                  e: JVM environment.
1326**                  o: Java object.
1327**                  pollBytes: Data from activation.
1328**                  actBytes: Data from activation.
1329**
1330** Returns:         True if formattable.
1331**
1332*******************************************************************************/
1333static jboolean nativeNfcTag_doIsIsoDepNdefFormatable (JNIEnv *e, jobject o, jbyteArray pollBytes, jbyteArray actBytes)
1334{
1335    uint8_t uidFake[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
1336    ALOGD ("%s", __FUNCTION__);
1337    jbyteArray uidArray = e->NewByteArray (8);
1338    e->SetByteArrayRegion (uidArray, 0, 8, (jbyte*) uidFake);
1339    return nativeNfcTag_doIsNdefFormatable (e, o, 0, uidArray, pollBytes, actBytes);
1340}
1341
1342
1343/*******************************************************************************
1344**
1345** Function:        nativeNfcTag_doNdefFormat
1346**
1347** Description:     Format a tag so it can store NDEF message.
1348**                  e: JVM environment.
1349**                  o: Java object.
1350**                  key: Not used.
1351**
1352** Returns:         True if ok.
1353**
1354*******************************************************************************/
1355static jboolean nativeNfcTag_doNdefFormat (JNIEnv*, jobject, jbyteArray)
1356{
1357    ALOGD ("%s: enter", __FUNCTION__);
1358    tNFA_STATUS status = NFA_STATUS_OK;
1359
1360    // Do not try to format if tag is already deactivated.
1361    if (NfcTag::getInstance ().isActivated () == false)
1362    {
1363        ALOGD ("%s: tag already deactivated(no need to format)", __FUNCTION__);
1364        return JNI_FALSE;
1365    }
1366
1367    sem_init (&sFormatSem, 0, 0);
1368    sFormatOk = false;
1369    status = NFA_RwFormatTag ();
1370    if (status == NFA_STATUS_OK)
1371    {
1372        ALOGD ("%s: wait for completion", __FUNCTION__);
1373        sem_wait (&sFormatSem);
1374        status = sFormatOk ? NFA_STATUS_OK : NFA_STATUS_FAILED;
1375    }
1376    else
1377        ALOGE ("%s: error status=%u", __FUNCTION__, status);
1378    sem_destroy (&sFormatSem);
1379
1380    ALOGD ("%s: exit", __FUNCTION__);
1381    return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
1382}
1383
1384
1385/*******************************************************************************
1386**
1387** Function:        nativeNfcTag_doMakeReadonlyResult
1388**
1389** Description:     Receive the result of making a tag read-only. Called by the
1390**                  NFA_SET_TAG_RO_EVT.
1391**                  status: Status of the operation.
1392**
1393** Returns:         None
1394**
1395*******************************************************************************/
1396void nativeNfcTag_doMakeReadonlyResult (tNFA_STATUS status)
1397{
1398    if (sMakeReadonlyWaitingForComplete != JNI_FALSE)
1399    {
1400        sMakeReadonlyWaitingForComplete = JNI_FALSE;
1401        sMakeReadonlyStatus = status;
1402
1403        sem_post (&sMakeReadonlySem);
1404    }
1405}
1406
1407
1408/*******************************************************************************
1409**
1410** Function:        nativeNfcTag_doMakeReadonly
1411**
1412** Description:     Make the tag read-only.
1413**                  e: JVM environment.
1414**                  o: Java object.
1415**                  key: Key to access the tag.
1416**
1417** Returns:         True if ok.
1418**
1419*******************************************************************************/
1420static jboolean nativeNfcTag_doMakeReadonly (JNIEnv*, jobject, jbyteArray)
1421{
1422    jboolean result = JNI_FALSE;
1423    tNFA_STATUS status;
1424
1425    ALOGD ("%s", __FUNCTION__);
1426
1427    /* Create the make_readonly semaphore */
1428    if (sem_init (&sMakeReadonlySem, 0, 0) == -1)
1429    {
1430        ALOGE ("%s: Make readonly semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
1431        return JNI_FALSE;
1432    }
1433
1434    sMakeReadonlyWaitingForComplete = JNI_TRUE;
1435
1436    // Hard-lock the tag (cannot be reverted)
1437    status = NFA_RwSetTagReadOnly(TRUE);
1438    if (status == NFA_STATUS_REJECTED)
1439    {
1440        status = NFA_RwSetTagReadOnly (FALSE); //try soft lock
1441        if (status != NFA_STATUS_OK)
1442        {
1443            ALOGE ("%s: fail soft lock, status=%d", __FUNCTION__, status);
1444            goto TheEnd;
1445        }
1446    }
1447    else if (status != NFA_STATUS_OK)
1448    {
1449        ALOGE ("%s: fail hard lock, status=%d", __FUNCTION__, status);
1450        goto TheEnd;
1451    }
1452
1453    /* Wait for check NDEF completion status */
1454    if (sem_wait (&sMakeReadonlySem))
1455    {
1456        ALOGE ("%s: Failed to wait for make_readonly semaphore (errno=0x%08x)", __FUNCTION__, errno);
1457        goto TheEnd;
1458    }
1459
1460    if (sMakeReadonlyStatus == NFA_STATUS_OK)
1461    {
1462        result = JNI_TRUE;
1463    }
1464
1465TheEnd:
1466    /* Destroy semaphore */
1467    if (sem_destroy (&sMakeReadonlySem))
1468    {
1469        ALOGE ("%s: Failed to destroy read_only semaphore (errno=0x%08x)", __FUNCTION__, errno);
1470    }
1471    sMakeReadonlyWaitingForComplete = JNI_FALSE;
1472    return result;
1473}
1474
1475
1476/*******************************************************************************
1477**
1478** Function:        nativeNfcTag_registerNdefTypeHandler
1479**
1480** Description:     Register a callback to receive NDEF message from the tag
1481**                  from the NFA_NDEF_DATA_EVT.
1482**
1483** Returns:         None
1484**
1485*******************************************************************************/
1486//register a callback to receive NDEF message from the tag
1487//from the NFA_NDEF_DATA_EVT;
1488void nativeNfcTag_registerNdefTypeHandler ()
1489{
1490    ALOGD ("%s", __FUNCTION__);
1491    sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1492    NFA_RegisterNDefTypeHandler (TRUE, NFA_TNF_DEFAULT, (UINT8 *) "", 0, ndefHandlerCallback);
1493}
1494
1495
1496/*******************************************************************************
1497**
1498** Function:        nativeNfcTag_deregisterNdefTypeHandler
1499**
1500** Description:     No longer need to receive NDEF message from the tag.
1501**
1502** Returns:         None
1503**
1504*******************************************************************************/
1505void nativeNfcTag_deregisterNdefTypeHandler ()
1506{
1507    ALOGD ("%s", __FUNCTION__);
1508    NFA_DeregisterNDefTypeHandler (sNdefTypeHandlerHandle);
1509    sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
1510}
1511
1512
1513/*****************************************************************************
1514**
1515** JNI functions for Android 4.0.3
1516**
1517*****************************************************************************/
1518static JNINativeMethod gMethods[] =
1519{
1520   {"doConnect", "(I)I", (void *)nativeNfcTag_doConnect},
1521   {"doDisconnect", "()Z", (void *)nativeNfcTag_doDisconnect},
1522   {"doReconnect", "()I", (void *)nativeNfcTag_doReconnect},
1523   {"doHandleReconnect", "(I)I", (void *)nativeNfcTag_doHandleReconnect},
1524   {"doTransceive", "([BZ[I)[B", (void *)nativeNfcTag_doTransceive},
1525   {"doGetNdefType", "(II)I", (void *)nativeNfcTag_doGetNdefType},
1526   {"doCheckNdef", "([I)I", (void *)nativeNfcTag_doCheckNdef},
1527   {"doRead", "()[B", (void *)nativeNfcTag_doRead},
1528   {"doWrite", "([B)Z", (void *)nativeNfcTag_doWrite},
1529   {"doPresenceCheck", "()Z", (void *)nativeNfcTag_doPresenceCheck},
1530   {"doIsIsoDepNdefFormatable", "([B[B)Z", (void *)nativeNfcTag_doIsIsoDepNdefFormatable},
1531   {"doNdefFormat", "([B)Z", (void *)nativeNfcTag_doNdefFormat},
1532   {"doMakeReadonly", "([B)Z", (void *)nativeNfcTag_doMakeReadonly},
1533};
1534
1535
1536/*******************************************************************************
1537**
1538** Function:        register_com_android_nfc_NativeNfcTag
1539**
1540** Description:     Regisgter JNI functions with Java Virtual Machine.
1541**                  e: Environment of JVM.
1542**
1543** Returns:         Status of registration.
1544**
1545*******************************************************************************/
1546int register_com_android_nfc_NativeNfcTag (JNIEnv *e)
1547{
1548    ALOGD ("%s", __FUNCTION__);
1549    return jniRegisterNativeMethods (e, gNativeNfcTagClassName, gMethods, NELEM (gMethods));
1550}
1551
1552
1553} /* namespace android */
1554