diff options
Diffstat (limited to 'nxp/jni/com_android_nfc_NativeLlcpSocket.cpp')
-rw-r--r-- | nxp/jni/com_android_nfc_NativeLlcpSocket.cpp | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/nxp/jni/com_android_nfc_NativeLlcpSocket.cpp b/nxp/jni/com_android_nfc_NativeLlcpSocket.cpp new file mode 100644 index 0000000..91a72a5 --- /dev/null +++ b/nxp/jni/com_android_nfc_NativeLlcpSocket.cpp @@ -0,0 +1,468 @@ +/* + * 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 <errno.h> + +#include "com_android_nfc.h" + +namespace android { + +/* + * Callbacks + */ + +static void nfc_jni_disconnect_callback(void* pContext, + NFCSTATUS status) +{ + struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; + LOG_CALLBACK("nfc_jni_disconnect_callback", status); + + /* Report the callback status and wake up the caller */ + pCallbackData->status = status; + sem_post(&pCallbackData->sem); +} + + +static void nfc_jni_connect_callback(void* pContext, uint8_t nErrCode, NFCSTATUS status) +{ + struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; + LOG_CALLBACK("nfc_jni_llcp_connect_callback", status); + + if(status == NFCSTATUS_SUCCESS) + { + TRACE("Socket connected\n"); + } + else + { + ALOGD("Socket not connected:"); + switch(nErrCode) + { + case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_ACTIVE: + { + ALOGD("> SAP NOT ACTIVE\n"); + }break; + + case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND: + { + ALOGD("> SAP NOT FOUND\n"); + }break; + + case PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED: + { + ALOGD("> CONNECT REJECTED\n"); + }break; + + case PHFRINFC_LLCP_DM_OPCODE_CONNECT_NOT_ACCEPTED: + { + ALOGD("> CONNECT NOT ACCEPTED\n"); + }break; + + case PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE: + { + ALOGD("> SOCKET NOT AVAILABLE\n"); + }break; + } + } + + /* Report the callback status and wake up the caller */ + pCallbackData->status = status; + sem_post(&pCallbackData->sem); +} + + + + +static void nfc_jni_receive_callback(void* pContext, NFCSTATUS status) +{ + struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; + LOG_CALLBACK("nfc_jni_llcp_receive_callback", status); + + /* Report the callback status and wake up the caller */ + pCallbackData->status = status; + sem_post(&pCallbackData->sem); +} + +static void nfc_jni_send_callback(void *pContext, NFCSTATUS status) +{ + struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; + LOG_CALLBACK("nfc_jni_llcp_send_callback", status); + + /* Report the callback status and wake up the caller */ + pCallbackData->status = status; + sem_post(&pCallbackData->sem); +} + +/* + * Methods + */ +static jboolean com_android_nfc_NativeLlcpSocket_doConnect(JNIEnv *e, jobject o, jint nSap) +{ + NFCSTATUS ret; + struct timespec ts; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + struct nfc_jni_callback_data cb_data; + jboolean result = JNI_FALSE; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + /* Create the local semaphore */ + if (!nfc_cb_data_init(&cb_data, NULL)) + { + goto clean_and_return; + } + + TRACE("phLibNfc_Llcp_Connect(%d)",nSap); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_Connect(hRemoteDevice, + hLlcpSocket, + nSap, + nfc_jni_connect_callback, + (void*)&cb_data); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_PENDING) + { + ALOGE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret)); + + /* Wait for callback response */ + if(sem_wait(&cb_data.sem)) + { + ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + goto clean_and_return; + } + + if(cb_data.status != NFCSTATUS_SUCCESS) + { + ALOGW("LLCP Connect request failed"); + goto clean_and_return; + } + + result = JNI_TRUE; + +clean_and_return: + nfc_cb_data_deinit(&cb_data); + return result; +} + +static jboolean com_android_nfc_NativeLlcpSocket_doConnectBy(JNIEnv *e, jobject o, jstring sn) +{ + NFCSTATUS ret; + struct timespec ts; + phNfc_sData_t serviceName = {0}; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + struct nfc_jni_callback_data cb_data; + jboolean result = JNI_FALSE; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + /* Create the local semaphore */ + if (!nfc_cb_data_init(&cb_data, NULL)) + { + goto clean_and_return; + } + + /* Service socket */ + serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL); + serviceName.length = (uint32_t)e->GetStringUTFLength(sn); + + TRACE("phLibNfc_Llcp_ConnectByUri()"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_ConnectByUri(hRemoteDevice, + hLlcpSocket, + &serviceName, + nfc_jni_connect_callback, + (void*)&cb_data); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_PENDING) + { + ALOGE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + + /* Wait for callback response */ + if(sem_wait(&cb_data.sem)) + { + ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + goto clean_and_return; + } + + if(cb_data.status != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + + result = JNI_TRUE; + +clean_and_return: + if (serviceName.buffer != NULL) { + e->ReleaseStringUTFChars(sn, (const char *)serviceName.buffer); + } + nfc_cb_data_deinit(&cb_data); + return result; +} + +static jboolean com_android_nfc_NativeLlcpSocket_doClose(JNIEnv *e, jobject o) +{ + NFCSTATUS ret; + phLibNfc_Handle hLlcpSocket; + + /* Retrieve socket handle */ + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + TRACE("phLibNfc_Llcp_Close()"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_Close(hLlcpSocket); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_SUCCESS) + { + ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return FALSE; + } + TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return TRUE; +} + +static jboolean com_android_nfc_NativeLlcpSocket_doSend(JNIEnv *e, jobject o, jbyteArray data) +{ + NFCSTATUS ret; + struct timespec ts; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + phNfc_sData_t sSendBuffer = {NULL, 0}; + struct nfc_jni_callback_data cb_data; + jboolean result = JNI_FALSE; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + /* Create the local semaphore */ + if (!nfc_cb_data_init(&cb_data, NULL)) + { + goto clean_and_return; + } + + sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL); + sSendBuffer.length = (uint32_t)e->GetArrayLength(data); + + TRACE("phLibNfc_Llcp_Send()"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_Send(hRemoteDevice, + hLlcpSocket, + &sSendBuffer, + nfc_jni_send_callback, + (void*)&cb_data); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_PENDING) + { + ALOGE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + + /* Wait for callback response */ + if(sem_wait(&cb_data.sem)) + { + ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + goto clean_and_return; + } + + if(cb_data.status != NFCSTATUS_SUCCESS) + { + goto clean_and_return; + } + + result = JNI_TRUE; + +clean_and_return: + if (sSendBuffer.buffer != NULL) + { + e->ReleaseByteArrayElements(data, (jbyte*)sSendBuffer.buffer, JNI_ABORT); + } + nfc_cb_data_deinit(&cb_data); + return result; +} + +static jint com_android_nfc_NativeLlcpSocket_doReceive(JNIEnv *e, jobject o, jbyteArray buffer) +{ + NFCSTATUS ret; + struct timespec ts; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + phNfc_sData_t sReceiveBuffer = {NULL, 0}; + struct nfc_jni_callback_data cb_data; + jint result = -1; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + /* Create the local semaphore */ + if (!nfc_cb_data_init(&cb_data, NULL)) + { + goto clean_and_return; + } + + sReceiveBuffer.buffer = (uint8_t*)e->GetByteArrayElements(buffer, NULL); + sReceiveBuffer.length = (uint32_t)e->GetArrayLength(buffer); + + TRACE("phLibNfc_Llcp_Recv()"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_Recv(hRemoteDevice, + hLlcpSocket, + &sReceiveBuffer, + nfc_jni_receive_callback, + (void*)&cb_data); + REENTRANCE_UNLOCK(); + if(ret == NFCSTATUS_PENDING) + { + /* Wait for callback response */ + if(sem_wait(&cb_data.sem)) + { + ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); + goto clean_and_return; + } + + if(cb_data.status == NFCSTATUS_SUCCESS) + { + result = sReceiveBuffer.length; + } + } + else if (ret == NFCSTATUS_SUCCESS) + { + result = sReceiveBuffer.length; + } + else + { + /* Return status should be either SUCCESS or PENDING */ + ALOGE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + +clean_and_return: + if (sReceiveBuffer.buffer != NULL) + { + e->ReleaseByteArrayElements(buffer, (jbyte*)sReceiveBuffer.buffer, 0); + } + nfc_cb_data_deinit(&cb_data); + return result; +} + +static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU(JNIEnv *e, jobject o) +{ + NFCSTATUS ret; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + phLibNfc_Llcp_sSocketOptions_t remoteSocketOption; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU)"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_SocketGetRemoteOptions(hRemoteDevice, + hLlcpSocket, + &remoteSocketOption); + REENTRANCE_UNLOCK(); + if(ret == NFCSTATUS_SUCCESS) + { + TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return remoteSocketOption.miu; + } + else + { + ALOGW("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return 0; + } +} + +static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW(JNIEnv *e, jobject o) +{ + NFCSTATUS ret; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + phLibNfc_Llcp_sSocketOptions_t remoteSocketOption; + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + + TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW)"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_SocketGetRemoteOptions(hRemoteDevice, + hLlcpSocket, + &remoteSocketOption); + REENTRANCE_UNLOCK(); + if(ret == NFCSTATUS_SUCCESS) + { + TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return remoteSocketOption.rw; + } + else + { + ALOGW("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return 0; + } +} + + +/* + * JNI registration. + */ +static JNINativeMethod gMethods[] = +{ + {"doConnect", "(I)Z", + (void *)com_android_nfc_NativeLlcpSocket_doConnect}, + + {"doConnectBy", "(Ljava/lang/String;)Z", + (void *)com_android_nfc_NativeLlcpSocket_doConnectBy}, + + {"doClose", "()Z", + (void *)com_android_nfc_NativeLlcpSocket_doClose}, + + {"doSend", "([B)Z", + (void *)com_android_nfc_NativeLlcpSocket_doSend}, + + {"doReceive", "([B)I", + (void *)com_android_nfc_NativeLlcpSocket_doReceive}, + + {"doGetRemoteSocketMiu", "()I", + (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU}, + + {"doGetRemoteSocketRw", "()I", + (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW}, +}; + + +int register_com_android_nfc_NativeLlcpSocket(JNIEnv *e) +{ + return jniRegisterNativeMethods(e, + "com/android/nfc/dhimpl/NativeLlcpSocket",gMethods, NELEM(gMethods)); +} + +} // namespace android |