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