summaryrefslogtreecommitdiffstats
path: root/nxp/jni/com_android_nfc_NativeLlcpSocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nxp/jni/com_android_nfc_NativeLlcpSocket.cpp')
-rw-r--r--nxp/jni/com_android_nfc_NativeLlcpSocket.cpp468
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