/* * 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 sem_t *nfc_jni_llcp_sem; static NFCSTATUS nfc_jni_cb_status = NFCSTATUS_FAILED; namespace android { extern phLibNfc_Handle hIncommingLlcpSocket; extern sem_t *nfc_jni_llcp_listen_sem; extern void nfc_jni_llcp_transport_socket_err_callback(void* pContext, uint8_t nErrCode); /* * Callbacks */ static void nfc_jni_llcp_accept_socket_callback(void* pContext, NFCSTATUS status) { PHNFC_UNUSED_VARIABLE(pContext); LOG_CALLBACK("nfc_jni_llcp_accept_socket_callback", status); nfc_jni_cb_status = status; sem_post(nfc_jni_llcp_sem); } /* * Methods */ static jobject com_NativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint miu, jint rw, jint linearBufferLength) { NFCSTATUS ret; struct timespec ts; phLibNfc_Llcp_sSocketOptions_t sOptions; phNfc_sData_t sWorkingBuffer; jfieldID f; jclass clsNativeLlcpSocket; jobject clientSocket = 0; /* Wait for tag Notification */ if(sem_wait(nfc_jni_llcp_listen_sem) == -1) { return NULL; } /* Set socket options with the socket options of the service */ sOptions.miu = miu; sOptions.rw = rw; /* Allocate Working buffer length */ sWorkingBuffer.buffer = (uint8_t*)malloc((miu*rw)+miu+linearBufferLength); sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength; /* Accept the incomming socket */ TRACE("phLibNfc_Llcp_Accept()"); REENTRANCE_LOCK(); ret = phLibNfc_Llcp_Accept( hIncommingLlcpSocket, &sOptions, &sWorkingBuffer, nfc_jni_llcp_transport_socket_err_callback, nfc_jni_llcp_accept_socket_callback, (void*)hIncommingLlcpSocket); REENTRANCE_UNLOCK(); if(ret != NFCSTATUS_PENDING) { LOGE("phLibNfc_Llcp_Accept() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); return NULL; } TRACE("phLibNfc_Llcp_Accept() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); /* Wait for tag Notification */ if(sem_wait(nfc_jni_llcp_sem) == -1) { return NULL; } if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) { /* Create new LlcpSocket object */ if(nfc_jni_cache_object(e,"com/android/nfc/NativeLlcpSocket",&(clientSocket)) == -1) { LOGD("LLCP Socket creation error"); return NULL; } /* Get NativeConnectionOriented class object */ clsNativeLlcpSocket = e->GetObjectClass(clientSocket); if(e->ExceptionCheck()) { LOGD("LLCP Socket get class object error"); return NULL; } /* Set socket handle */ f = e->GetFieldID(clsNativeLlcpSocket, "mHandle", "I"); e->SetIntField(clientSocket, f,(jint)hIncommingLlcpSocket); /* Set socket MIU */ f = e->GetFieldID(clsNativeLlcpSocket, "mLocalMiu", "I"); e->SetIntField(clientSocket, f,(jint)miu); /* Set socket RW */ f = e->GetFieldID(clsNativeLlcpSocket, "mLocalRw", "I"); e->SetIntField(clientSocket, f,(jint)rw); TRACE("socket handle 0x%02x: MIU = %d, RW = %d\n",hIncommingLlcpSocket, miu, rw); return clientSocket; } else { return NULL; } } static jboolean com_NativeLlcpServiceSocket_doClose(JNIEnv *e, jobject o) { NFCSTATUS ret; phLibNfc_Handle hLlcpSocket; TRACE("Close Service socket"); /* Retrieve socket handle */ hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); REENTRANCE_LOCK(); ret = phLibNfc_Llcp_Close(hLlcpSocket); REENTRANCE_UNLOCK(); if(ret == NFCSTATUS_SUCCESS) { TRACE("Close Service socket OK"); return TRUE; } else { LOGD("Close Service socket KO"); return FALSE; } } /* * JNI registration. */ static JNINativeMethod gMethods[] = { {"doAccept", "(III)Lcom/android/nfc/NativeLlcpSocket;", (void *)com_NativeLlcpServiceSocket_doAccept}, {"doClose", "()Z", (void *)com_NativeLlcpServiceSocket_doClose}, }; int register_com_android_nfc_NativeLlcpServiceSocket(JNIEnv *e) { nfc_jni_llcp_sem = (sem_t *)malloc(sizeof(sem_t)); if(sem_init(nfc_jni_llcp_sem, 0, 0) == -1) return -1; return jniRegisterNativeMethods(e, "com/android/nfc/NativeLlcpServiceSocket", gMethods, NELEM(gMethods)); } } // namespace android