| /* |
| * 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 */ |
| ScopedLocalRef<jintArray> techList(e, NULL); |
| nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, NULL, NULL); |
| |
| // TODO: Should use the "connected" technology, for now use the first |
| if ((techList.get() != NULL) && e->GetArrayLength(techList.get()) > 0) { |
| e->GetIntArrayRegion(techList.get(), 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; |
| } |
| } |
| |
| 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; |
| jint errorCode = EE_ERROR_INIT; |
| |
| 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) |
| { |
| ALOGE("Unable to open SE connection, device already connected to a P2P peer or a Tag"); |
| errorCode = EE_ERROR_LISTEN_MODE; |
| 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"); |
| errorCode = EE_ERROR_EXT_FIELD; |
| 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(®istry_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 errorCode; |
| } |
| |
| |
| 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) { |
| return NULL; |
| } |
| jintArray result = e->NewIntArray(1); |
| e->SetIntArrayRegion(result, 0, 1, &SecureElementTech); |
| return result; |
| } |
| |
| |
| /* |
| * 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 |