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 namespace android { 25 26 /* 27 * Callbacks 28 */ 29 30 static void nfc_jni_disconnect_callback(void* pContext, 31 NFCSTATUS status) 32 { 33 PHNFC_UNUSED_VARIABLE(pContext); 34 35 LOG_CALLBACK("nfc_jni_llcp_disconnect_callback", status); 36 37 nfc_jni_cb_status = status; 38 39 sem_post(nfc_jni_llcp_sem); 40 } 41 42 43 static void nfc_jni_connect_callback(void* pContext, uint8_t nErrCode, NFCSTATUS status) 44 { 45 PHNFC_UNUSED_VARIABLE(pContext); 46 47 LOG_CALLBACK("nfc_jni_llcp_connect_callback", status); 48 49 nfc_jni_cb_status = status; 50 51 if(status == NFCSTATUS_SUCCESS) 52 { 53 TRACE("Socket connected\n"); 54 } 55 else 56 { 57 LOGD("Socket not connected:"); 58 switch(nErrCode) 59 { 60 case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_ACTIVE: 61 { 62 LOGD("> SAP NOT ACTIVE\n"); 63 }break; 64 65 case PHFRINFC_LLCP_DM_OPCODE_SAP_NOT_FOUND: 66 { 67 LOGD("> SAP NOT FOUND\n"); 68 }break; 69 70 case PHFRINFC_LLCP_DM_OPCODE_CONNECT_REJECTED: 71 { 72 LOGD("> CONNECT REJECTED\n"); 73 }break; 74 75 case PHFRINFC_LLCP_DM_OPCODE_CONNECT_NOT_ACCEPTED: 76 { 77 LOGD("> CONNECT NOT ACCEPTED\n"); 78 }break; 79 80 case PHFRINFC_LLCP_DM_OPCODE_SOCKET_NOT_AVAILABLE: 81 { 82 LOGD("> SOCKET NOT AVAILABLE\n"); 83 }break; 84 } 85 } 86 87 sem_post(nfc_jni_llcp_sem); 88 } 89 90 91 92 93 static void nfc_jni_receive_callback(void* pContext, NFCSTATUS status) 94 { 95 uint8_t i; 96 PHNFC_UNUSED_VARIABLE(pContext); 97 98 LOG_CALLBACK("nfc_jni_llcp_receive_callback", status); 99 100 nfc_jni_cb_status = status; 101 102 sem_post(nfc_jni_llcp_sem); 103 } 104 105 static void nfc_jni_send_callback(void *pContext, NFCSTATUS status) 106 { 107 PHNFC_UNUSED_VARIABLE(pContext); 108 109 LOG_CALLBACK("nfc_jni_llcp_send_callback", status); 110 111 nfc_jni_cb_status = status; 112 113 sem_post(nfc_jni_llcp_sem); 114 } 115 116 /* 117 * Methods 118 */ 119 static jboolean com_android_nfc_NativeLlcpSocket_doConnect(JNIEnv *e, jobject o, jint nSap) 120 { 121 NFCSTATUS ret; 122 struct timespec ts; 123 phLibNfc_Handle hLlcpSocket; 124 125 /* Retrieve socket handle */ 126 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 127 128 TRACE("phLibNfc_Llcp_Connect(%d)",nSap); 129 REENTRANCE_LOCK(); 130 ret = phLibNfc_Llcp_Connect(hLlcpSocket, 131 nSap, 132 nfc_jni_connect_callback, 133 (void*)hLlcpSocket); 134 REENTRANCE_UNLOCK(); 135 if(ret != NFCSTATUS_PENDING) 136 { 137 LOGE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret)); 138 return FALSE; 139 } 140 TRACE("phLibNfc_Llcp_Connect(%d) returned 0x%04x[%s]", nSap, ret, nfc_jni_get_status_name(ret)); 141 142 /* Wait for callback response */ 143 if(sem_wait(nfc_jni_llcp_sem) == -1) 144 return FALSE; 145 146 if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) 147 { 148 TRACE("LLCP Connect request OK"); 149 return TRUE; 150 } 151 else 152 { 153 LOGD("LLCP Connect request KO"); 154 return FALSE; 155 } 156 } 157 158 static jboolean com_android_nfc_NativeLlcpSocket_doConnectBy(JNIEnv *e, jobject o, jstring sn) 159 { 160 NFCSTATUS ret; 161 struct timespec ts; 162 phNfc_sData_t serviceName; 163 phLibNfc_Handle hLlcpSocket; 164 165 /* Retrieve socket handle */ 166 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 167 168 /* Service socket */ 169 serviceName.buffer = (uint8_t*)e->GetStringUTFChars(sn, NULL); 170 serviceName.length = (uint32_t)e->GetStringUTFLength(sn); 171 172 TRACE("phLibNfc_Llcp_ConnectByUri()"); 173 REENTRANCE_LOCK(); 174 ret = phLibNfc_Llcp_ConnectByUri(hLlcpSocket, 175 &serviceName, 176 nfc_jni_connect_callback, 177 (void*)hLlcpSocket); 178 REENTRANCE_UNLOCK(); 179 if(ret != NFCSTATUS_PENDING) 180 { 181 LOGE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 182 return FALSE; 183 } 184 TRACE("phLibNfc_Llcp_ConnectByUri() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 185 186 /* Wait for callback response */ 187 if(sem_wait(nfc_jni_llcp_sem) == -1) 188 return FALSE; 189 190 if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) 191 { 192 return TRUE; 193 } 194 else 195 { 196 return FALSE; 197 } 198 } 199 200 static jboolean com_android_nfc_NativeLlcpSocket_doClose(JNIEnv *e, jobject o) 201 { 202 NFCSTATUS ret; 203 phLibNfc_Handle hLlcpSocket; 204 205 /* Retrieve socket handle */ 206 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 207 208 TRACE("phLibNfc_Llcp_Close()"); 209 REENTRANCE_LOCK(); 210 ret = phLibNfc_Llcp_Close(hLlcpSocket); 211 REENTRANCE_UNLOCK(); 212 if(ret != NFCSTATUS_SUCCESS) 213 { 214 LOGE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 215 return FALSE; 216 } 217 TRACE("phLibNfc_Llcp_Close() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 218 return TRUE; 219 } 220 221 static jboolean com_android_nfc_NativeLlcpSocket_doSend(JNIEnv *e, jobject o, jbyteArray data) 222 { 223 NFCSTATUS ret; 224 struct timespec ts; 225 phLibNfc_Handle hLlcpSocket; 226 phNfc_sData_t sSendBuffer; 227 228 /* Retrieve socket handle */ 229 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 230 231 sSendBuffer.buffer = (uint8_t*)e->GetByteArrayElements(data, NULL); 232 sSendBuffer.length = (uint32_t)e->GetArrayLength(data); 233 234 TRACE("phLibNfc_Llcp_Send()"); 235 REENTRANCE_LOCK(); 236 ret = phLibNfc_Llcp_Send(hLlcpSocket, 237 &sSendBuffer, 238 nfc_jni_send_callback, 239 (void*)hLlcpSocket); 240 REENTRANCE_UNLOCK(); 241 if(ret != NFCSTATUS_PENDING) 242 { 243 LOGE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 244 return FALSE; 245 } 246 TRACE("phLibNfc_Llcp_Send() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 247 248 /* Wait for callback response */ 249 if(sem_wait(nfc_jni_llcp_sem) == -1) 250 return FALSE; 251 252 253 if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) 254 { 255 return TRUE; 256 } 257 else 258 { 259 return FALSE; 260 } 261 } 262 263 static jint com_android_nfc_NativeLlcpSocket_doReceive(JNIEnv *e, jobject o, jbyteArray buffer) 264 { 265 NFCSTATUS ret; 266 struct timespec ts; 267 phLibNfc_Handle hLlcpSocket; 268 phNfc_sData_t sReceiveBuffer; 269 270 /* Retrieve socket handle */ 271 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 272 273 sReceiveBuffer.buffer = (uint8_t*)e->GetByteArrayElements(buffer, NULL); 274 sReceiveBuffer.length = (uint32_t)e->GetArrayLength(buffer); 275 276 TRACE("phLibNfc_Llcp_Recv()"); 277 REENTRANCE_LOCK(); 278 ret = phLibNfc_Llcp_Recv(hLlcpSocket, 279 &sReceiveBuffer, 280 nfc_jni_receive_callback, 281 (void*)hLlcpSocket); 282 REENTRANCE_UNLOCK(); 283 if((ret != NFCSTATUS_SUCCESS) && (ret != NFCSTATUS_PENDING)) 284 { 285 /* Return status should be either SUCCESS or PENDING */ 286 LOGE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 287 return 0; 288 } 289 TRACE("phLibNfc_Llcp_Recv() returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 290 291 /* Wait for callback response (happen if status is either SUCCESS or PENDING) */ 292 if(sem_wait(nfc_jni_llcp_sem) == -1) 293 { 294 return 0; 295 } 296 297 if(nfc_jni_cb_status == NFCSTATUS_SUCCESS) 298 { 299 return sReceiveBuffer.length; 300 } 301 else 302 { 303 return 0; 304 } 305 } 306 307 static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU(JNIEnv *e, jobject o) 308 { 309 NFCSTATUS ret; 310 phLibNfc_Handle hLlcpSocket; 311 phLibNfc_Llcp_sSocketOptions_t remoteSocketOption; 312 313 /* Retrieve socket handle */ 314 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 315 316 TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU)"); 317 REENTRANCE_LOCK(); 318 ret = phLibNfc_Llcp_SocketGetRemoteOptions(hLlcpSocket, 319 &remoteSocketOption); 320 REENTRANCE_UNLOCK(); 321 if(ret == NFCSTATUS_SUCCESS) 322 { 323 TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 324 return remoteSocketOption.miu; 325 } 326 else 327 { 328 LOGW("phLibNfc_Llcp_SocketGetRemoteOptions(MIU) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 329 return 0; 330 } 331 } 332 333 static jint com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW(JNIEnv *e, jobject o) 334 { 335 NFCSTATUS ret; 336 phLibNfc_Handle hLlcpSocket; 337 phLibNfc_Llcp_sSocketOptions_t remoteSocketOption; 338 339 /* Retrieve socket handle */ 340 hLlcpSocket = nfc_jni_get_nfc_socket_handle(e,o); 341 342 TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW)"); 343 REENTRANCE_LOCK(); 344 ret = phLibNfc_Llcp_SocketGetRemoteOptions(hLlcpSocket, 345 &remoteSocketOption); 346 REENTRANCE_UNLOCK(); 347 if(ret == NFCSTATUS_SUCCESS) 348 { 349 TRACE("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 350 return remoteSocketOption.rw; 351 } 352 else 353 { 354 LOGW("phLibNfc_Llcp_SocketGetRemoteOptions(RW) returned 0x%04x[%s]", ret, nfc_jni_get_status_name(ret)); 355 return 0; 356 } 357 } 358 359 360 /* 361 * JNI registration. 362 */ 363 static JNINativeMethod gMethods[] = 364 { 365 {"doConnect", "(I)Z", 366 (void *)com_android_nfc_NativeLlcpSocket_doConnect}, 367 368 {"doConnectBy", "(Ljava/lang/String;)Z", 369 (void *)com_android_nfc_NativeLlcpSocket_doConnectBy}, 370 371 {"doClose", "()Z", 372 (void *)com_android_nfc_NativeLlcpSocket_doClose}, 373 374 {"doSend", "([B)Z", 375 (void *)com_android_nfc_NativeLlcpSocket_doSend}, 376 377 {"doReceive", "([B)I", 378 (void *)com_android_nfc_NativeLlcpSocket_doReceive}, 379 380 {"doGetRemoteSocketMiu", "()I", 381 (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketMIU}, 382 383 {"doGetRemoteSocketRw", "()I", 384 (void *)com_android_nfc_NativeLlcpSocket_doGetRemoteSocketRW}, 385 }; 386 387 388 int register_com_android_nfc_NativeLlcpSocket(JNIEnv *e) 389 { 390 nfc_jni_llcp_sem = (sem_t *)malloc(sizeof(sem_t)); 391 if(sem_init(nfc_jni_llcp_sem, 0, 0) == -1) 392 return -1; 393 394 return jniRegisterNativeMethods(e, 395 "com/android/nfc/NativeLlcpSocket",gMethods, NELEM(gMethods)); 396 } 397 398 } // namespace android 399