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