summaryrefslogtreecommitdiffstats
path: root/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp')
-rwxr-xr-xnxp/jni/com_android_nfc_NativeNfcSecureElement.cpp770
1 files changed, 770 insertions, 0 deletions
diff --git a/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
new file mode 100755
index 0000000..bb1bb2a
--- /dev/null
+++ b/nxp/jni/com_android_nfc_NativeNfcSecureElement.cpp
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <semaphore.h>
+
+#include "com_android_nfc.h"
+
+static phNfc_sData_t *com_android_nfc_jni_transceive_buffer;
+static phNfc_sData_t *com_android_nfc_jni_ioctl_buffer;
+static phNfc_sRemoteDevInformation_t* SecureElementInfo;
+static int secureElementHandle;
+extern void *gHWRef;
+static int SecureElementTech;
+extern uint8_t device_connected_flag;
+
+namespace android {
+
+static void com_android_nfc_jni_ioctl_callback ( void* pContext,
+ phNfc_sData_t* Outparam_Cb,
+ NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+
+ if (status == NFCSTATUS_SUCCESS )
+ {
+ LOG_CALLBACK("> IOCTL successful",status);
+ }
+ else
+ {
+ LOG_CALLBACK("> IOCTL error",status);
+ }
+
+ com_android_nfc_jni_ioctl_buffer = Outparam_Cb;
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+static void com_android_nfc_jni_transceive_callback(void *pContext,
+ phLibNfc_Handle handle, phNfc_sData_t *pResBuffer, NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+
+ LOG_CALLBACK("com_android_nfc_jni_transceive_callback", status);
+
+ com_android_nfc_jni_transceive_buffer = pResBuffer;
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+
+static void com_android_nfc_jni_connect_callback(void *pContext,
+ phLibNfc_Handle hRemoteDev,
+ phLibNfc_sRemoteDevInformation_t *psRemoteDevInfo, NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+
+ LOG_CALLBACK("com_android_nfc_jni_connect_callback", status);
+
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+static void com_android_nfc_jni_disconnect_callback(void *pContext,
+ phLibNfc_Handle hRemoteDev,
+ NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+
+ LOG_CALLBACK("com_android_nfc_jni_disconnect_callback", status);
+
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+/* Set Secure Element mode callback*/
+static void com_android_nfc_jni_smartMX_setModeCb (void* pContext,
+ phLibNfc_Handle hSecureElement,
+ NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+
+ if(status==NFCSTATUS_SUCCESS)
+ {
+ LOG_CALLBACK("SE Set Mode is Successful",status);
+ TRACE("SE Handle: %lu", hSecureElement);
+ }
+ else
+ {
+ LOG_CALLBACK("SE Set Mode is failed\n ",status);
+ }
+
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+static void com_android_nfc_jni_open_secure_element_notification_callback(void *pContext,
+ phLibNfc_RemoteDevList_t *psRemoteDevList,
+ uint8_t uNofRemoteDev,
+ NFCSTATUS status)
+{
+ struct nfc_jni_callback_data * pContextData = (struct nfc_jni_callback_data*)pContext;
+ NFCSTATUS ret;
+ int i;
+ JNIEnv *e = nfc_get_env();
+
+ if(status == NFCSTATUS_DESELECTED)
+ {
+ LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback: Target deselected", status);
+ }
+ else
+ {
+ LOG_CALLBACK("com_android_nfc_jni_open_secure_element_notification_callback", status);
+ TRACE("Discovered %d secure elements", uNofRemoteDev);
+
+ if(status == NFCSTATUS_MULTIPLE_PROTOCOLS)
+ {
+ bool foundHandle = false;
+ TRACE("Multiple Protocol supported\n");
+ for (i=0; i<uNofRemoteDev; i++) {
+ // Always open the phNfc_eISO14443_A_PICC protocol
+ TRACE("Protocol %d handle=%x type=%d", i, psRemoteDevList[i].hTargetDev,
+ psRemoteDevList[i].psRemoteDevInfo->RemDevType);
+ if (psRemoteDevList[i].psRemoteDevInfo->RemDevType == phNfc_eISO14443_A_PICC) {
+ secureElementHandle = psRemoteDevList[i].hTargetDev;
+ foundHandle = true;
+ }
+ }
+ if (!foundHandle) {
+ ALOGE("Could not find ISO-DEP secure element");
+ status = NFCSTATUS_FAILED;
+ goto clean_and_return;
+ }
+ }
+ else
+ {
+ secureElementHandle = psRemoteDevList->hTargetDev;
+ }
+
+ TRACE("Secure Element Handle: 0x%08x", secureElementHandle);
+
+ /* Set type name */
+ jintArray techList;
+ nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL);
+
+ // TODO: Should use the "connected" technology, for now use the first
+ if ((techList != NULL) && e->GetArrayLength(techList) > 0) {
+ e->GetIntArrayRegion(techList, 0, 1, &SecureElementTech);
+ TRACE("Store Secure Element Info\n");
+ SecureElementInfo = psRemoteDevList->psRemoteDevInfo;
+
+ TRACE("Discovered secure element: tech=%d", SecureElementTech);
+ }
+ else {
+ ALOGE("Discovered secure element, but could not resolve tech");
+ status = NFCSTATUS_FAILED;
+ }
+
+ // This thread may not return to the virtual machine for a long time
+ // so make sure to delete the local refernce to the tech list.
+ e->DeleteLocalRef(techList);
+ }
+
+clean_and_return:
+ pContextData->status = status;
+ sem_post(&pContextData->sem);
+}
+
+
+static jint com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection(JNIEnv *e, jobject o)
+{
+ NFCSTATUS ret;
+ int semResult;
+
+ phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
+ uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
+ phLibNfc_sADD_Cfg_t discovery_cfg;
+ phLibNfc_Registry_Info_t registry_info;
+ phNfc_sData_t InParam;
+ phNfc_sData_t OutParam;
+ uint8_t ExternalRFDetected[3] = {0x00, 0xFC, 0x01};
+ uint8_t GpioGetValue[3] = {0x00, 0xF8, 0x2B};
+ uint8_t GpioSetValue[4];
+ uint8_t gpioValue;
+ uint8_t Output_Buff[10];
+ uint8_t reg_value;
+ uint8_t mask_value;
+ struct nfc_jni_callback_data cb_data;
+ struct nfc_jni_callback_data cb_data_SE_Notification;
+
+ /* Create the local semaphore */
+ if (!nfc_cb_data_init(&cb_data, NULL))
+ {
+ goto clean_and_return;
+ }
+
+ /* Create the local semaphore */
+ if (!nfc_cb_data_init(&cb_data_SE_Notification, NULL))
+ {
+ goto clean_and_return;
+ }
+
+ /* Registery */
+ registry_info.MifareUL = TRUE;
+ registry_info.MifareStd = TRUE;
+ registry_info.ISO14443_4A = TRUE;
+ registry_info.ISO14443_4B = TRUE;
+ registry_info.Jewel = TRUE;
+ registry_info.Felica = TRUE;
+ registry_info.NFC = FALSE;
+
+ CONCURRENCY_LOCK();
+
+ TRACE("Open Secure Element");
+
+ /* Check if NFC device is already connected to a tag or P2P peer */
+ if (device_connected_flag == 1)
+ {
+ ALOGD("Unable to open SE connection, device already connected to a P2P peer or a Tag");
+ goto clean_and_return;
+ }
+
+ /* Test if External RF field is detected */
+ InParam.buffer = ExternalRFDetected;
+ InParam.length = 3;
+ OutParam.buffer = Output_Buff;
+ TRACE("phLibNfc_Mgt_IoCtl()");
+ REENTRANCE_LOCK();
+ ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(ret!=NFCSTATUS_PENDING)
+ {
+ ALOGE("IOCTL status error");
+ goto clean_and_return;
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("IOCTL semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("READ MEM ERROR");
+ goto clean_and_return;
+ }
+
+ /* Check the value */
+ reg_value = com_android_nfc_jni_ioctl_buffer->buffer[0];
+ mask_value = reg_value & 0x40;
+
+ if(mask_value == 0x40)
+ {
+ // There is an external RF field present, fail the open request
+ ALOGD("Unable to open SE connection, external RF Field detected");
+ goto clean_and_return;
+ }
+
+ /* Get Secure Element List */
+ TRACE("phLibNfc_SE_GetSecureElementList()");
+ ret = phLibNfc_SE_GetSecureElementList( SE_List, &No_SE);
+ if (ret == NFCSTATUS_SUCCESS)
+ {
+ TRACE("\n> Number of Secure Element(s) : %d\n", No_SE);
+ /* Display Secure Element information */
+ for (i = 0; i<No_SE; i++)
+ {
+ if (SE_List[i].eSE_Type == phLibNfc_SE_Type_SmartMX)
+ {
+ TRACE("> SMX detected");
+ TRACE("> Secure Element Handle : %d\n", SE_List[i].hSecureElement);
+ /* save SMARTMX index */
+ SmartMX_detected = 1;
+ SmartMX_index = i;
+ }
+ }
+
+ if(SmartMX_detected)
+ {
+ REENTRANCE_LOCK();
+ TRACE("phLibNfc_RemoteDev_NtfRegister()");
+ ret = phLibNfc_RemoteDev_NtfRegister(&registry_info,
+ com_android_nfc_jni_open_secure_element_notification_callback,
+ (void *)&cb_data_SE_Notification);
+ REENTRANCE_UNLOCK();
+ if(ret != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("Register Notification error");
+ goto clean_and_return;
+ }
+
+ /* Set wired mode */
+ REENTRANCE_LOCK();
+ TRACE("phLibNfc_SE_SetMode: Wired mode");
+ ret = phLibNfc_SE_SetMode( SE_List[SmartMX_index].hSecureElement,
+ phLibNfc_SE_ActModeWired,
+ com_android_nfc_jni_smartMX_setModeCb,
+ (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if (ret != NFCSTATUS_PENDING )
+ {
+ ALOGE("\n> SE Set SmartMX mode ERROR \n" );
+ goto clean_and_return;
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("Secure Element opening error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("SE set mode failed");
+ goto clean_and_return;
+ }
+
+ TRACE("Waiting for notification");
+ /* Wait for callback response */
+ if(sem_wait(&cb_data_SE_Notification.sem))
+ {
+ ALOGE("Secure Element opening error");
+ goto clean_and_return;
+ }
+
+ if(cb_data_SE_Notification.status != NFCSTATUS_SUCCESS &&
+ cb_data_SE_Notification.status != NFCSTATUS_MULTIPLE_PROTOCOLS)
+ {
+ ALOGE("SE detection failed");
+ goto clean_and_return;
+ }
+ CONCURRENCY_UNLOCK();
+
+ /* Connect Tag */
+ CONCURRENCY_LOCK();
+ TRACE("phLibNfc_RemoteDev_Connect(SMX)");
+ REENTRANCE_LOCK();
+ ret = phLibNfc_RemoteDev_Connect(secureElementHandle, com_android_nfc_jni_connect_callback,(void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(ret != NFCSTATUS_PENDING)
+ {
+ ALOGE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
+ goto clean_and_return;
+ }
+ TRACE("phLibNfc_RemoteDev_Connect(SMX) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret));
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("CONNECT semaphore error");
+ goto clean_and_return;
+ }
+
+ /* Connect Status */
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("Secure Element connect error");
+ goto clean_and_return;
+ }
+
+ CONCURRENCY_UNLOCK();
+
+ /* Get GPIO information */
+ CONCURRENCY_LOCK();
+ InParam.buffer = GpioGetValue;
+ InParam.length = 3;
+ OutParam.buffer = Output_Buff;
+ TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
+ REENTRANCE_LOCK();
+ ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(ret!=NFCSTATUS_PENDING)
+ {
+ ALOGE("IOCTL status error");
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("IOCTL semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("READ MEM ERROR");
+ goto clean_and_return;
+ }
+
+ gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
+ TRACE("GpioValue = Ox%02x",gpioValue);
+
+ /* Set GPIO information */
+ GpioSetValue[0] = 0x00;
+ GpioSetValue[1] = 0xF8;
+ GpioSetValue[2] = 0x2B;
+ GpioSetValue[3] = (gpioValue | 0x40);
+
+ TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
+
+ for(i=0;i<4;i++)
+ {
+ TRACE("0x%02x",GpioSetValue[i]);
+ }
+
+ InParam.buffer = GpioSetValue;
+ InParam.length = 4;
+ OutParam.buffer = Output_Buff;
+ TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
+ REENTRANCE_LOCK();
+ ret = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(ret!=NFCSTATUS_PENDING)
+ {
+ ALOGE("IOCTL status error");
+ goto clean_and_return;
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("IOCTL semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("READ MEM ERROR");
+ goto clean_and_return;
+ }
+ CONCURRENCY_UNLOCK();
+
+ nfc_cb_data_deinit(&cb_data);
+ nfc_cb_data_deinit(&cb_data_SE_Notification);
+
+ /* Return the Handle of the SecureElement */
+ return secureElementHandle;
+ }
+ else
+ {
+ ALOGE("phLibNfc_SE_GetSecureElementList(): No SMX detected");
+ goto clean_and_return;
+ }
+ }
+ else
+ {
+ ALOGE("phLibNfc_SE_GetSecureElementList(): Error");
+ goto clean_and_return;
+ }
+
+clean_and_return:
+ nfc_cb_data_deinit(&cb_data);
+ nfc_cb_data_deinit(&cb_data_SE_Notification);
+
+ CONCURRENCY_UNLOCK();
+ return 0;
+}
+
+
+static jboolean com_android_nfc_NativeNfcSecureElement_doDisconnect(JNIEnv *e, jobject o, jint handle)
+{
+ jclass cls;
+ jfieldID f;
+ NFCSTATUS status;
+ jboolean result = JNI_FALSE;
+ phLibNfc_SE_List_t SE_List[PHLIBNFC_MAXNO_OF_SE];
+ uint8_t i, No_SE = PHLIBNFC_MAXNO_OF_SE, SmartMX_index=0, SmartMX_detected = 0;
+ uint32_t SmartMX_Handle;
+ struct nfc_jni_callback_data cb_data;
+ phNfc_sData_t InParam;
+ phNfc_sData_t OutParam;
+ uint8_t Output_Buff[10];
+ uint8_t GpioGetValue[3] = {0x00, 0xF8, 0x2B};
+ uint8_t GpioSetValue[4];
+ uint8_t gpioValue;
+
+ /* Create the local semaphore */
+ if (!nfc_cb_data_init(&cb_data, NULL))
+ {
+ goto clean_and_return;
+ }
+
+ TRACE("Close Secure element function ");
+
+ CONCURRENCY_LOCK();
+ /* Disconnect */
+ TRACE("Disconnecting from SMX (handle = 0x%x)", handle);
+ REENTRANCE_LOCK();
+ status = phLibNfc_RemoteDev_Disconnect(handle,
+ NFC_SMARTMX_RELEASE,
+ com_android_nfc_jni_disconnect_callback,
+ (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(status != NFCSTATUS_PENDING)
+ {
+ ALOGE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
+ goto clean_and_return;
+ }
+ TRACE("phLibNfc_RemoteDev_Disconnect(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ goto clean_and_return;
+ }
+
+ /* Disconnect Status */
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("\n> Disconnect SE ERROR \n" );
+ goto clean_and_return;
+ }
+ CONCURRENCY_UNLOCK();
+
+ /* Get GPIO information */
+ CONCURRENCY_LOCK();
+ InParam.buffer = GpioGetValue;
+ InParam.length = 3;
+ OutParam.buffer = Output_Buff;
+ TRACE("phLibNfc_Mgt_IoCtl()- GPIO Get Value");
+ REENTRANCE_LOCK();
+ status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_READ,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(status!=NFCSTATUS_PENDING)
+ {
+ ALOGE("IOCTL status error");
+ goto clean_and_return;
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("IOCTL semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("READ MEM ERROR");
+ goto clean_and_return;
+ }
+
+ gpioValue = com_android_nfc_jni_ioctl_buffer->buffer[0];
+ TRACE("GpioValue = Ox%02x",gpioValue);
+
+ /* Set GPIO information */
+ GpioSetValue[0] = 0x00;
+ GpioSetValue[1] = 0xF8;
+ GpioSetValue[2] = 0x2B;
+ GpioSetValue[3] = (gpioValue & 0xBF);
+
+ TRACE("GpioValue to be set = Ox%02x",GpioSetValue[3]);
+
+ for(i=0;i<4;i++)
+ {
+ TRACE("0x%02x",GpioSetValue[i]);
+ }
+
+ InParam.buffer = GpioSetValue;
+ InParam.length = 4;
+ OutParam.buffer = Output_Buff;
+ TRACE("phLibNfc_Mgt_IoCtl()- GPIO Set Value");
+ REENTRANCE_LOCK();
+ status = phLibNfc_Mgt_IoCtl(gHWRef,NFC_MEM_WRITE,&InParam, &OutParam,com_android_nfc_jni_ioctl_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(status!=NFCSTATUS_PENDING)
+ {
+ ALOGE("IOCTL status error");
+ goto clean_and_return;
+ }
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("IOCTL semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("READ MEM ERROR");
+ goto clean_and_return;
+ }
+
+ result = JNI_TRUE;
+
+clean_and_return:
+ nfc_cb_data_deinit(&cb_data);
+
+ CONCURRENCY_UNLOCK();
+ return result;
+}
+
+static jbyteArray com_android_nfc_NativeNfcSecureElement_doTransceive(JNIEnv *e,
+ jobject o,jint handle, jbyteArray data)
+{
+ uint8_t offset = 0;
+ uint8_t *buf;
+ uint32_t buflen;
+ phLibNfc_sTransceiveInfo_t transceive_info;
+ jbyteArray result = NULL;
+ int res;
+
+ int tech = SecureElementTech;
+ NFCSTATUS status;
+ struct nfc_jni_callback_data cb_data;
+
+ /* Create the local semaphore */
+ if (!nfc_cb_data_init(&cb_data, NULL))
+ {
+ goto clean_and_return;
+ }
+
+ TRACE("Exchange APDU function ");
+
+ CONCURRENCY_LOCK();
+
+ TRACE("Secure Element tech: %d\n", tech);
+
+ buf = (uint8_t *)e->GetByteArrayElements(data, NULL);
+ buflen = (uint32_t)e->GetArrayLength(data);
+
+ /* Prepare transceive info structure */
+ if(tech == TARGET_TYPE_MIFARE_CLASSIC || tech == TARGET_TYPE_MIFARE_UL)
+ {
+ offset = 2;
+ transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0];
+ transceive_info.addr = (uint8_t)buf[1];
+ }
+ else if(tech == TARGET_TYPE_ISO14443_4)
+ {
+ transceive_info.cmd.Iso144434Cmd = phNfc_eIso14443_4_Raw;
+ transceive_info.addr = 0;
+ }
+
+ transceive_info.sSendData.buffer = buf + offset;
+ transceive_info.sSendData.length = buflen - offset;
+ transceive_info.sRecvData.buffer = (uint8_t*)malloc(1024);
+ transceive_info.sRecvData.length = 1024;
+
+ if(transceive_info.sRecvData.buffer == NULL)
+ {
+ goto clean_and_return;
+ }
+
+ TRACE("phLibNfc_RemoteDev_Transceive(SMX)");
+ REENTRANCE_LOCK();
+ status = phLibNfc_RemoteDev_Transceive(handle, &transceive_info,
+ com_android_nfc_jni_transceive_callback, (void *)&cb_data);
+ REENTRANCE_UNLOCK();
+ if(status != NFCSTATUS_PENDING)
+ {
+ ALOGE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
+ goto clean_and_return;
+ }
+ TRACE("phLibNfc_RemoteDev_Transceive(SMX) returned 0x%04x[%s]", status, nfc_jni_get_status_name(status));
+
+ /* Wait for callback response */
+ if(sem_wait(&cb_data.sem))
+ {
+ ALOGE("TRANSCEIVE semaphore error");
+ goto clean_and_return;
+ }
+
+ if(cb_data.status != NFCSTATUS_SUCCESS)
+ {
+ ALOGE("TRANSCEIVE error");
+ goto clean_and_return;
+ }
+
+ /* Copy results back to Java */
+ result = e->NewByteArray(com_android_nfc_jni_transceive_buffer->length);
+ if(result != NULL)
+ {
+ e->SetByteArrayRegion(result, 0,
+ com_android_nfc_jni_transceive_buffer->length,
+ (jbyte *)com_android_nfc_jni_transceive_buffer->buffer);
+ }
+
+clean_and_return:
+ nfc_cb_data_deinit(&cb_data);
+
+ if(transceive_info.sRecvData.buffer != NULL)
+ {
+ free(transceive_info.sRecvData.buffer);
+ }
+
+ e->ReleaseByteArrayElements(data,
+ (jbyte *)transceive_info.sSendData.buffer, JNI_ABORT);
+
+ CONCURRENCY_UNLOCK();
+
+ return result;
+}
+
+static jbyteArray com_android_nfc_NativeNfcSecureElement_doGetUid(JNIEnv *e, jobject o, jint handle)
+{
+ TRACE("Get Secure element UID function ");
+ jbyteArray SecureElementUid;
+
+ if(handle == secureElementHandle)
+ {
+ SecureElementUid = e->NewByteArray(SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength);
+ e->SetByteArrayRegion(SecureElementUid, 0, SecureElementInfo->RemoteDevInfo.Iso14443A_Info.UidLength,(jbyte *)SecureElementInfo->RemoteDevInfo.Iso14443A_Info.Uid);
+ return SecureElementUid;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static jintArray com_android_nfc_NativeNfcSecureElement_doGetTechList(JNIEnv *e, jobject o, jint handle)
+{
+ jintArray techList;
+ TRACE("Get Secure element Type function ");
+
+ if(handle == secureElementHandle)
+ {
+ techList = e->NewIntArray(1);
+ e->SetIntArrayRegion(techList, 0, 1, &SecureElementTech);
+ return techList;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gMethods[] =
+{
+ {"doNativeOpenSecureElementConnection", "()I",
+ (void *)com_android_nfc_NativeNfcSecureElement_doOpenSecureElementConnection},
+ {"doNativeDisconnectSecureElementConnection", "(I)Z",
+ (void *)com_android_nfc_NativeNfcSecureElement_doDisconnect},
+ {"doTransceive", "(I[B)[B",
+ (void *)com_android_nfc_NativeNfcSecureElement_doTransceive},
+ {"doGetUid", "(I)[B",
+ (void *)com_android_nfc_NativeNfcSecureElement_doGetUid},
+ {"doGetTechList", "(I)[I",
+ (void *)com_android_nfc_NativeNfcSecureElement_doGetTechList},
+};
+
+int register_com_android_nfc_NativeNfcSecureElement(JNIEnv *e)
+{
+ return jniRegisterNativeMethods(e,
+ "com/android/nfc/dhimpl/NativeNfcSecureElement",
+ gMethods, NELEM(gMethods));
+}
+
+} // namespace android