diff options
Diffstat (limited to 'nxp/jni/com_android_nfc_NativeLlcpConnectionlessSocket.cpp')
-rw-r--r-- | nxp/jni/com_android_nfc_NativeLlcpConnectionlessSocket.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/nxp/jni/com_android_nfc_NativeLlcpConnectionlessSocket.cpp b/nxp/jni/com_android_nfc_NativeLlcpConnectionlessSocket.cpp new file mode 100644 index 00000000..188edb40 --- /dev/null +++ b/nxp/jni/com_android_nfc_NativeLlcpConnectionlessSocket.cpp @@ -0,0 +1,253 @@ +/* + * 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_receive_callback(void* pContext, uint8_t ssap, NFCSTATUS status) +{ + struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; + LOG_CALLBACK("nfc_jni_receiveFrom_callback", status); + + if(status == NFCSTATUS_SUCCESS) + { + pCallbackData->pContext = (void*)ssap; + TRACE("RECEIVE UI_FRAME FROM SAP %d OK \n", ssap); + } + + /* 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_sendTo_callback", status); + + /* Report the callback status and wake up the caller */ + pCallbackData->status = status; + sem_post(&pCallbackData->sem); +} + +/* +* Methods +*/ +static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv *e, jobject o, jint nsap, 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_SendTo()"); + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_SendTo(hRemoteDevice, + hLlcpSocket, + nsap, + &sSendBuffer, + nfc_jni_send_callback, + (void*)&cb_data); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_PENDING) + { + ALOGE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_SendTo() 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 jobject com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv *e, jobject o, jint linkMiu) +{ + NFCSTATUS ret; + struct timespec ts; + uint8_t ssap; + jobject llcpPacket = NULL; + phLibNfc_Handle hRemoteDevice; + phLibNfc_Handle hLlcpSocket; + phNfc_sData_t sReceiveBuffer; + jclass clsLlcpPacket; + jfieldID f; + jbyteArray receivedData = NULL; + struct nfc_jni_callback_data cb_data; + + /* Create the local semaphore */ + if (!nfc_cb_data_init(&cb_data, NULL)) + { + goto clean_and_return; + } + + /* Create new LlcpPacket object */ + if(nfc_jni_cache_object(e,"com/android/nfc/LlcpPacket",&(llcpPacket)) == -1) + { + ALOGE("Find LlcpPacket class error"); + goto clean_and_return; + } + + /* Get NativeConnectionless class object */ + clsLlcpPacket = e->GetObjectClass(llcpPacket); + if(e->ExceptionCheck()) + { + ALOGE("Get Object class error"); + goto clean_and_return; + } + + /* Retrieve handles */ + hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); + hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); + TRACE("phLibNfc_Llcp_RecvFrom(), Socket Handle = 0x%02x, Link LIU = %d", hLlcpSocket, linkMiu); + + sReceiveBuffer.buffer = (uint8_t*)malloc(linkMiu); + sReceiveBuffer.length = linkMiu; + + REENTRANCE_LOCK(); + ret = phLibNfc_Llcp_RecvFrom(hRemoteDevice, + hLlcpSocket, + &sReceiveBuffer, + nfc_jni_receive_callback, + &cb_data); + REENTRANCE_UNLOCK(); + if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS) + { + ALOGE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + goto clean_and_return; + } + TRACE("phLibNfc_Llcp_RecvFrom() 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; + } + + ssap = (uint32_t)cb_data.pContext; + TRACE("Data Received From SSAP = %d\n, length = %d", ssap, sReceiveBuffer.length); + + /* Set Llcp Packet remote SAP */ + f = e->GetFieldID(clsLlcpPacket, "mRemoteSap", "I"); + e->SetIntField(llcpPacket, f,(jbyte)ssap); + + /* Set Llcp Packet Buffer */ + ALOGD("Set LlcpPacket Data Buffer\n"); + f = e->GetFieldID(clsLlcpPacket, "mDataBuffer", "[B"); + receivedData = e->NewByteArray(sReceiveBuffer.length); + e->SetByteArrayRegion(receivedData, 0, sReceiveBuffer.length,(jbyte *)sReceiveBuffer.buffer); + e->SetObjectField(llcpPacket, f, receivedData); + +clean_and_return: + nfc_cb_data_deinit(&cb_data); + return llcpPacket; +} + +static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o) +{ + NFCSTATUS ret; + phLibNfc_Handle hLlcpSocket; + TRACE("Close Connectionless socket"); + + /* 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) + { + TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return TRUE; + } + else + { + ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); + return FALSE; + } +} + + +/* + * JNI registration. + */ +static JNINativeMethod gMethods[] = +{ + {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo}, + + {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom}, + + {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose}, +}; + + +int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e) +{ + return jniRegisterNativeMethods(e, + "com/android/nfc/nxp/NativeLlcpConnectionlessSocket", + gMethods, NELEM(gMethods)); +} + +} // android namespace |