Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2010 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 
     20 #include "com_android_nfc.h"
     21 #include "phNfcHalTypes.h"
     22 
     23 static phLibNfc_Data_t nfc_jni_ndef_rw;
     24 static phLibNfc_Handle handle;
     25 uint8_t *nfc_jni_ndef_buf = NULL;
     26 uint32_t nfc_jni_ndef_buf_len = 0;
     27 
     28 extern uint8_t device_connected_flag;
     29 
     30 namespace android {
     31 
     32 extern phLibNfc_Handle storedHandle;
     33 
     34 extern void nfc_jni_restart_discovery_locked(struct nfc_jni_native_data *nat);
     35 extern void nfc_jni_reset_timeout_values();
     36 
     37 /*
     38  * Callbacks
     39  */
     40  static void nfc_jni_tag_rw_callback(void *pContext, NFCSTATUS status)
     41 {
     42    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
     43    LOG_CALLBACK("nfc_jni_tag_rw_callback", status);
     44 
     45    /* Report the callback status and wake up the caller */
     46    pCallbackData->status = status;
     47    sem_post(&pCallbackData->sem);
     48 }
     49 
     50 static void nfc_jni_connect_callback(void *pContext,
     51    phLibNfc_Handle hRemoteDev,
     52    phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
     53 {
     54    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
     55    LOG_CALLBACK("nfc_jni_connect_callback", status);
     56 
     57    /* Report the callback status and wake up the caller */
     58    pCallbackData->status = status;
     59    if (pCallbackData->pContext != NULL) {
     60        // Store the remote dev info ptr in the callback context
     61        // Note that this ptr will remain valid, it is tied to a statically
     62        // allocated buffer in libnfc.
     63        phLibNfc_sRemoteDevInformation_t** ppRemoteDevInfo =
     64            (phLibNfc_sRemoteDevInformation_t**)pCallbackData->pContext;
     65        *ppRemoteDevInfo = psRemoteDevInfo;
     66    }
     67 
     68    sem_post(&pCallbackData->sem);
     69 }
     70 
     71 static void nfc_jni_checkndef_callback(void *pContext,
     72    phLibNfc_ChkNdef_Info_t info, NFCSTATUS status)
     73 {
     74    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
     75    LOG_CALLBACK("nfc_jni_checkndef_callback", status);
     76    phLibNfc_ChkNdef_Info_t* pNdefInfo = (phLibNfc_ChkNdef_Info_t*) (pCallbackData->pContext);
     77    if(status == NFCSTATUS_OK)
     78    {
     79       if(nfc_jni_ndef_buf)
     80       {
     81          free(nfc_jni_ndef_buf);
     82       }
     83       nfc_jni_ndef_buf_len = info.MaxNdefMsgLength;
     84       nfc_jni_ndef_buf = (uint8_t*)malloc(nfc_jni_ndef_buf_len);
     85       if (pNdefInfo != NULL) *pNdefInfo = info;
     86    }
     87    else {
     88       if (pNdefInfo != NULL) {
     89         memset(pNdefInfo, 0, sizeof(*pNdefInfo));
     90       }
     91    }
     92 
     93    /* Report the callback status and wake up the caller */
     94    pCallbackData->status = status;
     95    sem_post(&pCallbackData->sem);
     96 }
     97 
     98 static void nfc_jni_disconnect_callback(void *pContext,
     99    phLibNfc_Handle hRemoteDev, NFCSTATUS status)
    100 {
    101    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
    102    LOG_CALLBACK("nfc_jni_disconnect_callback", status);
    103 
    104    if(nfc_jni_ndef_buf)
    105    {
    106       free(nfc_jni_ndef_buf);
    107    }
    108    nfc_jni_ndef_buf = NULL;
    109    nfc_jni_ndef_buf_len = 0;
    110 
    111    /* Report the callback status and wake up the caller */
    112    pCallbackData->status = status;
    113    sem_post(&pCallbackData->sem);
    114 }
    115 
    116 static void nfc_jni_async_disconnect_callback(void *pContext,
    117    phLibNfc_Handle hRemoteDev, NFCSTATUS status)
    118 {
    119    LOG_CALLBACK("nfc_jni_async_disconnect_callback", status);
    120 
    121    if(nfc_jni_ndef_buf)
    122    {
    123       free(nfc_jni_ndef_buf);
    124    }
    125    nfc_jni_ndef_buf = NULL;
    126    nfc_jni_ndef_buf_len = 0;
    127 }
    128 
    129 static phNfc_sData_t *nfc_jni_transceive_buffer;
    130 
    131 static void nfc_jni_transceive_callback(void *pContext,
    132    phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
    133 {
    134    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
    135    LOG_CALLBACK("nfc_jni_transceive_callback", status);
    136 
    137    nfc_jni_transceive_buffer = pResBuffer;
    138 
    139    /* Report the callback status and wake up the caller */
    140    pCallbackData->status = status;
    141    sem_post(&pCallbackData->sem);
    142 }
    143 
    144 static void nfc_jni_presencecheck_callback(void *pContext, NFCSTATUS status)
    145 {
    146    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
    147    LOG_CALLBACK("nfc_jni_presencecheck_callback", status);
    148 
    149    /* Report the callback status and wake up the caller */
    150    pCallbackData->status = status;
    151    sem_post(&pCallbackData->sem);
    152 }
    153 
    154 static void nfc_jni_formatndef_callback(void *pContext, NFCSTATUS status)
    155 {
    156    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
    157    LOG_CALLBACK("nfc_jni_formatndef_callback", status);
    158 
    159    /* Report the callback status and wake up the caller */
    160    pCallbackData->status = status;
    161    sem_post(&pCallbackData->sem);
    162 }
    163 
    164 static void nfc_jni_readonly_callback(void *pContext, NFCSTATUS status)
    165 {
    166    struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext;
    167    LOG_CALLBACK("nfc_jni_readonly_callback", status);
    168 
    169    /* Report the callback status and wake up the caller */
    170    pCallbackData->status = status;
    171    sem_post(&pCallbackData->sem);
    172 }
    173 
    174 /* Functions */
    175 static jbyteArray com_android_nfc_NativeNfcTag_doRead(JNIEnv *e,
    176    jobject o)
    177 {
    178    NFCSTATUS status;
    179    phLibNfc_Handle handle = 0;
    180    jbyteArray buf = NULL;
    181    struct nfc_jni_callback_data cb_data;
    182 
    183    CONCURRENCY_LOCK();
    184 
    185    /* Create the local semaphore */
    186    if (!nfc_cb_data_init(&cb_data, NULL))
    187    {
    188       goto clean_and_return;
    189    }
    190 
    191    handle = nfc_jni_get_connected_handle(e, o);
    192 
    193    nfc_jni_ndef_rw.length = nfc_jni_ndef_buf_len;
    194    nfc_jni_ndef_rw.buffer = nfc_jni_ndef_buf;
    195 
    196    TRACE("phLibNfc_Ndef_Read()");
    197    REENTRANCE_LOCK();
    198    status = phLibNfc_Ndef_Read(handle, &nfc_jni_ndef_rw,
    199                                phLibNfc_Ndef_EBegin,
    200                                nfc_jni_tag_rw_callback,
    201                                (void *)&cb_data);
    202    REENTRANCE_UNLOCK();
    203    if(status != NFCSTATUS_PENDING)
    204    {
    205       LOGE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    206       goto clean_and_return;
    207    }
    208    TRACE("phLibNfc_Ndef_Read() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    209 
    210    /* Wait for callback response */
    211    if(sem_wait(&cb_data.sem))
    212    {
    213       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    214       goto clean_and_return;
    215    }
    216 
    217    if(cb_data.status != NFCSTATUS_SUCCESS)
    218    {
    219       goto clean_and_return;
    220    }
    221 
    222    buf = e->NewByteArray(nfc_jni_ndef_rw.length);
    223    e->SetByteArrayRegion(buf, 0, nfc_jni_ndef_rw.length,
    224       (jbyte *)nfc_jni_ndef_rw.buffer);
    225 
    226 clean_and_return:
    227    nfc_cb_data_deinit(&cb_data);
    228    CONCURRENCY_UNLOCK();
    229 
    230    return buf;
    231 }
    232 
    233 
    234 static jboolean com_android_nfc_NativeNfcTag_doWrite(JNIEnv *e,
    235    jobject o, jbyteArray buf)
    236 {
    237    NFCSTATUS   status;
    238    jboolean    result = JNI_FALSE;
    239    struct nfc_jni_callback_data cb_data;
    240 
    241    phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o);
    242 
    243    CONCURRENCY_LOCK();
    244 
    245    /* Create the local semaphore */
    246    if (!nfc_cb_data_init(&cb_data, NULL))
    247    {
    248       goto clean_and_return;
    249    }
    250 
    251    nfc_jni_ndef_rw.length = (uint32_t)e->GetArrayLength(buf);
    252    nfc_jni_ndef_rw.buffer = (uint8_t *)e->GetByteArrayElements(buf, NULL);
    253 
    254    TRACE("phLibNfc_Ndef_Write()");
    255    TRACE("Ndef Handle :0x%x\n",handle);
    256    TRACE("Ndef buffer length : %d", nfc_jni_ndef_rw.length);
    257    REENTRANCE_LOCK();
    258    status = phLibNfc_Ndef_Write(handle, &nfc_jni_ndef_rw,nfc_jni_tag_rw_callback, (void *)&cb_data);
    259    REENTRANCE_UNLOCK();
    260    if(status != NFCSTATUS_PENDING)
    261    {
    262       LOGE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    263       goto clean_and_return;
    264    }
    265    TRACE("phLibNfc_Ndef_Write() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    266 
    267    /* Wait for callback response */
    268    if(sem_wait(&cb_data.sem))
    269    {
    270       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    271       goto clean_and_return;
    272    }
    273 
    274    if(cb_data.status != NFCSTATUS_SUCCESS)
    275    {
    276       goto clean_and_return;
    277    }
    278 
    279    result = JNI_TRUE;
    280 
    281 clean_and_return:
    282    e->ReleaseByteArrayElements(buf, (jbyte *)nfc_jni_ndef_rw.buffer, JNI_ABORT);
    283 
    284    nfc_cb_data_deinit(&cb_data);
    285    CONCURRENCY_UNLOCK();
    286    return result;
    287 }
    288 
    289 /*
    290  *  Utility to recover poll bytes from target infos
    291  */
    292 static void set_target_pollBytes(JNIEnv *e, jobject tag,
    293         phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
    294 {
    295     jclass tag_cls = e->GetObjectClass(tag);
    296     jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B");
    297 
    298     jobjectArray existingPollBytes = (jobjectArray) e->GetObjectField(tag, f);
    299 
    300     if (existingPollBytes != NULL) {
    301         return;
    302     }
    303 
    304     jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I");
    305     jintArray techList = (jintArray) e->GetObjectField(tag, techListField);
    306     jint *techId = e->GetIntArrayElements(techList, 0);
    307     int techListLength = e->GetArrayLength(techList);
    308 
    309     jbyteArray pollBytes = e->NewByteArray(0);
    310     jobjectArray techPollBytes = e->NewObjectArray(techListLength,
    311             e->GetObjectClass(pollBytes), 0);
    312 
    313     for (int tech = 0; tech < techListLength; tech++) {
    314         switch(techId[tech])
    315         {
    316             /* ISO14443-3A: ATQA/SENS_RES */
    317             case TARGET_TYPE_ISO14443_3A:
    318                 if (psRemoteDevInfo->RemDevType == phNfc_eJewel_PICC) {
    319                     // Jewel ATQA is not read and stored by the PN544, but it is fixed
    320                     // at {0x00, 0x0C} in the spec. So eJewel can safely be
    321                     // translated to {0x00, 0x0C}.
    322                     const static jbyte JewelAtqA[2] = {0x00, 0x0C};
    323                     pollBytes = e->NewByteArray(2);
    324                     e->SetByteArrayRegion(pollBytes, 0, 2, (jbyte*) JewelAtqA);
    325                 }
    326                 else {
    327                     pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA));
    328                     e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA),
    329                                           (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA);
    330                 }
    331                 break;
    332             /* ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES */
    333             case TARGET_TYPE_ISO14443_3B:
    334                 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData)
    335                                            + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo));
    336                 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
    337                                       (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData);
    338                 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.AppData),
    339                                       sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo),
    340                                       (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.AtqB.AtqResInfo.ProtInfo);
    341                 break;
    342             /* JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte) */
    343             case TARGET_TYPE_FELICA:
    344                 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm)
    345                                            + sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode));
    346                 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
    347                                       (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm);
    348                 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.PMm),
    349                                       sizeof(psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode),
    350                                       (jbyte *)psRemoteDevInfo->RemoteDevInfo.Felica_Info.SystemCode);
    351                 break;
    352             /* ISO15693: response flags (1 byte), DSFID (1 byte) */
    353             case TARGET_TYPE_ISO15693:
    354                 pollBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
    355                                            + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid));
    356                 e->SetByteArrayRegion(pollBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
    357                                       (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
    358                 e->SetByteArrayRegion(pollBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
    359                                       sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
    360                                       (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
    361                 break;
    362             default:
    363                 pollBytes = e->NewByteArray(0);
    364                 break;
    365         }
    366         e->SetObjectArrayElement(techPollBytes, tech, pollBytes);
    367     }
    368 
    369     e->SetObjectField(tag, f, techPollBytes);
    370 
    371     e->ReleaseIntArrayElements(techList, techId, 0);
    372 
    373 }
    374 
    375 /*
    376  *  Utility to recover activation bytes from target infos
    377  */
    378 static void set_target_activationBytes(JNIEnv *e, jobject tag,
    379         phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo)
    380 {
    381     jclass tag_cls = e->GetObjectClass(tag);
    382 
    383     jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B");
    384     jobjectArray existingActBytes = (jobjectArray) e->GetObjectField(tag, f);
    385 
    386     if (existingActBytes != NULL) {
    387         return;
    388     }
    389 
    390     jfieldID techListField = e->GetFieldID(tag_cls, "mTechList", "[I");
    391     jintArray techList = (jintArray) e->GetObjectField(tag, techListField);
    392     int techListLength = e->GetArrayLength(techList);
    393     jint *techId = e->GetIntArrayElements(techList, 0);
    394 
    395     jbyteArray actBytes = e->NewByteArray(0);
    396     jobjectArray techActBytes = e->NewObjectArray(techListLength,
    397             e->GetObjectClass(actBytes), 0);
    398 
    399     for (int tech = 0; tech < techListLength; tech++) {
    400         switch(techId[tech]) {
    401 
    402             /* ISO14443-3A: SAK/SEL_RES */
    403             case TARGET_TYPE_ISO14443_3A:
    404                 actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak));
    405                 e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak),
    406                                       (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak);
    407                 break;
    408             /* ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS */
    409             /* ISO14443-3B & ISO14443-4: HiLayerResp */
    410             case TARGET_TYPE_ISO14443_4:
    411                 // Determine whether -A or -B
    412                 if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_B_PICC ||
    413                     psRemoteDevInfo->RemDevType == phNfc_eISO14443_4B_PICC) {
    414                     actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength);
    415                     e->SetByteArrayRegion(actBytes, 0, psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerRespLength,
    416                                       (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443B_Info.HiLayerResp);
    417                 }
    418                 else if (psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC ||
    419                          psRemoteDevInfo->RemDevType == phNfc_eISO14443_4A_PICC) {
    420                     actBytes = e->NewByteArray(psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength);
    421                     e->SetByteArrayRegion(actBytes, 0,
    422                                           psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppDataLength,
    423                                           (jbyte *)psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AppData);
    424                 }
    425                 break;
    426             /* ISO15693: response flags (1 byte), DSFID (1 byte) */
    427             case TARGET_TYPE_ISO15693:
    428                 actBytes = e->NewByteArray(sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags)
    429                                            + sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid));
    430                 e->SetByteArrayRegion(actBytes, 0, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
    431                                       (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags);
    432                 e->SetByteArrayRegion(actBytes, sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Flags),
    433                                       sizeof(psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid),
    434                                       (jbyte *)&psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Dsfid);
    435                 break;
    436             default:
    437                 actBytes = e->NewByteArray(0);
    438                 break;
    439         }
    440         e->SetObjectArrayElement(techActBytes, tech, actBytes);
    441     }
    442     e->SetObjectField(tag, f, techActBytes);
    443 
    444     e->ReleaseIntArrayElements(techList, techId, 0);
    445 }
    446 
    447 static jint com_android_nfc_NativeNfcTag_doConnect(JNIEnv *e,
    448    jobject o, phLibNfc_Handle handle)
    449 {
    450    jclass cls;
    451    jfieldID f;
    452    jint status;
    453    struct nfc_jni_callback_data cb_data;
    454    phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
    455 
    456    CONCURRENCY_LOCK();
    457 
    458    /* Create the local semaphore */
    459    if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
    460    {
    461       status = NFCSTATUS_NOT_ENOUGH_MEMORY;
    462       goto clean_and_return;
    463    }
    464 
    465    TRACE("phLibNfc_RemoteDev_Connect(RW)");
    466    REENTRANCE_LOCK();
    467    storedHandle = handle;
    468    status = phLibNfc_RemoteDev_Connect(handle, nfc_jni_connect_callback,(void *)&cb_data);
    469    REENTRANCE_UNLOCK();
    470    if(status != NFCSTATUS_PENDING)
    471    {
    472       LOGE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    473       goto clean_and_return;
    474    }
    475    TRACE("phLibNfc_RemoteDev_Connect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    476 
    477    /* Wait for callback response */
    478    if(sem_wait(&cb_data.sem))
    479    {
    480       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    481       status = NFCSTATUS_ABORTED;
    482       goto clean_and_return;
    483    }
    484 
    485    status = cb_data.status;
    486    TRACE("phLibNfc_RemoteDev_Connect() - Status code = %d", status);
    487 
    488    /* Connect Status */
    489    if(status != NFCSTATUS_SUCCESS)
    490    {
    491       goto clean_and_return;
    492    }
    493 
    494    // Success, set poll & act bytes
    495    set_target_pollBytes(e, o, pRemDevInfo);
    496    set_target_activationBytes(e, o, pRemDevInfo);
    497 
    498 clean_and_return:
    499    nfc_cb_data_deinit(&cb_data);
    500    CONCURRENCY_UNLOCK();
    501    return status;
    502 }
    503 
    504 static jint com_android_nfc_NativeNfcTag_doHandleReconnect(JNIEnv *e,
    505    jobject o, phLibNfc_Handle handle)
    506 {
    507    jclass cls;
    508    jfieldID f;
    509    jint status;
    510    struct nfc_jni_callback_data cb_data;
    511    phLibNfc_sRemoteDevInformation_t* pRemDevInfo = NULL;
    512    CONCURRENCY_LOCK();
    513 
    514    /* Create the local semaphore */
    515    if (!nfc_cb_data_init(&cb_data, &pRemDevInfo))
    516    {
    517       status = NFCSTATUS_NOT_ENOUGH_MEMORY;
    518       goto clean_and_return;
    519    }
    520 
    521    TRACE("phLibNfc_RemoteDev_ReConnect(RW)");
    522    REENTRANCE_LOCK();
    523    storedHandle = handle;
    524    status = phLibNfc_RemoteDev_ReConnect(handle, nfc_jni_connect_callback,(void *)&cb_data);
    525    REENTRANCE_UNLOCK();
    526    if(status != NFCSTATUS_PENDING)
    527    {
    528       LOGE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    529       goto clean_and_return;
    530    }
    531    TRACE("phLibNfc_RemoteDev_ReConnect(RW) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    532 
    533    /* Wait for callback response */
    534    if(sem_wait(&cb_data.sem))
    535    {
    536       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    537       status = NFCSTATUS_ABORTED;
    538       goto clean_and_return;
    539    }
    540 
    541    status = cb_data.status;
    542 
    543    /* Connect Status */
    544    if(status != NFCSTATUS_SUCCESS)
    545    {
    546       goto clean_and_return;
    547    }
    548 
    549 clean_and_return:
    550    nfc_cb_data_deinit(&cb_data);
    551    CONCURRENCY_UNLOCK();
    552    return status;
    553 }
    554 
    555 static jint com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e,
    556    jobject o)
    557 {
    558     // Reconnect is provided by libnfc by just calling connect again
    559     // on the same handle.
    560     int libNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o);
    561     if (libNfcType != -1) {
    562         // Note that some tag types are stateless, hence we do not reconnect
    563         // those. Currently those are the Jewel and Iso15693 technologies.
    564         if ((libNfcType != phNfc_eJewel_PICC) && (libNfcType != phNfc_eISO15693_PICC)) {
    565             phLibNfc_Handle handle = nfc_jni_get_connected_handle(e,o);
    566             return com_android_nfc_NativeNfcTag_doConnect(e, o, handle);
    567         }
    568         else {
    569             return NFCSTATUS_SUCCESS;
    570         }
    571     }
    572     else {
    573         return NFCSTATUS_REJECTED;
    574     }
    575 }
    576 
    577 
    578 static jboolean com_android_nfc_NativeNfcTag_doDisconnect(JNIEnv *e, jobject o)
    579 {
    580    phLibNfc_Handle handle = 0;
    581    jclass cls;
    582    jfieldID f;
    583    NFCSTATUS status;
    584    jboolean result = JNI_FALSE;
    585    struct nfc_jni_callback_data cb_data;
    586 
    587    CONCURRENCY_LOCK();
    588 
    589    handle = nfc_jni_get_connected_handle(e, o);
    590 
    591    /* Create the local semaphore */
    592    if (!nfc_cb_data_init(&cb_data, NULL))
    593    {
    594       goto clean_and_return;
    595    }
    596 
    597    /* Reset the stored handle */
    598    storedHandle = 0;
    599 
    600    nfc_jni_reset_timeout_values();
    601 
    602    /* Disconnect */
    603    TRACE("Disconnecting from tag (%x)", handle);
    604 
    605    if (handle == -1) {
    606        // Was never connected to any tag, exit
    607        result = JNI_TRUE;
    608        LOGE("doDisconnect() - Target already disconnected");
    609        nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
    610        goto clean_and_return;
    611    }
    612 
    613     TRACE("phLibNfc_RemoteDev_Disconnect(%x)", handle);
    614     REENTRANCE_LOCK();
    615     status = phLibNfc_RemoteDev_Disconnect(handle, NFC_DISCOVERY_CONTINUE,
    616                                           nfc_jni_disconnect_callback, (void *)&cb_data);
    617     REENTRANCE_UNLOCK();
    618 
    619     if(status == NFCSTATUS_TARGET_NOT_CONNECTED)
    620     {
    621         result = JNI_TRUE;
    622         TRACE("phLibNfc_RemoteDev_Disconnect() - Target already disconnected");
    623         goto clean_and_return;
    624     }
    625     if(status != NFCSTATUS_PENDING)
    626     {
    627         LOGE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
    628         nfc_jni_restart_discovery_locked(nfc_jni_get_nat_ext(e));
    629         goto clean_and_return;
    630     }
    631     TRACE("phLibNfc_RemoteDev_Disconnect(%x) returned 0x%04x[%s]", handle, status, nfc_jni_get_status_name(status));
    632 
    633     /* Wait for callback response */
    634     if(sem_wait(&cb_data.sem))
    635     {
    636        LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    637        goto clean_and_return;
    638     }
    639 
    640     /* Disconnect Status */
    641     if(cb_data.status != NFCSTATUS_SUCCESS)
    642     {
    643         goto clean_and_return;
    644     }
    645 
    646     result = JNI_TRUE;
    647 
    648 clean_and_return:
    649     /* Reset device connected flag */
    650     device_connected_flag = 0;
    651    nfc_cb_data_deinit(&cb_data);
    652    CONCURRENCY_UNLOCK();
    653    return result;
    654 }
    655 
    656 static uint16_t
    657 crc_16_ccitt1( uint8_t* msg, size_t len, uint16_t init )
    658 {
    659     uint16_t b, crc = init;
    660 
    661     do {
    662         b = *msg++ ^ (crc & 0xFF);
    663         b ^= (b << 4) & 0xFF;
    664         crc = (crc >> 8) ^ (b << 8) ^ (b << 3) ^ (b >> 4);
    665     } while( --len );
    666 
    667     return crc;
    668 }
    669 
    670 static void
    671 nfc_insert_crc_a( uint8_t* msg, size_t len )
    672 {
    673     uint16_t crc;
    674 
    675     crc = crc_16_ccitt1( msg, len, 0x6363 );
    676     msg[len] = crc & 0xFF;
    677     msg[len + 1] = (crc >> 8) & 0xFF;
    678 }
    679 
    680 static void
    681 nfc_get_crc_a( uint8_t* msg, size_t len, uint8_t* byte1, uint8_t* byte2)
    682 {
    683     uint16_t crc;
    684 
    685     crc = crc_16_ccitt1( msg, len, 0x6363 );
    686     *byte1 = crc & 0xFF;
    687     *byte2 = (crc >> 8) & 0xFF;
    688 }
    689 
    690 static bool
    691 crc_valid( uint8_t* msg, size_t len)
    692 {
    693     uint8_t crcByte1, crcByte2;
    694 
    695     nfc_get_crc_a(nfc_jni_transceive_buffer->buffer,
    696           len - 2, &crcByte1, &crcByte2);
    697 
    698     if (msg[len - 2] == crcByte1 &&
    699           msg[len - 1] == crcByte2) {
    700         return true;
    701     }
    702     else {
    703         return false;
    704     }
    705 
    706 }
    707 
    708 static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e,
    709    jobject o, jbyteArray data, jboolean raw, jintArray statusTargetLost)
    710 {
    711     uint8_t offset = 0;
    712     // buf is the pointer to the JNI array and never overwritten,
    713     // outbuf is passed into the transceive - it may be pointed to new memory
    714     // to be extended with CRC.
    715     uint8_t *buf = NULL;
    716     uint32_t buflen;
    717 
    718     uint8_t *outbuf = NULL;
    719     uint32_t outlen;
    720     phLibNfc_sTransceiveInfo_t transceive_info;
    721     jbyteArray result = NULL;
    722     int res;
    723     phLibNfc_Handle handle = nfc_jni_get_connected_handle(e, o);
    724     NFCSTATUS status;
    725     struct nfc_jni_callback_data cb_data;
    726     int selectedTech = 0;
    727     int selectedLibNfcType = 0;
    728     jint* technologies = NULL;
    729     bool checkResponseCrc = false;
    730 
    731     jint *targetLost;
    732     if (statusTargetLost != NULL) {
    733         targetLost = e->GetIntArrayElements(statusTargetLost, 0);
    734         if (targetLost != NULL) {
    735             *targetLost = 0;
    736         }
    737     } else {
    738         targetLost = NULL;
    739     }
    740 
    741     memset(&transceive_info, 0, sizeof(transceive_info));
    742     CONCURRENCY_LOCK();
    743 
    744     /* Create the local semaphore */
    745     if (!nfc_cb_data_init(&cb_data, NULL))
    746     {
    747        goto clean_and_return;
    748     }
    749 
    750     selectedTech = nfc_jni_get_connected_technology(e, o);
    751     selectedLibNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o);
    752 
    753     buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL);
    754     buflen = outlen = (uint32_t)e->GetArrayLength(data);
    755 
    756     switch (selectedTech) {
    757         case TARGET_TYPE_FELICA:
    758           transceive_info.cmd.FelCmd = phNfc_eFelica_Raw;
    759           transceive_info.addr = 0;
    760           break;
    761         case TARGET_TYPE_MIFARE_CLASSIC:
    762         case TARGET_TYPE_MIFARE_UL:
    763           if (raw) {
    764               transceive_info.cmd.MfCmd = phHal_eMifareRaw;
    765               transceive_info.addr = 0;
    766               // Need to add in the crc here
    767               outbuf = (uint8_t*)malloc(buflen + 2);
    768               outlen += 2;
    769               memcpy(outbuf, buf, buflen);
    770               nfc_insert_crc_a(outbuf, buflen);
    771 
    772               checkResponseCrc = true;
    773           } else {
    774               offset = 2;
    775               transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
    776               transceive_info.addr = (uint8_t)buf[1];
    777           }
    778           break;
    779         case TARGET_TYPE_ISO14443_3A:
    780           // Check which libnfc type
    781           if (selectedLibNfcType == phNfc_eJewel_PICC) {
    782               // For the Jewel pipe, CRC is automatically computed
    783               transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw;
    784               transceive_info.addr = 0;
    785           } else {
    786               if (raw) {
    787                   // Use Mifare Raw to implement a standard
    788                   // ISO14443-3A transceive, with CRC added
    789                   transceive_info.cmd.MfCmd = phHal_eMifareRaw;
    790                   transceive_info.addr = 0;
    791                   // Need to add in the crc here
    792                   outbuf = (uint8_t*)malloc(buflen + 2);
    793                   outlen += 2;
    794                   memcpy(outbuf, buf, buflen);
    795                   nfc_insert_crc_a(outbuf, buflen);
    796 
    797                   checkResponseCrc = true;
    798               } else {
    799                   // Use the mifare pipe
    800                   offset = 2;
    801                   transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
    802                   transceive_info.addr = (uint8_t)buf[1];
    803               }
    804 
    805           }
    806           break;
    807         case TARGET_TYPE_ISO14443_4:
    808           transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
    809           transceive_info.addr = 0;
    810           break;
    811         case TARGET_TYPE_ISO15693:
    812           transceive_info.cmd.Iso15693Cmd = phNfc_eIso15693_Cmd;
    813           transceive_info.addr = 0;
    814           break;
    815         case TARGET_TYPE_UNKNOWN:
    816         case TARGET_TYPE_ISO14443_3B:
    817           // Not supported
    818           goto clean_and_return;
    819         default:
    820           break;
    821     }
    822 
    823     transceive_info.sSendData.buffer = outbuf + offset;
    824     transceive_info.sSendData.length = outlen - offset;
    825     transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
    826     transceive_info.sRecvData.length = 1024;
    827     if(transceive_info.sRecvData.buffer == NULL)
    828     {
    829       goto clean_and_return;
    830     }
    831 
    832     TRACE("phLibNfc_RemoteDev_Transceive()");
    833     REENTRANCE_LOCK();
    834     status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
    835          nfc_jni_transceive_callback, (void *)&cb_data);
    836     REENTRANCE_UNLOCK();
    837     if(status != NFCSTATUS_PENDING)
    838     {
    839       LOGE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    840       if ((targetLost != NULL) && (status == NFCSTATUS_TARGET_LOST)) {
    841           *targetLost = 1;
    842       }
    843       goto clean_and_return;
    844     }
    845     TRACE("phLibNfc_RemoteDev_Transceive() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    846 
    847     /* Wait for callback response */
    848     if(sem_wait(&cb_data.sem))
    849     {
    850        LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    851        goto clean_and_return;
    852     }
    853 
    854     if(cb_data.status != NFCSTATUS_SUCCESS)
    855     {
    856         if ((targetLost != NULL) && (cb_data.status == NFCSTATUS_TARGET_LOST)) {
    857             *targetLost = 1;
    858         }
    859         goto clean_and_return;
    860     }
    861 
    862     /* Copy results back to Java *
    863      * In case of NfcA and raw, also check the CRC in the response
    864      * and cut it off in the returned data.
    865      */
    866     if ((nfc_jni_transceive_buffer->length > 2) && checkResponseCrc) {
    867         if (crc_valid(nfc_jni_transceive_buffer->buffer, nfc_jni_transceive_buffer->length)) {
    868             result = e->NewByteArray(nfc_jni_transceive_buffer->length - 2);
    869             if (result != NULL) {
    870                 e->SetByteArrayRegion(result, 0,
    871                  nfc_jni_transceive_buffer->length - 2,
    872                  (jbyte *)nfc_jni_transceive_buffer->buffer);
    873             }
    874         }
    875     } else {
    876         result = e->NewByteArray(nfc_jni_transceive_buffer->length);
    877         if (result != NULL) {
    878             e->SetByteArrayRegion(result, 0,
    879              nfc_jni_transceive_buffer->length,
    880              (jbyte *)nfc_jni_transceive_buffer->buffer);
    881         }
    882     }
    883 clean_and_return:
    884     if(transceive_info.sRecvData.buffer != NULL)
    885     {
    886       free(transceive_info.sRecvData.buffer);
    887     }
    888 
    889     if ((outbuf != buf) && (outbuf != NULL)) {
    890         // Buf was extended and re-alloced with crc bytes, free separately
    891         free(outbuf);
    892     }
    893 
    894     e->ReleaseByteArrayElements(data,
    895       (jbyte *)buf, JNI_ABORT);
    896 
    897     if (targetLost != NULL) {
    898         e->ReleaseIntArrayElements(statusTargetLost, targetLost, 0);
    899     }
    900 
    901     nfc_cb_data_deinit(&cb_data);
    902 
    903     CONCURRENCY_UNLOCK();
    904 
    905     return result;
    906 }
    907 
    908 static jint com_android_nfc_NativeNfcTag_doGetNdefType(JNIEnv *e, jobject o,
    909         jint libnfcType, jint javaType)
    910 {
    911     jint ndefType =  NDEF_UNKNOWN_TYPE;
    912 
    913     switch (libnfcType) {
    914           case phNfc_eJewel_PICC:
    915               ndefType = NDEF_TYPE1_TAG;
    916               break;
    917           case phNfc_eISO14443_3A_PICC:
    918               ndefType = NDEF_TYPE2_TAG;;
    919               break;
    920           case phNfc_eFelica_PICC:
    921               ndefType = NDEF_TYPE3_TAG;
    922               break;
    923           case phNfc_eISO14443_A_PICC:
    924           case phNfc_eISO14443_4A_PICC:
    925           case phNfc_eISO14443_B_PICC:
    926           case phNfc_eISO14443_4B_PICC:
    927               ndefType = NDEF_TYPE4_TAG;
    928               break;
    929           case phNfc_eMifare_PICC:
    930               if (javaType == TARGET_TYPE_MIFARE_UL) {
    931                   ndefType = NDEF_TYPE2_TAG;
    932               } else {
    933                   ndefType = NDEF_MIFARE_CLASSIC_TAG;
    934               }
    935               break;
    936           case phNfc_eISO15693_PICC:
    937               ndefType = NDEF_ICODE_SLI_TAG;
    938               break;
    939           default:
    940               ndefType = NDEF_UNKNOWN_TYPE;
    941               break;
    942     }
    943     return ndefType;
    944 }
    945 
    946 static jint com_android_nfc_NativeNfcTag_doCheckNdef(JNIEnv *e, jobject o, jintArray ndefinfo)
    947 {
    948    phLibNfc_Handle handle = 0;
    949    jint status;
    950    phLibNfc_ChkNdef_Info_t sNdefInfo;
    951    struct nfc_jni_callback_data cb_data;
    952    jint *ndef = e->GetIntArrayElements(ndefinfo, 0);
    953    int apiCardState = NDEF_MODE_UNKNOWN;
    954 
    955    CONCURRENCY_LOCK();
    956 
    957    /* Create the local semaphore */
    958    if (!nfc_cb_data_init(&cb_data, NULL))
    959    {
    960       status = NFCSTATUS_NOT_ENOUGH_MEMORY;
    961       goto clean_and_return;
    962    }
    963    cb_data.pContext = &sNdefInfo;
    964 
    965    handle = nfc_jni_get_connected_handle(e, o);
    966 
    967    TRACE("phLibNfc_Ndef_CheckNdef()");
    968    REENTRANCE_LOCK();
    969    status = phLibNfc_Ndef_CheckNdef(handle, nfc_jni_checkndef_callback,(void *)&cb_data);
    970    REENTRANCE_UNLOCK();
    971    if(status != NFCSTATUS_PENDING)
    972    {
    973       LOGE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    974       goto clean_and_return;
    975    }
    976    TRACE("phLibNfc_Ndef_CheckNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    977 
    978    /* Wait for callback response */
    979    if(sem_wait(&cb_data.sem))
    980    {
    981       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
    982       status = NFCSTATUS_ABORTED;
    983       goto clean_and_return;
    984    }
    985 
    986    status = cb_data.status;
    987    TRACE("phLibNfc_Ndef_CheckNdef() - Status code = %d", status);
    988 
    989    if (status != NFCSTATUS_SUCCESS)
    990    {
    991       goto clean_and_return;
    992    }
    993 
    994    ndef[0] = sNdefInfo.MaxNdefMsgLength;
    995    // Translate the card state to know values for the NFC API
    996    switch (sNdefInfo.NdefCardState) {
    997        case PHLIBNFC_NDEF_CARD_INITIALISED:
    998            apiCardState = NDEF_MODE_READ_WRITE;
    999            break;
   1000        case PHLIBNFC_NDEF_CARD_READ_ONLY:
   1001            apiCardState = NDEF_MODE_READ_ONLY;
   1002            break;
   1003        case PHLIBNFC_NDEF_CARD_READ_WRITE:
   1004            apiCardState = NDEF_MODE_READ_WRITE;
   1005            break;
   1006        case PHLIBNFC_NDEF_CARD_INVALID:
   1007            apiCardState = NDEF_MODE_UNKNOWN;
   1008            break;
   1009    }
   1010    ndef[1] = apiCardState;
   1011 
   1012 clean_and_return:
   1013    e->ReleaseIntArrayElements(ndefinfo, ndef, 0);
   1014    nfc_cb_data_deinit(&cb_data);
   1015    CONCURRENCY_UNLOCK();
   1016    return status;
   1017 }
   1018 
   1019 static jboolean com_android_nfc_NativeNfcTag_doPresenceCheck(JNIEnv *e, jobject o)
   1020 {
   1021    phLibNfc_Handle handle = 0;
   1022    NFCSTATUS status;
   1023    jboolean result = JNI_FALSE;
   1024    struct nfc_jni_callback_data cb_data;
   1025 
   1026    CONCURRENCY_LOCK();
   1027 
   1028    /* Create the local semaphore */
   1029    if (!nfc_cb_data_init(&cb_data, NULL))
   1030    {
   1031       goto clean_and_return;
   1032    }
   1033 
   1034    handle = nfc_jni_get_connected_handle(e, o);
   1035 
   1036    TRACE("phLibNfc_RemoteDev_CheckPresence()");
   1037    REENTRANCE_LOCK();
   1038    status = phLibNfc_RemoteDev_CheckPresence(handle, nfc_jni_presencecheck_callback, (void *)&cb_data);
   1039    REENTRANCE_UNLOCK();
   1040 
   1041    if(status != NFCSTATUS_PENDING)
   1042    {
   1043       LOGE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1044       goto clean_and_return;
   1045    }
   1046    TRACE("phLibNfc_RemoteDev_CheckPresence() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1047 
   1048    /* Wait for callback response */
   1049    if(sem_wait(&cb_data.sem))
   1050    {
   1051       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
   1052       goto clean_and_return;
   1053    }
   1054 
   1055    if (cb_data.status == NFCSTATUS_SUCCESS)
   1056    {
   1057        result = JNI_TRUE;
   1058    }
   1059 
   1060 clean_and_return:
   1061    nfc_cb_data_deinit(&cb_data);
   1062 
   1063    CONCURRENCY_UNLOCK();
   1064 
   1065    return result;
   1066 }
   1067 
   1068 static jboolean com_android_nfc_NativeNfcTag_doIsNdefFormatable(JNIEnv *e,
   1069         jobject o, jint libNfcType, jbyteArray uidBytes,
   1070         jbyteArray pollBytes, jbyteArray actBytes)
   1071 {
   1072     // Determine whether libnfc can format this type
   1073     jboolean result = JNI_FALSE;
   1074 
   1075     switch (libNfcType) {
   1076         case phNfc_eISO14443_A_PICC:
   1077         case phNfc_eISO14443_4A_PICC:
   1078             // ISO14443-4A -> only if it's a DESfire!
   1079             // DESfire has one sak byte and 2 ATQA bytes
   1080             if (pollBytes != NULL && (e->GetArrayLength(pollBytes) >= 2) &&
   1081                     actBytes != NULL && (e->GetArrayLength(actBytes) >= 1)) {
   1082                 jbyte* poll = e->GetByteArrayElements(pollBytes, NULL);
   1083                 jbyte* act = e->GetByteArrayElements(actBytes, NULL);
   1084                 if (act[0] == 0x20 && poll[1] == 0x03) {
   1085                     uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
   1086                     // Identifies as DESfire, use get version cmd to be sure
   1087                     jbyteArray versionCmd = e->NewByteArray(5);
   1088 
   1089                     e->SetByteArrayRegion(versionCmd, 0, 5, (jbyte*)cmd);
   1090                     jbyteArray resp = com_android_nfc_NativeNfcTag_doTransceive(e, o,
   1091                                 versionCmd, JNI_TRUE, NULL);
   1092                     if (resp != NULL) {
   1093                         // Having a response is a good enough indication this
   1094                         // is actually a DESfire.
   1095                         result = JNI_TRUE;
   1096                     }
   1097                 }
   1098                 e->ReleaseByteArrayElements(pollBytes, (jbyte *)poll, JNI_ABORT);
   1099                 e->ReleaseByteArrayElements(actBytes, (jbyte *)act, JNI_ABORT);
   1100             }
   1101             break;
   1102         case phNfc_eMifare_PICC:
   1103             // We can always format Mifare Classic / UL
   1104             result = JNI_TRUE;
   1105             break;
   1106         case phNfc_eISO15693_PICC:
   1107             result = JNI_FALSE;
   1108             if (e->GetArrayLength(uidBytes) >= 8) {
   1109                 jbyte* uid = e->GetByteArrayElements(uidBytes, NULL);
   1110                 // Byte 5: tag code, supported [1..3]
   1111                 // Byte 6: manufacturer ID, 0x04 == NXP
   1112                 if ((uid[5] >= 1) && (uid[5] <= 3) &&
   1113                         (uid[6] == 0x04)) {
   1114                     result = JNI_TRUE;
   1115                 }
   1116                 e->ReleaseByteArrayElements(uidBytes, (jbyte *)uid, JNI_ABORT);
   1117             }
   1118             break;
   1119         default:
   1120             result = JNI_FALSE;
   1121             break;
   1122     }
   1123     return result;
   1124 
   1125 }
   1126 
   1127 static jboolean com_android_nfc_NativeNfcTag_doNdefFormat(JNIEnv *e, jobject o, jbyteArray key)
   1128 {
   1129    phLibNfc_Handle handle = 0;
   1130    NFCSTATUS status;
   1131    phNfc_sData_t keyBuffer;
   1132    jboolean result = JNI_FALSE;
   1133    struct nfc_jni_callback_data cb_data;
   1134 
   1135    CONCURRENCY_LOCK();
   1136 
   1137    /* Create the local semaphore */
   1138    if (!nfc_cb_data_init(&cb_data, NULL))
   1139    {
   1140       goto clean_and_return;
   1141    }
   1142 
   1143    handle = nfc_jni_get_connected_handle(e, o);
   1144 
   1145    keyBuffer.buffer = (uint8_t *)e->GetByteArrayElements(key, NULL);
   1146    keyBuffer.length = e->GetArrayLength(key);
   1147    TRACE("phLibNfc_RemoteDev_FormatNdef()");
   1148    REENTRANCE_LOCK();
   1149    status = phLibNfc_RemoteDev_FormatNdef(handle, &keyBuffer, nfc_jni_formatndef_callback, (void *)&cb_data);
   1150    REENTRANCE_UNLOCK();
   1151 
   1152    if(status != NFCSTATUS_PENDING)
   1153    {
   1154       LOGE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1155       goto clean_and_return;
   1156    }
   1157    TRACE("phLibNfc_RemoteDev_FormatNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1158 
   1159    /* Wait for callback response */
   1160    if(sem_wait(&cb_data.sem))
   1161    {
   1162       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
   1163       goto clean_and_return;
   1164    }
   1165 
   1166    if (cb_data.status == NFCSTATUS_SUCCESS)
   1167    {
   1168        result = JNI_TRUE;
   1169    }
   1170 
   1171 clean_and_return:
   1172    e->ReleaseByteArrayElements(key, (jbyte *)keyBuffer.buffer, JNI_ABORT);
   1173    nfc_cb_data_deinit(&cb_data);
   1174    CONCURRENCY_UNLOCK();
   1175    return result;
   1176 }
   1177 
   1178 static jboolean com_android_nfc_NativeNfcTag_doMakeReadonly(JNIEnv *e, jobject o)
   1179 {
   1180    phLibNfc_Handle handle = 0;
   1181    NFCSTATUS status;
   1182    jboolean result = JNI_FALSE;
   1183    struct nfc_jni_callback_data cb_data;
   1184 
   1185    CONCURRENCY_LOCK();
   1186 
   1187    /* Create the local semaphore */
   1188    if (!nfc_cb_data_init(&cb_data, NULL))
   1189    {
   1190       goto clean_and_return;
   1191    }
   1192 
   1193    handle = nfc_jni_get_connected_handle(e, o);
   1194 
   1195    TRACE("phLibNfc_ConvertToReadOnlyNdef()");
   1196    REENTRANCE_LOCK();
   1197    status = phLibNfc_ConvertToReadOnlyNdef(handle, nfc_jni_readonly_callback, (void *)&cb_data);
   1198    REENTRANCE_UNLOCK();
   1199 
   1200    if(status != NFCSTATUS_PENDING)
   1201    {
   1202       LOGE("pphLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1203       goto clean_and_return;
   1204    }
   1205    TRACE("phLibNfc_ConvertToReadOnlyNdef() returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
   1206 
   1207    /* Wait for callback response */
   1208    if(sem_wait(&cb_data.sem))
   1209    {
   1210       LOGE("Failed to wait for semaphore (errno=0x%08x)", errno);
   1211       goto clean_and_return;
   1212    }
   1213 
   1214    if (cb_data.status == NFCSTATUS_SUCCESS)
   1215    {
   1216        result = JNI_TRUE;
   1217    }
   1218 
   1219 clean_and_return:
   1220    nfc_cb_data_deinit(&cb_data);
   1221    CONCURRENCY_UNLOCK();
   1222    return result;
   1223 }
   1224 /*
   1225  * JNI registration.
   1226  */
   1227 static JNINativeMethod gMethods[] =
   1228 {
   1229    {"doConnect", "(I)I",
   1230       (void *)com_android_nfc_NativeNfcTag_doConnect},
   1231    {"doDisconnect", "()Z",
   1232       (void *)com_android_nfc_NativeNfcTag_doDisconnect},
   1233    {"doReconnect", "()I",
   1234       (void *)com_android_nfc_NativeNfcTag_doReconnect},
   1235    {"doHandleReconnect", "(I)I",
   1236       (void *)com_android_nfc_NativeNfcTag_doHandleReconnect},
   1237    {"doTransceive", "([BZ[I)[B",
   1238       (void *)com_android_nfc_NativeNfcTag_doTransceive},
   1239    {"doGetNdefType", "(II)I",
   1240       (void *)com_android_nfc_NativeNfcTag_doGetNdefType},
   1241    {"doCheckNdef", "([I)I",
   1242       (void *)com_android_nfc_NativeNfcTag_doCheckNdef},
   1243    {"doRead", "()[B",
   1244       (void *)com_android_nfc_NativeNfcTag_doRead},
   1245    {"doWrite", "([B)Z",
   1246       (void *)com_android_nfc_NativeNfcTag_doWrite},
   1247    {"doPresenceCheck", "()Z",
   1248       (void *)com_android_nfc_NativeNfcTag_doPresenceCheck},
   1249    {"doIsNdefFormatable", "(I[B[B[B)Z",
   1250       (void *)com_android_nfc_NativeNfcTag_doIsNdefFormatable},
   1251    {"doNdefFormat", "([B)Z",
   1252       (void *)com_android_nfc_NativeNfcTag_doNdefFormat},
   1253    {"doMakeReadonly", "()Z",
   1254       (void *)com_android_nfc_NativeNfcTag_doMakeReadonly},
   1255 };
   1256 
   1257 int register_com_android_nfc_NativeNfcTag(JNIEnv *e)
   1258 {
   1259    return jniRegisterNativeMethods(e,
   1260       "com/android/nfc/NativeNfcTag",
   1261       gMethods, NELEM(gMethods));
   1262 }
   1263 
   1264 } // namespace android
   1265