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