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 #include <string>
     32 
     33 extern "C"
     34 {
     35     #include "nfa_api.h"
     36     #include "nfa_rw_api.h"
     37     #include "ndef_utils.h"
     38     #include "rw_api.h"
     39 }
     40 namespace android
     41 {
     42     extern nfc_jni_native_data* getNative(JNIEnv *e, jobject o);
     43     extern bool nfcManager_isNfcActive();
     44 }
     45 
     46 extern bool         gActivated;
     47 extern SyncEvent    gDeactivatedEvent;
     48 
     49 /*****************************************************************************
     50 **
     51 ** public variables and functions
     52 **
     53 *****************************************************************************/
     54 namespace 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 *****************************************************************************/
     66 namespace 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 
     81 static uint32_t     sCheckNdefCurrentSize = 0;
     82 static tNFA_STATUS  sCheckNdefStatus = 0; //whether tag already contains a NDEF message
     83 static bool         sCheckNdefCapable = false; //whether tag has NDEF capability
     84 static tNFA_HANDLE  sNdefTypeHandlerHandle = NFA_HANDLE_INVALID;
     85 static tNFA_INTF_TYPE   sCurrentRfInterface = NFA_INTERFACE_ISO_DEP;
     86 static std::basic_string<UINT8> sRxDataBuffer;
     87 static tNFA_STATUS  sRxDataStatus = NFA_STATUS_OK;
     88 static bool         sWaitingForTransceive = false;
     89 static bool         sTransceiveRfTimeout = false;
     90 static Mutex        sRfInterfaceMutex;
     91 static uint32_t     sReadDataLen = 0;
     92 static uint8_t*     sReadData = NULL;
     93 static bool         sIsReadingNdefMessage = false;
     94 static SyncEvent    sReadEvent;
     95 static sem_t        sWriteSem;
     96 static sem_t        sFormatSem;
     97 static SyncEvent    sTransceiveEvent;
     98 static SyncEvent    sReconnectEvent;
     99 static sem_t        sCheckNdefSem;
    100 static SyncEvent    sPresenceCheckEvent;
    101 static sem_t        sMakeReadonlySem;
    102 static IntervalTimer sSwitchBackTimer; // timer used to tell us to switch back to ISO_DEP frame interface
    103 static jboolean     sWriteOk = JNI_FALSE;
    104 static jboolean     sWriteWaitingForComplete = JNI_FALSE;
    105 static bool         sFormatOk = false;
    106 static jboolean     sConnectOk = JNI_FALSE;
    107 static jboolean     sConnectWaitingForComplete = JNI_FALSE;
    108 static bool         sGotDeactivate = false;
    109 static uint32_t     sCheckNdefMaxSize = 0;
    110 static bool         sCheckNdefCardReadOnly = false;
    111 static jboolean     sCheckNdefWaitingForComplete = JNI_FALSE;
    112 static bool         sIsTagPresent = true;
    113 static tNFA_STATUS  sMakeReadonlyStatus = NFA_STATUS_FAILED;
    114 static jboolean     sMakeReadonlyWaitingForComplete = JNI_FALSE;
    115 static int          sCurrentConnectedTargetType = TARGET_TYPE_UNKNOWN;
    116 
    117 static int reSelect (tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded);
    118 static 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 *******************************************************************************/
    130 void 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 *******************************************************************************/
    169 void 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 *******************************************************************************/
    199 static 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 *******************************************************************************/
    240 static 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 *******************************************************************************/
    302 void 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 *******************************************************************************/
    324 void 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 *******************************************************************************/
    343 static 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 
    412 TheEnd:
    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 *******************************************************************************/
    434 void 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 *******************************************************************************/
    455 void 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 *******************************************************************************/
    476 static 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 
    515 TheEnd:
    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 *******************************************************************************/
    531 static 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 *******************************************************************************/
    647 static 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 *******************************************************************************/
    674 static 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 
    700 TheEnd:
    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 *******************************************************************************/
    718 static 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 *******************************************************************************/
    736 static 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 
    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 **                  status: operation status.
    765 **                  buf: Contains tag's response.
    766 **                  bufLen: Length of buffer.
    767 **
    768 ** Returns:         None
    769 **
    770 *******************************************************************************/
    771 void 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 
    789 void 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 *******************************************************************************/
    815 static 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 *******************************************************************************/
    943 static 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 *******************************************************************************/
    992 void 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 *******************************************************************************/
   1067 static 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 
   1156 TheEnd:
   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 *******************************************************************************/
   1177 void 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 *******************************************************************************/
   1193 void 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 *******************************************************************************/
   1212 static 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 *******************************************************************************/
   1291 static 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 *******************************************************************************/
   1333 static 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 *******************************************************************************/
   1355 static 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 *******************************************************************************/
   1396 void 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 *******************************************************************************/
   1420 static 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 
   1465 TheEnd:
   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;
   1488 void 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 *******************************************************************************/
   1505 void 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 *****************************************************************************/
   1518 static 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 *******************************************************************************/
   1546 int 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