/* * 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) { LOGE("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)) { LOGE("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,"android/nfc/LlcpPacket",&(llcpPacket)) == -1) { LOGE("Find LlcpPacket class error"); goto clean_and_return; } /* Get NativeConnectionless class object */ clsLlcpPacket = e->GetObjectClass(llcpPacket); if(e->ExceptionCheck()) { LOGE("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) { LOGE("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)) { LOGE("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 */ LOGD("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: if (receivedData != NULL) { e->ReleaseByteArrayElements(receivedData, (jbyte*)sReceiveBuffer.buffer, 0); } 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 { LOGE("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)Landroid/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/NativeLlcpConnectionlessSocket", gMethods, NELEM(gMethods)); } } // android namespace