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 #include <errno.h> 19 20 #include "com_android_nfc.h" 21 22 namespace android { 23 24 /* 25 * Callbacks 26 */ 27 28 static void nfc_jni_receive_callback(void* pContext, uint8_t ssap, NFCSTATUS status) 29 { 30 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 31 LOG_CALLBACK("nfc_jni_receiveFrom_callback", status); 32 33 if(status == NFCSTATUS_SUCCESS) 34 { 35 pCallbackData->pContext = (void*)(uintptr_t)ssap; 36 TRACE("RECEIVE UI_FRAME FROM SAP %d OK \n", ssap); 37 } 38 39 /* Report the callback status and wake up the caller */ 40 pCallbackData->status = status; 41 sem_post(&pCallbackData->sem); 42 } 43 44 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status) 45 { 46 struct nfc_jni_callback_data * pCallbackData = (struct nfc_jni_callback_data *) pContext; 47 LOG_CALLBACK("nfc_jni_sendTo_callback", status); 48 49 /* Report the callback status and wake up the caller */ 50 pCallbackData->status = status; 51 sem_post(&pCallbackData->sem); 52 } 53 54 /* 55 * Methods 56 */ 57 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo(JNIEnv *e, jobject o, jint nsap, jbyteArray data) 58 { 59 NFCSTATUS ret; 60 struct timespec ts; 61 phLibNfc_Handle hRemoteDevice; 62 phLibNfc_Handle hLlcpSocket; 63 phNfc_sData_t sSendBuffer = {NULL, 0}; 64 struct nfc_jni_callback_data cb_data; 65 jboolean result = JNI_FALSE; 66 67 /* Retrieve handles */ 68 hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); 69 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 70 71 /* Create the local semaphore */ 72 if (!nfc_cb_data_init(&cb_data, NULL)) 73 { 74 goto clean_and_return; 75 } 76 77 sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL); 78 sSendBuffer.length = (uint32_t)e->GetArrayLength(data); 79 80 TRACE("phLibNfc_Llcp_SendTo()"); 81 REENTRANCE_LOCK(); 82 ret = phLibNfc_Llcp_SendTo(hRemoteDevice, 83 hLlcpSocket, 84 nsap, 85 &sSendBuffer, 86 nfc_jni_send_callback, 87 (void*)&cb_data); 88 REENTRANCE_UNLOCK(); 89 if(ret != NFCSTATUS_PENDING) 90 { 91 ALOGE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 92 goto clean_and_return; 93 } 94 TRACE("phLibNfc_Llcp_SendTo() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 95 96 /* Wait for callback response */ 97 if(sem_wait(&cb_data.sem)) 98 { 99 ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 100 goto clean_and_return; 101 } 102 103 if(cb_data.status != NFCSTATUS_SUCCESS) 104 { 105 goto clean_and_return; 106 } 107 108 result = JNI_TRUE; 109 110 clean_and_return: 111 if (sSendBuffer.buffer != NULL) 112 { 113 e->ReleaseByteArrayElements(data, (jbyte*)sSendBuffer.buffer, JNI_ABORT); 114 } 115 nfc_cb_data_deinit(&cb_data); 116 return result; 117 } 118 119 static jobject com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom(JNIEnv *e, jobject o, jint linkMiu) 120 { 121 NFCSTATUS ret; 122 struct timespec ts; 123 uint8_t ssap; 124 jobject llcpPacket = NULL; 125 phLibNfc_Handle hRemoteDevice; 126 phLibNfc_Handle hLlcpSocket; 127 phNfc_sData_t sReceiveBuffer; 128 jclass clsLlcpPacket; 129 jfieldID f; 130 jbyteArray receivedData = NULL; 131 struct nfc_jni_callback_data cb_data; 132 133 /* Create the local semaphore */ 134 if (!nfc_cb_data_init(&cb_data, NULL)) 135 { 136 goto clean_and_return; 137 } 138 139 /* Create new LlcpPacket object */ 140 if(nfc_jni_cache_object(e,"com/android/nfc/LlcpPacket",&(llcpPacket)) == -1) 141 { 142 ALOGE("Find LlcpPacket class error"); 143 goto clean_and_return; 144 } 145 146 /* Get NativeConnectionless class object */ 147 clsLlcpPacket = e->GetObjectClass(llcpPacket); 148 if(e->ExceptionCheck()) 149 { 150 ALOGE("Get Object class error"); 151 goto clean_and_return; 152 } 153 154 /* Retrieve handles */ 155 hRemoteDevice = nfc_jni_get_p2p_device_handle(e,o); 156 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 157 TRACE("phLibNfc_Llcp_RecvFrom(), Socket Handle = 0x%02x, Link LIU = %d", hLlcpSocket, linkMiu); 158 159 sReceiveBuffer.buffer = (uint8_t*)malloc(linkMiu); 160 sReceiveBuffer.length = linkMiu; 161 162 REENTRANCE_LOCK(); 163 ret = phLibNfc_Llcp_RecvFrom(hRemoteDevice, 164 hLlcpSocket, 165 &sReceiveBuffer, 166 nfc_jni_receive_callback, 167 &cb_data); 168 REENTRANCE_UNLOCK(); 169 if(ret != NFCSTATUS_PENDING && ret != NFCSTATUS_SUCCESS) 170 { 171 ALOGE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 172 goto clean_and_return; 173 } 174 TRACE("phLibNfc_Llcp_RecvFrom() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 175 176 /* Wait for callback response */ 177 if(sem_wait(&cb_data.sem)) 178 { 179 ALOGE("Failed to wait for semaphore (errno=0x%08x)", errno); 180 goto clean_and_return; 181 } 182 183 if(cb_data.status != NFCSTATUS_SUCCESS) 184 { 185 goto clean_and_return; 186 } 187 188 ssap = (uintptr_t)cb_data.pContext; 189 TRACE("Data Received From SSAP = %d\n, length = %d", ssap, sReceiveBuffer.length); 190 191 /* Set Llcp Packet remote SAP */ 192 f = e->GetFieldID(clsLlcpPacket, "mRemoteSap", "I"); 193 e->SetIntField(llcpPacket, f,(jbyte)ssap); 194 195 /* Set Llcp Packet Buffer */ 196 ALOGD("Set LlcpPacket Data Buffer\n"); 197 f = e->GetFieldID(clsLlcpPacket, "mDataBuffer", "[B"); 198 receivedData = e->NewByteArray(sReceiveBuffer.length); 199 e->SetByteArrayRegion(receivedData, 0, sReceiveBuffer.length,(jbyte *)sReceiveBuffer.buffer); 200 e->SetObjectField(llcpPacket, f, receivedData); 201 202 clean_and_return: 203 nfc_cb_data_deinit(&cb_data); 204 return llcpPacket; 205 } 206 207 static jboolean com_android_nfc_NativeLlcpConnectionlessSocket_doClose(JNIEnv *e, jobject o) 208 { 209 NFCSTATUS ret; 210 phLibNfc_Handle hLlcpSocket; 211 TRACE("Close Connectionless socket"); 212 213 /* Retrieve socket handle */ 214 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 215 216 TRACE("phLibNfc_Llcp_Close()"); 217 REENTRANCE_LOCK(); 218 ret = phLibNfc_Llcp_Close(hLlcpSocket); 219 REENTRANCE_UNLOCK(); 220 if(ret == NFCSTATUS_SUCCESS) 221 { 222 TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 223 return TRUE; 224 } 225 else 226 { 227 ALOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 228 return FALSE; 229 } 230 } 231 232 233 /* 234 * JNI registration. 235 */ 236 static JNINativeMethod gMethods[] = 237 { 238 {"doSendTo", "(I[B)Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doSendTo}, 239 240 {"doReceiveFrom", "(I)Lcom/android/nfc/LlcpPacket;", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doReceiveFrom}, 241 242 {"doClose", "()Z", (void *)com_android_nfc_NativeLlcpConnectionlessSocket_doClose}, 243 }; 244 245 246 int register_com_android_nfc_NativeLlcpConnectionlessSocket(JNIEnv *e) 247 { 248 return jniRegisterNativeMethods(e, 249 "com/android/nfc/dhimpl/NativeLlcpConnectionlessSocket", 250 gMethods, NELEM(gMethods)); 251 } 252 253 } // android namespace 254