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