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