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 
     19 #include "com_android_nfc.h"
     20 
     21 static phNfc_sData_t *com_android_nfc_jni_transceive_buffer;
     22 static phNfc_sData_t *com_android_nfc_jni_ioctl_buffer;
     23 static phNfc_sRemoteDevInformation_t* SecureElementInfo;
     24 static int secureElementHandle;
     25 extern void                 *gHWRef;
     26 static int SecureElementTech;
     27 extern uint8_t device_connected_flag;
     28 
     29 namespace android {
     30 
     31 static void com_android_nfc_jni_ioctl_callback ( void*            pContext,
     32                                             phNfc_sData_t*   Outparam_Cb,
     33                                             NFCSTATUS        status)
     34 {
     35     struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
     36 
     37 	if (status == NFCSTATUS_SUCCESS )
     38 	{
     39 	    LOG_CALLBACK("> IOCTL successful",status);
     40 	}
     41 	else
     42 	{
     43 	    LOG_CALLBACK("> IOCTL error",status);
     44 	}
     45 
     46    com_android_nfc_jni_ioctl_buffer = Outparam_Cb;
     47    pContextData->status = status;
     48    sem_post(&pContextData->sem);
     49 }
     50 
     51 static void com_android_nfc_jni_transceive_callback(void *pContext,
     52    phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
     53 {
     54    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
     55 
     56    LOG_CALLBACK("com_android_nfc_jni_transceive_callback", status);
     57 
     58    com_android_nfc_jni_transceive_buffer = pResBuffer;
     59    pContextData->status = status;
     60    sem_post(&pContextData->sem);
     61 }
     62 
     63 
     64 static void com_android_nfc_jni_connect_callback(void *pContext,
     65                                             phLibNfc_Handle hRemoteDev,
     66                                             phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
     67 {
     68    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
     69 
     70    LOG_CALLBACK("com_android_nfc_jni_connect_callback", status);
     71 
     72    pContextData->status = status;
     73    sem_post(&pContextData->sem);
     74 }
     75 
     76 static void com_android_nfc_jni_disconnect_callback(void *pContext,
     77                                                phLibNfc_Handle hRemoteDev,
     78                                                NFCSTATUS status)
     79 {
     80    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
     81 
     82    LOG_CALLBACK("com_android_nfc_jni_disconnect_callback", status);
     83 
     84    pContextData->status = status;
     85    sem_post(&pContextData->sem);
     86 }
     87 
     88 /* Set Secure Element mode callback*/
     89 static void com_android_nfc_jni_smartMX_setModeCb (void*            pContext,
     90 							                                phLibNfc_Handle  hSecureElement,
     91                                               NFCSTATUS        status)
     92 {
     93     struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
     94 
     95 	if(status==NFCSTATUS_SUCCESS)
     96 	{
     97 	    LOG_CALLBACK("SE Set Mode is Successful",status);
     98 	    TRACE("SE Handle: %lu", hSecureElement);
     99 	}
    100 	else
    101 	{
    102 	    LOG_CALLBACK("SE Set Mode is failed\n ",status);
    103   }
    104 
    105    pContextData->status = status;
    106    sem_post(&pContextData->sem);
    107 }
    108 
    109 static void com_android_nfc_jni_open_secure_element_notification_callback(void *pContext,
    110                                                                      phLibNfc_RemoteDevList_t *psRemoteDevList,
    111                                                                      uint8_t uNofRemoteDev,
    112                                                                      NFCSTATUS status)
    113 {
    114    struct nfc_jni_callback_data * pContextData =  (struct nfc_jni_callback_data*)pContext;
    115    NFCSTATUS ret;
    116    int i;
    117    JNIEnv *e = nfc_get_env();
    118 
    119    if(status == NFCSTATUS_DESELECTED)
    120    {
    121       LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback: Target deselected", status);
    122    }
    123    else
    124    {
    125       LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback", status);
    126       TRACE("Discovered %d secure elements", uNofRemoteDev);
    127 
    128       if(status == NFCSTATUS_MULTIPLE_PROTOCOLS)
    129       {
    130          bool foundHandle = false;
    131          TRACE("Multiple Protocol supported\n");
    132          for (i=0; i<uNofRemoteDev; i++) {
    133              // Always open the phNfc_eISO14443_A_PICC protocol
    134              TRACE("Protocol %d handle=%x type=%d", i, psRemoteDevList[i].hTargetDev,
    135                      psRemoteDevList[i].psRemoteDevInfo->RemDevType);
    136              if (psRemoteDevList[i].psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC) {
    137                  secureElementHandle = psRemoteDevList[i].hTargetDev;
    138                  foundHandle = true;
    139              }
    140          }
    141          if (!foundHandle) {
    142              ALOGE("Could not find ISO-DEP secure element");
    143              status = NFCSTATUS_FAILED;
    144              goto clean_and_return;
    145          }
    146       }
    147       else
    148       {
    149          secureElementHandle = psRemoteDevList->hTargetDev;
    150       }
    151 
    152       TRACE("Secure Element Handle: 0x%08x", secureElementHandle);
    153 
    154       /* Set type name */
    155       ScopedLocalRef<jintArray> techList(e, NULL);
    156       nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL);
    157 
    158       // TODO: Should use the "connected" technology, for now use the first
    159       if ((techList.get() != NULL) && e->GetArrayLength(techList.get()) > 0) {
    160          e->GetIntArrayRegion(techList.get(), 0, 1, &SecureElementTech);
    161          TRACE("Store Secure Element Info\n");
    162          SecureElementInfo = psRemoteDevList->psRemoteDevInfo;
    163 
    164          TRACE("Discovered secure element: tech=%d", SecureElementTech);
    165       }
    166       else {
    167          ALOGE("Discovered secure element, but could not resolve tech");
    168          status = NFCSTATUS_FAILED;
    169       }
    170    }
    171 
    172 clean_and_return:
    173    pContextData->status = status;
    174    sem_post(&pContextData->sem);
    175 }
    176 
    177 
    178 static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o)
    179 {
    180    NFCSTATUS ret;
    181    int semResult;
    182    jint errorCode = EE_ERROR_INIT;
    183 
    184    phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
    185    uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
    186    phLibNfc_sADD_Cfg_t discovery_cfg;
    187    phLibNfc_Registry_Info_t registry_info;
    188    phNfc_sData_t        InParam;
    189    phNfc_sData_t        OutParam;
    190    uint8_t              ExternalRFDetected[3] = {0x00, 0xFC, 0x01};
    191    uint8_t              GpioGetValue[3] = {0x00, 0xF8, 0x2B};
    192    uint8_t              GpioSetValue[4];
    193    uint8_t              gpioValue;
    194    uint8_t              Output_Buff[10];
    195    uint8_t              reg_value;
    196    uint8_t              mask_value;
    197    struct nfc_jni_callback_data cb_data;
    198    struct nfc_jni_callback_data cb_data_SE_Notification;
    199 
    200    /* Create the local semaphore */
    201    if (!nfc_cb_data_init(&cb_data, NULL))
    202    {
    203       goto clean_and_return;
    204    }
    205 
    206    /* Create the local semaphore */
    207    if (!nfc_cb_data_init(&cb_data_SE_Notification, NULL))
    208    {
    209       goto clean_and_return;
    210    }
    211 
    212    /* Registery */
    213    registry_info.MifareUL = TRUE;
    214    registry_info.MifareStd = TRUE;
    215    registry_info.ISO14443_4A = TRUE;
    216    registry_info.ISO14443_4B = TRUE;
    217    registry_info.Jewel = TRUE;
    218    registry_info.Felica = TRUE;
    219    registry_info.NFC = FALSE;
    220 
    221    CONCURRENCY_LOCK();
    222 
    223    TRACE("Open Secure Element");
    224 
    225    /* Check if NFC device is already connected to a tag or P2P peer */
    226    if (device_connected_flag == 1)
    227    {
    228        ALOGE("Unable to open SE connection, device already connected to a P2P peer or a Tag");
    229        errorCode = EE_ERROR_LISTEN_MODE;
    230        goto clean_and_return;
    231    }
    232 
    233    /* Test if External RF field is detected */
    234    InParam.buffer = ExternalRFDetected;
    235    InParam.length = 3;
    236    OutParam.buffer = Output_Buff;
    237    TRACE("phLibNfc_Mgt_IoCtl()");
    238    REENTRANCE_LOCK();
    239    ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    240    REENTRANCE_UNLOCK();
    241    if(ret!=NFCSTATUS_PENDING)
    242    {
    243       ALOGE("IOCTL status error");
    244       goto clean_and_return;
    245    }
    246 
    247    /* Wait for callback response */
    248    if(sem_wait(&cb_data.sem))
    249    {
    250       ALOGE("IOCTL semaphore error");
    251       goto clean_and_return;
    252    }
    253 
    254    if(cb_data.status != NFCSTATUS_SUCCESS)
    255    {
    256       ALOGE("READ MEM ERROR");
    257       goto clean_and_return;
    258    }
    259 
    260    /* Check the value */
    261    reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0];
    262    mask_value = reg_value & 0x40;
    263 
    264    if(mask_value == 0x40)
    265    {
    266       // There is an external RF field present, fail the open request
    267       ALOGD("Unable to open SE connection, external RF Field detected");
    268       errorCode = EE_ERROR_EXT_FIELD;
    269       goto clean_and_return;
    270    }
    271 
    272    /* Get Secure Element List */
    273    TRACE("phLibNfc_SE_GetSecureElementList()");
    274    ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE);
    275    if (ret == NFCSTATUS_SUCCESS)
    276    {
    277       TRACE("\n> Number of Secure Element(s) : %d\n", No_SE);
    278       /* Display Secure Element information */
    279       for (i = 0; i<No_SE; i++)
    280       {
    281          if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX)
    282          {
    283            TRACE("> SMX detected");
    284            TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement);
    285            /* save SMARTMX index */
    286            SmartMX_detected = 1;
    287            SmartMX_index = i;
    288          }
    289       }
    290 
    291       if(SmartMX_detected)
    292       {
    293          REENTRANCE_LOCK();
    294          TRACE("phLibNfc_RemoteDev_NtfRegister()");
    295          ret = phLibNfc_RemoteDev_NtfRegister(&registry_info,
    296                  com_android_nfc_jni_open_secure_element_notification_callback,
    297                  (void *)&cb_data_SE_Notification);
    298          REENTRANCE_UNLOCK();
    299          if(ret != NFCSTATUS_SUCCESS)
    300          {
    301             ALOGE("Register Notification error");
    302             goto clean_and_return;
    303          }
    304 
    305          /* Set wired mode */
    306          REENTRANCE_LOCK();
    307          TRACE("phLibNfc_SE_SetMode: Wired mode");
    308          ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement,
    309                                      phLibNfc_SE_ActModeWired,
    310                                      com_android_nfc_jni_smartMX_setModeCb,
    311                                      (void *)&cb_data);
    312          REENTRANCE_UNLOCK();
    313          if (ret != NFCSTATUS_PENDING )
    314          {
    315             ALOGE("\n> SE Set SmartMX mode ERROR \n" );
    316             goto clean_and_return;
    317          }
    318 
    319          /* Wait for callback response */
    320          if(sem_wait(&cb_data.sem))
    321          {
    322             ALOGE("Secure Element opening error");
    323             goto clean_and_return;
    324          }
    325 
    326          if(cb_data.status != NFCSTATUS_SUCCESS)
    327          {
    328             ALOGE("SE set mode failed");
    329             goto clean_and_return;
    330          }
    331 
    332          TRACE("Waiting for notification");
    333          /* Wait for callback response */
    334          if(sem_wait(&cb_data_SE_Notification.sem))
    335          {
    336             ALOGE("Secure Element opening error");
    337             goto clean_and_return;
    338          }
    339 
    340          if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS &&
    341                  cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS)
    342          {
    343             ALOGE("SE detection failed");
    344             goto clean_and_return;
    345          }
    346          CONCURRENCY_UNLOCK();
    347 
    348          /* Connect Tag */
    349          CONCURRENCY_LOCK();
    350          TRACE("phLibNfc_RemoteDev_Connect(SMX)");
    351          REENTRANCE_LOCK();
    352          ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data);
    353          REENTRANCE_UNLOCK();
    354          if(ret != NFCSTATUS_PENDING)
    355          {
    356             ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    357             goto clean_and_return;
    358          }
    359          TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    360 
    361          /* Wait for callback response */
    362          if(sem_wait(&cb_data.sem))
    363          {
    364              ALOGE("CONNECT semaphore error");
    365              goto clean_and_return;
    366          }
    367 
    368          /* Connect Status */
    369          if(cb_data.status != NFCSTATUS_SUCCESS)
    370          {
    371             ALOGE("Secure Element connect error");
    372             goto clean_and_return;
    373          }
    374 
    375          CONCURRENCY_UNLOCK();
    376 
    377          /* Get GPIO information */
    378          CONCURRENCY_LOCK();
    379          InParam.buffer = GpioGetValue;
    380          InParam.length = 3;
    381          OutParam.buffer = Output_Buff;
    382          TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
    383          REENTRANCE_LOCK();
    384          ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    385          REENTRANCE_UNLOCK();
    386          if(ret!=NFCSTATUS_PENDING)
    387          {
    388              ALOGE("IOCTL status error");
    389          }
    390 
    391          /* Wait for callback response */
    392          if(sem_wait(&cb_data.sem))
    393          {
    394             ALOGE("IOCTL semaphore error");
    395             goto clean_and_return;
    396          }
    397 
    398          if(cb_data.status != NFCSTATUS_SUCCESS)
    399          {
    400             ALOGE("READ MEM ERROR");
    401             goto clean_and_return;
    402          }
    403 
    404          gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
    405          TRACE("GpioValue = Ox%02x",gpioValue);
    406 
    407          /* Set GPIO information */
    408          GpioSetValue[0] = 0x00;
    409          GpioSetValue[1] = 0xF8;
    410          GpioSetValue[2] = 0x2B;
    411          GpioSetValue[3] = (gpioValue | 0x40);
    412 
    413          TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
    414 
    415          for(i=0;i<4;i++)
    416          {
    417              TRACE("0x%02x",GpioSetValue[i]);
    418          }
    419 
    420          InParam.buffer = GpioSetValue;
    421          InParam.length = 4;
    422          OutParam.buffer = Output_Buff;
    423          TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
    424          REENTRANCE_LOCK();
    425          ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    426          REENTRANCE_UNLOCK();
    427          if(ret!=NFCSTATUS_PENDING)
    428          {
    429              ALOGE("IOCTL status error");
    430              goto clean_and_return;
    431          }
    432 
    433          /* Wait for callback response */
    434          if(sem_wait(&cb_data.sem))
    435          {
    436             ALOGE("IOCTL semaphore error");
    437             goto clean_and_return;
    438          }
    439 
    440          if(cb_data.status != NFCSTATUS_SUCCESS)
    441          {
    442             ALOGE("READ MEM ERROR");
    443             goto clean_and_return;
    444          }
    445          CONCURRENCY_UNLOCK();
    446 
    447          nfc_cb_data_deinit(&cb_data);
    448          nfc_cb_data_deinit(&cb_data_SE_Notification);
    449 
    450          /* Return the Handle of the SecureElement */
    451          return secureElementHandle;
    452       }
    453       else
    454       {
    455          ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected");
    456          goto clean_and_return;
    457       }
    458   }
    459   else
    460   {
    461       ALOGE("phLibNfc_SE_GetSecureElementList(): Error");
    462       goto clean_and_return;
    463   }
    464 
    465 clean_and_return:
    466    nfc_cb_data_deinit(&cb_data);
    467    nfc_cb_data_deinit(&cb_data_SE_Notification);
    468 
    469    CONCURRENCY_UNLOCK();
    470    return errorCode;
    471 }
    472 
    473 
    474 static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle)
    475 {
    476    jclass cls;
    477    jfieldID f;
    478    NFCSTATUS status;
    479    jboolean result = JNI_FALSE;
    480    phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
    481    uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
    482    uint32_t SmartMX_Handle;
    483    struct nfc_jni_callback_data cb_data;
    484    phNfc_sData_t    InParam;
    485    phNfc_sData_t    OutParam;
    486    uint8_t          Output_Buff[10];
    487    uint8_t          GpioGetValue[3] = {0x00, 0xF8, 0x2B};
    488    uint8_t          GpioSetValue[4];
    489    uint8_t          gpioValue;
    490 
    491    /* Create the local semaphore */
    492    if (!nfc_cb_data_init(&cb_data, NULL))
    493    {
    494       goto clean_and_return;
    495    }
    496 
    497    TRACE("Close Secure element function ");
    498 
    499    CONCURRENCY_LOCK();
    500    /* Disconnect */
    501    TRACE("Disconnecting from SMX (handle = 0x%x)", handle);
    502    REENTRANCE_LOCK();
    503    status = phLibNfc_RemoteDev_Disconnect(handle,
    504                                           NFC_SMARTMX_RELEASE,
    505                                           com_android_nfc_jni_disconnect_callback,
    506                                           (void *)&cb_data);
    507    REENTRANCE_UNLOCK();
    508    if(status != NFCSTATUS_PENDING)
    509    {
    510       ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    511       goto clean_and_return;
    512    }
    513    TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    514 
    515    /* Wait for callback response */
    516    if(sem_wait(&cb_data.sem))
    517    {
    518        goto clean_and_return;
    519    }
    520 
    521    /* Disconnect Status */
    522    if(cb_data.status != NFCSTATUS_SUCCESS)
    523    {
    524      ALOGE("\n> Disconnect SE ERROR \n" );
    525       goto clean_and_return;
    526    }
    527    CONCURRENCY_UNLOCK();
    528 
    529    /* Get GPIO information */
    530    CONCURRENCY_LOCK();
    531    InParam.buffer = GpioGetValue;
    532    InParam.length = 3;
    533    OutParam.buffer = Output_Buff;
    534    TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
    535    REENTRANCE_LOCK();
    536    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    537    REENTRANCE_UNLOCK();
    538    if(status!=NFCSTATUS_PENDING)
    539    {
    540        ALOGE("IOCTL status error");
    541        goto clean_and_return;
    542    }
    543 
    544    /* Wait for callback response */
    545    if(sem_wait(&cb_data.sem))
    546    {
    547       ALOGE("IOCTL semaphore error");
    548       goto clean_and_return;
    549    }
    550 
    551    if(cb_data.status != NFCSTATUS_SUCCESS)
    552    {
    553       ALOGE("READ MEM ERROR");
    554       goto clean_and_return;
    555    }
    556 
    557    gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
    558    TRACE("GpioValue = Ox%02x",gpioValue);
    559 
    560    /* Set GPIO information */
    561    GpioSetValue[0] = 0x00;
    562    GpioSetValue[1] = 0xF8;
    563    GpioSetValue[2] = 0x2B;
    564    GpioSetValue[3] = (gpioValue & 0xBF);
    565 
    566    TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
    567 
    568    for(i=0;i<4;i++)
    569    {
    570        TRACE("0x%02x",GpioSetValue[i]);
    571    }
    572 
    573    InParam.buffer = GpioSetValue;
    574    InParam.length = 4;
    575    OutParam.buffer = Output_Buff;
    576    TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
    577    REENTRANCE_LOCK();
    578    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    579    REENTRANCE_UNLOCK();
    580    if(status!=NFCSTATUS_PENDING)
    581    {
    582        ALOGE("IOCTL status error");
    583        goto clean_and_return;
    584    }
    585 
    586    /* Wait for callback response */
    587    if(sem_wait(&cb_data.sem))
    588    {
    589       ALOGE("IOCTL semaphore error");
    590       goto clean_and_return;
    591    }
    592 
    593    if(cb_data.status != NFCSTATUS_SUCCESS)
    594    {
    595       ALOGE("READ MEM ERROR");
    596       goto clean_and_return;
    597    }
    598 
    599    result = JNI_TRUE;
    600 
    601 clean_and_return:
    602    nfc_cb_data_deinit(&cb_data);
    603 
    604    CONCURRENCY_UNLOCK();
    605    return result;
    606 }
    607 
    608 static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e,
    609    jobject o,jint handle, jbyteArray data)
    610 {
    611    uint8_t offset = 0;
    612    uint8_t *buf;
    613    uint32_t buflen;
    614    phLibNfc_sTransceiveInfo_t transceive_info;
    615    jbyteArray result = NULL;
    616    int res;
    617 
    618    int tech = SecureElementTech;
    619    NFCSTATUS status;
    620    struct nfc_jni_callback_data cb_data;
    621 
    622    /* Create the local semaphore */
    623    if (!nfc_cb_data_init(&cb_data, NULL))
    624    {
    625       goto clean_and_return;
    626    }
    627 
    628    TRACE("Exchange APDU function ");
    629 
    630    CONCURRENCY_LOCK();
    631 
    632    TRACE("Secure Element tech: %d\n", tech);
    633 
    634    buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
    635    buflen = (uint32_t)e->GetArrayLength(data);
    636 
    637    /* Prepare transceive info structure */
    638    if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL)
    639    {
    640       offset = 2;
    641       transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
    642       transceive_info.addr = (uint8_t)buf[1];
    643    }
    644    else if(tech == TARGET_TYPE_ISO14443_4)
    645    {
    646       transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
    647       transceive_info.addr = 0;
    648    }
    649 
    650    transceive_info.sSendData.buffer = buf + offset;
    651    transceive_info.sSendData.length = buflen - offset;
    652    transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
    653    transceive_info.sRecvData.length = 1024;
    654 
    655    if(transceive_info.sRecvData.buffer == NULL)
    656    {
    657       goto clean_and_return;
    658    }
    659 
    660    TRACE("phLibNfc_RemoteDev_Transceive(SMX)");
    661    REENTRANCE_LOCK();
    662    status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
    663 		   com_android_nfc_jni_transceive_callback, (void *)&cb_data);
    664    REENTRANCE_UNLOCK();
    665    if(status != NFCSTATUS_PENDING)
    666    {
    667       ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    668       goto clean_and_return;
    669    }
    670    TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    671 
    672    /* Wait for callback response */
    673    if(sem_wait(&cb_data.sem))
    674    {
    675        ALOGE("TRANSCEIVE semaphore error");
    676        goto clean_and_return;
    677    }
    678 
    679    if(cb_data.status != NFCSTATUS_SUCCESS)
    680    {
    681       ALOGE("TRANSCEIVE error");
    682       goto clean_and_return;
    683    }
    684 
    685    /* Copy results back to Java */
    686    result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length);
    687    if(result != NULL)
    688    {
    689       e->SetByteArrayRegion(result, 0,
    690     		  com_android_nfc_jni_transceive_buffer->length,
    691          (jbyte *)com_android_nfc_jni_transceive_buffer->buffer);
    692    }
    693 
    694 clean_and_return:
    695    nfc_cb_data_deinit(&cb_data);
    696 
    697    if(transceive_info.sRecvData.buffer != NULL)
    698    {
    699       free(transceive_info.sRecvData.buffer);
    700    }
    701 
    702    e->ReleaseByteArrayElements(data,
    703       (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);
    704 
    705    CONCURRENCY_UNLOCK();
    706 
    707    return result;
    708 }
    709 
    710 static jbyteArray com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv *e, jobject o, jint handle)
    711 {
    712    TRACE("Get Secure element UID function ");
    713    jbyteArray SecureElementUid;
    714 
    715    if(handle == secureElementHandle)
    716    {
    717       SecureElementUid = e->NewByteArray(SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength);
    718       e->SetByteArrayRegion(SecureElementUid, 0, SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength,(jbyte *)SecureElementInfo->RemoteDevInfo.Iso14443A_Info.Uid);
    719       return SecureElementUid;
    720    }
    721    else
    722    {
    723       return NULL;
    724    }
    725 }
    726 
    727 static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jobject o, jint handle)
    728 {
    729    jintArray techList;
    730    TRACE("Get Secure element Type function ");
    731 
    732    if (handle != secureElementHandle) {
    733       return NULL;
    734    }
    735    jintArray result = e->NewIntArray(1);
    736    e->SetIntArrayRegion(result, 0, 1, &SecureElementTech);
    737    return result;
    738 }
    739 
    740 
    741 /*
    742  * JNI registration.
    743  */
    744 static JNINativeMethod gMethods[] =
    745 {
    746    {"doNativeOpenSecureElementConnection", "()I",
    747       (void *)com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection},
    748    {"doNativeDisconnectSecureElementConnection", "(I)Z",
    749       (void *)com_android_nfc_NativeNfcSecureElement_doDisconnect},
    750    {"doTransceive", "(I[B)[B",
    751       (void *)com_android_nfc_NativeNfcSecureElement_doTransceive},
    752    {"doGetUid", "(I)[B",
    753       (void *)com_android_nfc_NativeNfcSecureElement_doGetUid},
    754    {"doGetTechList", "(I)[I",
    755       (void *)com_android_nfc_NativeNfcSecureElement_doGetTechList},
    756 };
    757 
    758 int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e)
    759 {
    760    return jniRegisterNativeMethods(e,
    761       "com/android/nfc/dhimpl/NativeNfcSecureElement",
    762       gMethods, NELEM(gMethods));
    763 }
    764 
    765 } // namespace android
    766