1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <semaphore.h> 18 19 #include "com_android_nfc.h" 20 21 static sem_t *nfc_jni_llcp_sem; 22 static NFCSTATUS nfc_jni_cb_status = NFCSTATUS_FAILED; 23 24 25 namespace android { 26 27 extern phLibNfc_Handle hIncommingLlcpSocket; 28 extern sem_t *nfc_jni_llcp_listen_sem; 29 extern void nfc_jni_llcp_transport_socket_err_callback(void* pContext, 30 uint8_t nErrCode); 31 /* 32 * Callbacks 33 */ 34 static void nfc_jni_llcp_accept_socket_callback(void* pContext, 35 NFCSTATUS status) 36 { 37 PHNFC_UNUSED_VARIABLE(pContext); 38 39 LOG_CALLBACK("nfc_jni_llcp_accept_socket_callback", status); 40 41 nfc_jni_cb_status = status; 42 43 sem_post(nfc_jni_llcp_sem); 44 } 45 46 47 /* 48 * Methods 49 */ 50 static jobject com_NativeLlcpServiceSocket_doAccept(JNIEnv *e, jobject o, jint miu, jint rw, jint linearBufferLength) 51 { 52 NFCSTATUS ret; 53 struct timespec ts; 54 phLibNfc_Llcp_sSocketOptions_t sOptions; 55 phNfc_sData_t sWorkingBuffer; 56 jfieldID f; 57 jclass clsNativeLlcpSocket; 58 jobject clientSocket = 0; 59 60 61 /* Wait for tag Notification */ 62 if(sem_wait(nfc_jni_llcp_listen_sem) == -1) 63 { 64 return NULL; 65 } 66 67 /* Set socket options with the socket options of the service */ 68 sOptions.miu = miu; 69 sOptions.rw = rw; 70 71 /* Allocate Working buffer length */ 72 sWorkingBuffer.buffer = (uint8_t*)malloc((miu*rw)+miu+linearBufferLength); 73 sWorkingBuffer.length = (miu*rw)+ miu + linearBufferLength; 74 75 /* Accept the incomming socket */ 76 TRACE("phLibNfc_Llcp_Accept()"); 77 REENTRANCE_LOCK(); 78 ret = phLibNfc_Llcp_Accept( hIncommingLlcpSocket, 79 &sOptions, 80 &sWorkingBuffer, 81 nfc_jni_llcp_transport_socket_err_callback, 82 nfc_jni_llcp_accept_socket_callback, 83 (void*)hIncommingLlcpSocket); 84 REENTRANCE_UNLOCK(); 85 if(ret != NFCSTATUS_PENDING) 86 { 87 LOGE("phLibNfc_Llcp_Accept() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 88 return NULL; 89 } 90 TRACE("phLibNfc_Llcp_Accept() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 91 92 /* Wait for tag Notification */ 93 if(sem_wait(nfc_jni_llcp_sem) == -1) 94 { 95 return NULL; 96 } 97 98 if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) 99 { 100 /* Create new LlcpSocket object */ 101 if(nfc_jni_cache_object(e,"com/android/nfc/NativeLlcpSocket",&(clientSocket)) == -1) 102 { 103 LOGD("LLCP Socket creation error"); 104 return NULL; 105 } 106 107 /* Get NativeConnectionOriented class object */ 108 clsNativeLlcpSocket = e->GetObjectClass(clientSocket); 109 if(e->ExceptionCheck()) 110 { 111 LOGD("LLCP Socket get class object error"); 112 return NULL; 113 } 114 115 /* Set socket handle */ 116 f = e->GetFieldID(clsNativeLlcpSocket, "mHandle", "I"); 117 e->SetIntField(clientSocket, f,(jint)hIncommingLlcpSocket); 118 119 /* Set socket MIU */ 120 f = e->GetFieldID(clsNativeLlcpSocket, "mLocalMiu", "I"); 121 e->SetIntField(clientSocket, f,(jint)miu); 122 123 /* Set socket RW */ 124 f = e->GetFieldID(clsNativeLlcpSocket, "mLocalRw", "I"); 125 e->SetIntField(clientSocket, f,(jint)rw); 126 127 TRACE("socket handle 0x%02x: MIU = %d, RW = %d\n",hIncommingLlcpSocket, miu, rw); 128 129 return clientSocket; 130 131 } 132 else 133 { 134 return NULL; 135 } 136 } 137 138 static jboolean com_NativeLlcpServiceSocket_doClose(JNIEnv *e, jobject o) 139 { 140 NFCSTATUS ret; 141 phLibNfc_Handle hLlcpSocket; 142 TRACE("Close Service socket"); 143 144 /* Retrieve socket handle */ 145 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 146 147 REENTRANCE_LOCK(); 148 ret = phLibNfc_Llcp_Close(hLlcpSocket); 149 REENTRANCE_UNLOCK(); 150 if(ret == NFCSTATUS_SUCCESS) 151 { 152 TRACE("Close Service socket OK"); 153 return TRUE; 154 } 155 else 156 { 157 LOGD("Close Service socket KO"); 158 return FALSE; 159 } 160 } 161 162 163 /* 164 * JNI registration. 165 */ 166 static JNINativeMethod gMethods[] = 167 { 168 {"doAccept", "(III)Lcom/android/nfc/NativeLlcpSocket;", 169 (void *)com_NativeLlcpServiceSocket_doAccept}, 170 171 {"doClose", "()Z", 172 (void *)com_NativeLlcpServiceSocket_doClose}, 173 }; 174 175 176 int register_com_android_nfc_NativeLlcpServiceSocket(JNIEnv *e) 177 { 178 nfc_jni_llcp_sem = (sem_t *)malloc(sizeof(sem_t)); 179 if(sem_init(nfc_jni_llcp_sem, 0, 0) == -1) 180 return -1; 181 182 return jniRegisterNativeMethods(e, 183 "com/android/nfc/NativeLlcpServiceSocket", 184 gMethods, NELEM(gMethods)); 185 } 186 187 } // namespace android 188