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