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