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       jintArray techList;
    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 != NULL) && e->GetArrayLength(techList) > 0) {
    160          e->GetIntArrayRegion(techList, 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       // This thread may not return to the virtual machine for a long time
    172       // so make sure to delete the local refernce to the tech list.
    173       e->DeleteLocalRef(techList);
    174    }
    175 
    176 clean_and_return:
    177    pContextData->status = status;
    178    sem_post(&pContextData->sem);
    179 }
    180 
    181 
    182 static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o)
    183 {
    184    NFCSTATUS ret;
    185    int semResult;
    186 
    187    phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
    188    uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
    189    phLibNfc_sADD_Cfg_t discovery_cfg;
    190    phLibNfc_Registry_Info_t registry_info;
    191    phNfc_sData_t        InParam;
    192    phNfc_sData_t        OutParam;
    193    uint8_t              ExternalRFDetected[3] = {0x00, 0xFC, 0x01};
    194    uint8_t              GpioGetValue[3] = {0x00, 0xF8, 0x2B};
    195    uint8_t              GpioSetValue[4];
    196    uint8_t              gpioValue;
    197    uint8_t              Output_Buff[10];
    198    uint8_t              reg_value;
    199    uint8_t              mask_value;
    200    struct nfc_jni_callback_data cb_data;
    201    struct nfc_jni_callback_data cb_data_SE_Notification;
    202 
    203    /* Create the local semaphore */
    204    if (!nfc_cb_data_init(&cb_data, NULL))
    205    {
    206       goto clean_and_return;
    207    }
    208 
    209    /* Create the local semaphore */
    210    if (!nfc_cb_data_init(&cb_data_SE_Notification, NULL))
    211    {
    212       goto clean_and_return;
    213    }
    214 
    215    /* Registery */
    216    registry_info.MifareUL = TRUE;
    217    registry_info.MifareStd = TRUE;
    218    registry_info.ISO14443_4A = TRUE;
    219    registry_info.ISO14443_4B = TRUE;
    220    registry_info.Jewel = TRUE;
    221    registry_info.Felica = TRUE;
    222    registry_info.NFC = FALSE;
    223 
    224    CONCURRENCY_LOCK();
    225 
    226    TRACE("Open Secure Element");
    227 
    228    /* Check if NFC device is already connected to a tag or P2P peer */
    229    if (device_connected_flag == 1)
    230    {
    231        ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag");
    232        goto clean_and_return;
    233    }
    234 
    235    /* Test if External RF field is detected */
    236    InParam.buffer = ExternalRFDetected;
    237    InParam.length = 3;
    238    OutParam.buffer = Output_Buff;
    239    TRACE("phLibNfc_Mgt_IoCtl()");
    240    REENTRANCE_LOCK();
    241    ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    242    REENTRANCE_UNLOCK();
    243    if(ret!=NFCSTATUS_PENDING)
    244    {
    245       ALOGE("IOCTL status error");
    246       goto clean_and_return;
    247    }
    248 
    249    /* Wait for callback response */
    250    if(sem_wait(&cb_data.sem))
    251    {
    252       ALOGE("IOCTL semaphore error");
    253       goto clean_and_return;
    254    }
    255 
    256    if(cb_data.status != NFCSTATUS_SUCCESS)
    257    {
    258       ALOGE("READ MEM ERROR");
    259       goto clean_and_return;
    260    }
    261 
    262    /* Check the value */
    263    reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0];
    264    mask_value = reg_value & 0x40;
    265 
    266    if(mask_value == 0x40)
    267    {
    268       // There is an external RF field present, fail the open request
    269       ALOGD("Unable to open SE connection, external RF Field detected");
    270       goto clean_and_return;
    271    }
    272 
    273    /* Get Secure Element List */
    274    TRACE("phLibNfc_SE_GetSecureElementList()");
    275    ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE);
    276    if (ret == NFCSTATUS_SUCCESS)
    277    {
    278       TRACE("\n> Number of Secure Element(s) : %d\n", No_SE);
    279       /* Display Secure Element information */
    280       for (i = 0; i<No_SE; i++)
    281       {
    282          if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX)
    283          {
    284            TRACE("> SMX detected");
    285            TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement);
    286            /* save SMARTMX index */
    287            SmartMX_detected = 1;
    288            SmartMX_index = i;
    289          }
    290       }
    291 
    292       if(SmartMX_detected)
    293       {
    294          REENTRANCE_LOCK();
    295          TRACE("phLibNfc_RemoteDev_NtfRegister()");
    296          ret = phLibNfc_RemoteDev_NtfRegister(&registry_info,
    297                  com_android_nfc_jni_open_secure_element_notification_callback,
    298                  (void *)&cb_data_SE_Notification);
    299          REENTRANCE_UNLOCK();
    300          if(ret != NFCSTATUS_SUCCESS)
    301          {
    302             ALOGE("Register Notification error");
    303             goto clean_and_return;
    304          }
    305 
    306          /* Set wired mode */
    307          REENTRANCE_LOCK();
    308          TRACE("phLibNfc_SE_SetMode: Wired mode");
    309          ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement,
    310                                      phLibNfc_SE_ActModeWired,
    311                                      com_android_nfc_jni_smartMX_setModeCb,
    312                                      (void *)&cb_data);
    313          REENTRANCE_UNLOCK();
    314          if (ret != NFCSTATUS_PENDING )
    315          {
    316             ALOGE("\n> SE Set SmartMX mode ERROR \n" );
    317             goto clean_and_return;
    318          }
    319 
    320          /* Wait for callback response */
    321          if(sem_wait(&cb_data.sem))
    322          {
    323             ALOGE("Secure Element opening error");
    324             goto clean_and_return;
    325          }
    326 
    327          if(cb_data.status != NFCSTATUS_SUCCESS)
    328          {
    329             ALOGE("SE set mode failed");
    330             goto clean_and_return;
    331          }
    332 
    333          TRACE("Waiting for notification");
    334          /* Wait for callback response */
    335          if(sem_wait(&cb_data_SE_Notification.sem))
    336          {
    337             ALOGE("Secure Element opening error");
    338             goto clean_and_return;
    339          }
    340 
    341          if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS &&
    342                  cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS)
    343          {
    344             ALOGE("SE detection failed");
    345             goto clean_and_return;
    346          }
    347          CONCURRENCY_UNLOCK();
    348 
    349          /* Connect Tag */
    350          CONCURRENCY_LOCK();
    351          TRACE("phLibNfc_RemoteDev_Connect(SMX)");
    352          REENTRANCE_LOCK();
    353          ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data);
    354          REENTRANCE_UNLOCK();
    355          if(ret != NFCSTATUS_PENDING)
    356          {
    357             ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    358             goto clean_and_return;
    359          }
    360          TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
    361 
    362          /* Wait for callback response */
    363          if(sem_wait(&cb_data.sem))
    364          {
    365              ALOGE("CONNECT semaphore error");
    366              goto clean_and_return;
    367          }
    368 
    369          /* Connect Status */
    370          if(cb_data.status != NFCSTATUS_SUCCESS)
    371          {
    372             ALOGE("Secure Element connect error");
    373             goto clean_and_return;
    374          }
    375 
    376          CONCURRENCY_UNLOCK();
    377 
    378          /* Get GPIO information */
    379          CONCURRENCY_LOCK();
    380          InParam.buffer = GpioGetValue;
    381          InParam.length = 3;
    382          OutParam.buffer = Output_Buff;
    383          TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
    384          REENTRANCE_LOCK();
    385          ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    386          REENTRANCE_UNLOCK();
    387          if(ret!=NFCSTATUS_PENDING)
    388          {
    389              ALOGE("IOCTL status error");
    390          }
    391 
    392          /* Wait for callback response */
    393          if(sem_wait(&cb_data.sem))
    394          {
    395             ALOGE("IOCTL semaphore error");
    396             goto clean_and_return;
    397          }
    398 
    399          if(cb_data.status != NFCSTATUS_SUCCESS)
    400          {
    401             ALOGE("READ MEM ERROR");
    402             goto clean_and_return;
    403          }
    404 
    405          gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
    406          TRACE("GpioValue = Ox%02x",gpioValue);
    407 
    408          /* Set GPIO information */
    409          GpioSetValue[0] = 0x00;
    410          GpioSetValue[1] = 0xF8;
    411          GpioSetValue[2] = 0x2B;
    412          GpioSetValue[3] = (gpioValue | 0x40);
    413 
    414          TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
    415 
    416          for(i=0;i<4;i++)
    417          {
    418              TRACE("0x%02x",GpioSetValue[i]);
    419          }
    420 
    421          InParam.buffer = GpioSetValue;
    422          InParam.length = 4;
    423          OutParam.buffer = Output_Buff;
    424          TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
    425          REENTRANCE_LOCK();
    426          ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    427          REENTRANCE_UNLOCK();
    428          if(ret!=NFCSTATUS_PENDING)
    429          {
    430              ALOGE("IOCTL status error");
    431              goto clean_and_return;
    432          }
    433 
    434          /* Wait for callback response */
    435          if(sem_wait(&cb_data.sem))
    436          {
    437             ALOGE("IOCTL semaphore error");
    438             goto clean_and_return;
    439          }
    440 
    441          if(cb_data.status != NFCSTATUS_SUCCESS)
    442          {
    443             ALOGE("READ MEM ERROR");
    444             goto clean_and_return;
    445          }
    446          CONCURRENCY_UNLOCK();
    447 
    448          nfc_cb_data_deinit(&cb_data);
    449          nfc_cb_data_deinit(&cb_data_SE_Notification);
    450 
    451          /* Return the Handle of the SecureElement */
    452          return secureElementHandle;
    453       }
    454       else
    455       {
    456          ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected");
    457          goto clean_and_return;
    458       }
    459   }
    460   else
    461   {
    462       ALOGE("phLibNfc_SE_GetSecureElementList(): Error");
    463       goto clean_and_return;
    464   }
    465 
    466 clean_and_return:
    467    nfc_cb_data_deinit(&cb_data);
    468    nfc_cb_data_deinit(&cb_data_SE_Notification);
    469 
    470    CONCURRENCY_UNLOCK();
    471    return 0;
    472 }
    473 
    474 
    475 static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle)
    476 {
    477    jclass cls;
    478    jfieldID f;
    479    NFCSTATUS status;
    480    jboolean result = JNI_FALSE;
    481    phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
    482    uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
    483    uint32_t SmartMX_Handle;
    484    struct nfc_jni_callback_data cb_data;
    485    phNfc_sData_t    InParam;
    486    phNfc_sData_t    OutParam;
    487    uint8_t          Output_Buff[10];
    488    uint8_t          GpioGetValue[3] = {0x00, 0xF8, 0x2B};
    489    uint8_t          GpioSetValue[4];
    490    uint8_t          gpioValue;
    491 
    492    /* Create the local semaphore */
    493    if (!nfc_cb_data_init(&cb_data, NULL))
    494    {
    495       goto clean_and_return;
    496    }
    497 
    498    TRACE("Close Secure element function ");
    499 
    500    CONCURRENCY_LOCK();
    501    /* Disconnect */
    502    TRACE("Disconnecting from SMX (handle = 0x%x)", handle);
    503    REENTRANCE_LOCK();
    504    status = phLibNfc_RemoteDev_Disconnect(handle,
    505                                           NFC_SMARTMX_RELEASE,
    506                                           com_android_nfc_jni_disconnect_callback,
    507                                           (void *)&cb_data);
    508    REENTRANCE_UNLOCK();
    509    if(status != NFCSTATUS_PENDING)
    510    {
    511       ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    512       goto clean_and_return;
    513    }
    514    TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    515 
    516    /* Wait for callback response */
    517    if(sem_wait(&cb_data.sem))
    518    {
    519        goto clean_and_return;
    520    }
    521 
    522    /* Disconnect Status */
    523    if(cb_data.status != NFCSTATUS_SUCCESS)
    524    {
    525      ALOGE("\n> Disconnect SE ERROR \n" );
    526       goto clean_and_return;
    527    }
    528    CONCURRENCY_UNLOCK();
    529 
    530    /* Get GPIO information */
    531    CONCURRENCY_LOCK();
    532    InParam.buffer = GpioGetValue;
    533    InParam.length = 3;
    534    OutParam.buffer = Output_Buff;
    535    TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
    536    REENTRANCE_LOCK();
    537    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    538    REENTRANCE_UNLOCK();
    539    if(status!=NFCSTATUS_PENDING)
    540    {
    541        ALOGE("IOCTL status error");
    542        goto clean_and_return;
    543    }
    544 
    545    /* Wait for callback response */
    546    if(sem_wait(&cb_data.sem))
    547    {
    548       ALOGE("IOCTL semaphore error");
    549       goto clean_and_return;
    550    }
    551 
    552    if(cb_data.status != NFCSTATUS_SUCCESS)
    553    {
    554       ALOGE("READ MEM ERROR");
    555       goto clean_and_return;
    556    }
    557 
    558    gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
    559    TRACE("GpioValue = Ox%02x",gpioValue);
    560 
    561    /* Set GPIO information */
    562    GpioSetValue[0] = 0x00;
    563    GpioSetValue[1] = 0xF8;
    564    GpioSetValue[2] = 0x2B;
    565    GpioSetValue[3] = (gpioValue & 0xBF);
    566 
    567    TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
    568 
    569    for(i=0;i<4;i++)
    570    {
    571        TRACE("0x%02x",GpioSetValue[i]);
    572    }
    573 
    574    InParam.buffer = GpioSetValue;
    575    InParam.length = 4;
    576    OutParam.buffer = Output_Buff;
    577    TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
    578    REENTRANCE_LOCK();
    579    status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
    580    REENTRANCE_UNLOCK();
    581    if(status!=NFCSTATUS_PENDING)
    582    {
    583        ALOGE("IOCTL status error");
    584        goto clean_and_return;
    585    }
    586 
    587    /* Wait for callback response */
    588    if(sem_wait(&cb_data.sem))
    589    {
    590       ALOGE("IOCTL semaphore error");
    591       goto clean_and_return;
    592    }
    593 
    594    if(cb_data.status != NFCSTATUS_SUCCESS)
    595    {
    596       ALOGE("READ MEM ERROR");
    597       goto clean_and_return;
    598    }
    599 
    600    result = JNI_TRUE;
    601 
    602 clean_and_return:
    603    nfc_cb_data_deinit(&cb_data);
    604 
    605    CONCURRENCY_UNLOCK();
    606    return result;
    607 }
    608 
    609 static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e,
    610    jobject o,jint handle, jbyteArray data)
    611 {
    612    uint8_t offset = 0;
    613    uint8_t *buf;
    614    uint32_t buflen;
    615    phLibNfc_sTransceiveInfo_t transceive_info;
    616    jbyteArray result = NULL;
    617    int res;
    618 
    619    int tech = SecureElementTech;
    620    NFCSTATUS status;
    621    struct nfc_jni_callback_data cb_data;
    622 
    623    /* Create the local semaphore */
    624    if (!nfc_cb_data_init(&cb_data, NULL))
    625    {
    626       goto clean_and_return;
    627    }
    628 
    629    TRACE("Exchange APDU function ");
    630 
    631    CONCURRENCY_LOCK();
    632 
    633    TRACE("Secure Element tech: %d\n", tech);
    634 
    635    buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
    636    buflen = (uint32_t)e->GetArrayLength(data);
    637 
    638    /* Prepare transceive info structure */
    639    if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL)
    640    {
    641       offset = 2;
    642       transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
    643       transceive_info.addr = (uint8_t)buf[1];
    644    }
    645    else if(tech == TARGET_TYPE_ISO14443_4)
    646    {
    647       transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
    648       transceive_info.addr = 0;
    649    }
    650 
    651    transceive_info.sSendData.buffer = buf + offset;
    652    transceive_info.sSendData.length = buflen - offset;
    653    transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
    654    transceive_info.sRecvData.length = 1024;
    655 
    656    if(transceive_info.sRecvData.buffer == NULL)
    657    {
    658       goto clean_and_return;
    659    }
    660 
    661    TRACE("phLibNfc_RemoteDev_Transceive(SMX)");
    662    REENTRANCE_LOCK();
    663    status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
    664 		   com_android_nfc_jni_transceive_callback, (void *)&cb_data);
    665    REENTRANCE_UNLOCK();
    666    if(status != NFCSTATUS_PENDING)
    667    {
    668       ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    669       goto clean_and_return;
    670    }
    671    TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
    672 
    673    /* Wait for callback response */
    674    if(sem_wait(&cb_data.sem))
    675    {
    676        ALOGE("TRANSCEIVE semaphore error");
    677        goto clean_and_return;
    678    }
    679 
    680    if(cb_data.status != NFCSTATUS_SUCCESS)
    681    {
    682       ALOGE("TRANSCEIVE error");
    683       goto clean_and_return;
    684    }
    685 
    686    /* Copy results back to Java */
    687    result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length);
    688    if(result != NULL)
    689    {
    690       e->SetByteArrayRegion(result, 0,
    691     		  com_android_nfc_jni_transceive_buffer->length,
    692          (jbyte *)com_android_nfc_jni_transceive_buffer->buffer);
    693    }
    694 
    695 clean_and_return:
    696    nfc_cb_data_deinit(&cb_data);
    697 
    698    if(transceive_info.sRecvData.buffer != NULL)
    699    {
    700       free(transceive_info.sRecvData.buffer);
    701    }
    702 
    703    e->ReleaseByteArrayElements(data,
    704       (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);
    705 
    706    CONCURRENCY_UNLOCK();
    707 
    708    return result;
    709 }
    710 
    711 static jbyteArray com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv *e, jobject o, jint handle)
    712 {
    713    TRACE("Get Secure element UID function ");
    714    jbyteArray SecureElementUid;
    715 
    716    if(handle == secureElementHandle)
    717    {
    718       SecureElementUid = e->NewByteArray(SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength);
    719       e->SetByteArrayRegion(SecureElementUid, 0, SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength,(jbyte *)SecureElementInfo->RemoteDevInfo.Iso14443A_Info.Uid);
    720       return SecureElementUid;
    721    }
    722    else
    723    {
    724       return NULL;
    725    }
    726 }
    727 
    728 static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jobject o, jint handle)
    729 {
    730    jintArray techList;
    731    TRACE("Get Secure element Type function ");
    732 
    733    if(handle == secureElementHandle)
    734    {
    735       techList = e->NewIntArray(1);
    736       e->SetIntArrayRegion(techList, 0, 1, &SecureElementTech);
    737       return techList;
    738    }
    739    else
    740    {
    741       return NULL;
    742    }
    743 }
    744 
    745 
    746 /*
    747  * JNI registration.
    748  */
    749 static JNINativeMethod gMethods[] =
    750 {
    751    {"doNativeOpenSecureElementConnection", "()I",
    752       (void *)com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection},
    753    {"doNativeDisconnectSecureElementConnection", "(I)Z",
    754       (void *)com_android_nfc_NativeNfcSecureElement_doDisconnect},
    755    {"doTransceive", "(I[B)[B",
    756       (void *)com_android_nfc_NativeNfcSecureElement_doTransceive},
    757    {"doGetUid", "(I)[B",
    758       (void *)com_android_nfc_NativeNfcSecureElement_doGetUid},
    759    {"doGetTechList", "(I)[I",
    760       (void *)com_android_nfc_NativeNfcSecureElement_doGetTechList},
    761 };
    762 
    763 int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e)
    764 {
    765    return jniRegisterNativeMethods(e,
    766       "com/android/nfc/nxp/NativeNfcSecureElement",
    767       gMethods, NELEM(gMethods));
    768 }
    769 
    770 } // namespace android
    771