1/* 2** Copyright 2006, 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#define LOG_TAG "BT HSHFP" 18 19#include "android_bluetooth_common.h" 20#include "android_runtime/AndroidRuntime.h" 21#include "JNIHelp.h" 22#include "jni.h" 23#include "utils/Log.h" 24#include "utils/misc.h" 25 26#include <stdio.h> 27#include <string.h> 28#include <stdlib.h> 29#include <errno.h> 30#include <unistd.h> 31#include <fcntl.h> 32#include <sys/socket.h> 33#include <sys/uio.h> 34#include <sys/poll.h> 35 36#ifdef HAVE_BLUETOOTH 37#include <bluetooth/bluetooth.h> 38#include <bluetooth/rfcomm.h> 39#include <bluetooth/sco.h> 40#endif 41 42namespace android { 43 44#ifdef HAVE_BLUETOOTH 45static jfieldID field_mNativeData; 46static jfieldID field_mAddress; 47static jfieldID field_mRfcommChannel; 48static jfieldID field_mTimeoutRemainingMs; 49 50typedef struct { 51 jstring address; 52 const char *c_address; 53 int rfcomm_channel; 54 int last_read_err; 55 int rfcomm_sock; 56 int rfcomm_connected; // -1 in progress, 0 not connected, 1 connected 57 int rfcomm_sock_flags; 58} native_data_t; 59 60static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { 61 return (native_data_t *)(env->GetIntField(object, field_mNativeData)); 62} 63 64static const char CRLF[] = "\xd\xa"; 65static const int CRLF_LEN = 2; 66 67static inline int write_error_check(int fd, const char* line, int len) { 68 int ret; 69 errno = 0; 70 ret = write(fd, line, len); 71 if (ret < 0) { 72 LOGE("%s: write() failed: %s (%d)", __FUNCTION__, strerror(errno), 73 errno); 74 return -1; 75 } 76 if (ret != len) { 77 LOGE("%s: write() only wrote %d of %d bytes", __FUNCTION__, ret, len); 78 return -1; 79 } 80 return 0; 81} 82 83static int send_line(int fd, const char* line) { 84 int nw; 85 int len = strlen(line); 86 int llen = len + CRLF_LEN * 2 + 1; 87 char *buffer = (char *)calloc(llen, sizeof(char)); 88 89 snprintf(buffer, llen, "%s%s%s", CRLF, line, CRLF); 90 91 if (write_error_check(fd, buffer, llen - 1)) { 92 free(buffer); 93 return -1; 94 } 95 free(buffer); 96 return 0; 97} 98 99static int is_ascii(char *line) { 100 for (;;line++) { 101 if (*line == 0) return 1; 102 if (*line >> 7) return 0; 103 } 104} 105 106static const char* get_line(int fd, char *buf, int len, int timeout_ms, 107 int *err) { 108 char *bufit=buf; 109 int fd_flags = fcntl(fd, F_GETFL, 0); 110 struct pollfd pfd; 111 112again: 113 *bufit = 0; 114 pfd.fd = fd; 115 pfd.events = POLLIN; 116 *err = errno = 0; 117 int ret = poll(&pfd, 1, timeout_ms); 118 if (ret < 0) { 119 LOGE("poll() error\n"); 120 *err = errno; 121 return NULL; 122 } 123 if (ret == 0) { 124 return NULL; 125 } 126 127 if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) { 128 LOGW("RFCOMM poll() returned success (%d), " 129 "but with an unexpected revents bitmask: %#x\n", ret, pfd.revents); 130 errno = EIO; 131 *err = errno; 132 return NULL; 133 } 134 135 while ((int)(bufit - buf) < (len - 1)) 136 { 137 errno = 0; 138 int rc = read(fd, bufit, 1); 139 140 if (!rc) 141 break; 142 143 if (rc < 0) { 144 if (errno == EBUSY) { 145 LOGI("read() error %s (%d): repeating read()...", 146 strerror(errno), errno); 147 goto again; 148 } 149 *err = errno; 150 LOGE("read() error %s (%d)", strerror(errno), errno); 151 return NULL; 152 } 153 154 155 if (*bufit=='\xd') { 156 break; 157 } 158 159 if (*bufit=='\xa') 160 bufit = buf; 161 else 162 bufit++; 163 } 164 165 *bufit = NULL; 166 167 // Simple validation. Must be all ASCII. 168 // (we sometimes send non-ASCII UTF-8 in address book, but should 169 // never receive non-ASCII UTF-8). 170 // This was added because of the BMW 2005 E46 which sends binary junk. 171 if (is_ascii(buf)) { 172 IF_LOGV() LOG(LOG_VERBOSE, "Bluetooth AT recv", "%s", buf); 173 } else { 174 LOGW("Ignoring invalid AT command: %s", buf); 175 buf[0] = NULL; 176 } 177 178 return buf; 179} 180#endif 181 182static void classInitNative(JNIEnv* env, jclass clazz) { 183 LOGV(__FUNCTION__); 184#ifdef HAVE_BLUETOOTH 185 field_mNativeData = get_field(env, clazz, "mNativeData", "I"); 186 field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;"); 187 field_mTimeoutRemainingMs = get_field(env, clazz, "mTimeoutRemainingMs", "I"); 188 field_mRfcommChannel = get_field(env, clazz, "mRfcommChannel", "I"); 189#endif 190} 191 192static void initializeNativeDataNative(JNIEnv* env, jobject object, 193 jint socketFd) { 194 LOGV(__FUNCTION__); 195#ifdef HAVE_BLUETOOTH 196 native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); 197 if (NULL == nat) { 198 LOGE("%s: out of memory!", __FUNCTION__); 199 return; 200 } 201 202 env->SetIntField(object, field_mNativeData, (jint)nat); 203 nat->address = 204 (jstring)env->NewGlobalRef(env->GetObjectField(object, 205 field_mAddress)); 206 nat->c_address = env->GetStringUTFChars(nat->address, NULL); 207 nat->rfcomm_channel = env->GetIntField(object, field_mRfcommChannel); 208 nat->rfcomm_sock = socketFd; 209 nat->rfcomm_connected = socketFd >= 0; 210 if (nat->rfcomm_connected) 211 LOGI("%s: ALREADY CONNECTED!", __FUNCTION__); 212#endif 213} 214 215static void cleanupNativeDataNative(JNIEnv* env, jobject object) { 216 LOGV(__FUNCTION__); 217#ifdef HAVE_BLUETOOTH 218 native_data_t *nat = 219 (native_data_t *)env->GetIntField(object, field_mNativeData); 220 env->ReleaseStringUTFChars(nat->address, nat->c_address); 221 env->DeleteGlobalRef(nat->address); 222 if (nat) 223 free(nat); 224#endif 225} 226 227static jboolean connectNative(JNIEnv *env, jobject obj) 228{ 229 LOGV(__FUNCTION__); 230#ifdef HAVE_BLUETOOTH 231 int lm; 232 struct sockaddr_rc addr; 233 native_data_t *nat = get_native_data(env, obj); 234 235 nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 236 237 if (nat->rfcomm_sock < 0) { 238 LOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__, 239 strerror(errno)); 240 return JNI_FALSE; 241 } 242 243 if (debug_no_encrypt()) { 244 lm = RFCOMM_LM_AUTH; 245 } else { 246 lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; 247 } 248 249 if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm, 250 sizeof(lm)) < 0) { 251 LOGE("%s: Can't set RFCOMM link mode", __FUNCTION__); 252 close(nat->rfcomm_sock); 253 return JNI_FALSE; 254 } 255 256 memset(&addr, 0, sizeof(struct sockaddr_rc)); 257 get_bdaddr(nat->c_address, &addr.rc_bdaddr); 258 addr.rc_channel = nat->rfcomm_channel; 259 addr.rc_family = AF_BLUETOOTH; 260 nat->rfcomm_connected = 0; 261 while (nat->rfcomm_connected == 0) { 262 if (connect(nat->rfcomm_sock, (struct sockaddr *)&addr, 263 sizeof(addr)) < 0) { 264 if (errno == EINTR) continue; 265 LOGE("%s: connect() failed: %s\n", __FUNCTION__, strerror(errno)); 266 close(nat->rfcomm_sock); 267 nat->rfcomm_sock = -1; 268 return JNI_FALSE; 269 } else { 270 nat->rfcomm_connected = 1; 271 } 272 } 273 274 return JNI_TRUE; 275#else 276 return JNI_FALSE; 277#endif 278} 279 280static jint connectAsyncNative(JNIEnv *env, jobject obj) { 281 LOGV(__FUNCTION__); 282#ifdef HAVE_BLUETOOTH 283 struct sockaddr_rc addr; 284 native_data_t *nat = get_native_data(env, obj); 285 286 if (nat->rfcomm_connected) { 287 LOGV("RFCOMM socket is already connected or connection is in progress."); 288 return 0; 289 } 290 291 if (nat->rfcomm_sock < 0) { 292 int lm; 293 294 nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 295 if (nat->rfcomm_sock < 0) { 296 LOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__, 297 strerror(errno)); 298 return -1; 299 } 300 301 if (debug_no_encrypt()) { 302 lm = RFCOMM_LM_AUTH; 303 } else { 304 lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; 305 } 306 307 if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm, 308 sizeof(lm)) < 0) { 309 LOGE("%s: Can't set RFCOMM link mode", __FUNCTION__); 310 close(nat->rfcomm_sock); 311 return -1; 312 } 313 LOGI("Created RFCOMM socket fd %d.", nat->rfcomm_sock); 314 } 315 316 memset(&addr, 0, sizeof(struct sockaddr_rc)); 317 get_bdaddr(nat->c_address, &addr.rc_bdaddr); 318 addr.rc_channel = nat->rfcomm_channel; 319 addr.rc_family = AF_BLUETOOTH; 320 if (nat->rfcomm_sock_flags >= 0) { 321 nat->rfcomm_sock_flags = fcntl(nat->rfcomm_sock, F_GETFL, 0); 322 if (fcntl(nat->rfcomm_sock, 323 F_SETFL, nat->rfcomm_sock_flags | O_NONBLOCK) >= 0) { 324 int rc; 325 nat->rfcomm_connected = 0; 326 errno = 0; 327 rc = connect(nat->rfcomm_sock, 328 (struct sockaddr *)&addr, 329 sizeof(addr)); 330 331 if (rc >= 0) { 332 nat->rfcomm_connected = 1; 333 LOGI("async connect successful"); 334 return 0; 335 } 336 else if (rc < 0) { 337 if (errno == EINPROGRESS || errno == EAGAIN) 338 { 339 LOGI("async connect is in progress (%s)", 340 strerror(errno)); 341 nat->rfcomm_connected = -1; 342 return 0; 343 } 344 else 345 { 346 LOGE("async connect error: %s (%d)", strerror(errno), errno); 347 close(nat->rfcomm_sock); 348 nat->rfcomm_sock = -1; 349 return -errno; 350 } 351 } 352 } // fcntl(nat->rfcomm_sock ...) 353 } // if (nat->rfcomm_sock_flags >= 0) 354#endif 355 return -1; 356} 357 358static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj, 359 jint timeout_ms) { 360 LOGV(__FUNCTION__); 361#ifdef HAVE_BLUETOOTH 362 struct sockaddr_rc addr; 363 native_data_t *nat = get_native_data(env, obj); 364 365 env->SetIntField(obj, field_mTimeoutRemainingMs, timeout_ms); 366 367 if (nat->rfcomm_connected > 0) { 368 LOGI("RFCOMM is already connected!"); 369 return 1; 370 } 371 372 if (nat->rfcomm_sock >= 0 && nat->rfcomm_connected == 0) { 373 LOGI("Re-opening RFCOMM socket."); 374 close(nat->rfcomm_sock); 375 nat->rfcomm_sock = -1; 376 } 377 int ret = connectAsyncNative(env, obj); 378 379 if (ret < 0) { 380 LOGI("Failed to re-open RFCOMM socket!"); 381 return ret; 382 } 383 384 if (nat->rfcomm_sock >= 0) { 385 /* Do an asynchronous select() */ 386 int n; 387 fd_set rset, wset; 388 struct timeval to; 389 390 FD_ZERO(&rset); 391 FD_ZERO(&wset); 392 FD_SET(nat->rfcomm_sock, &rset); 393 FD_SET(nat->rfcomm_sock, &wset); 394 if (timeout_ms >= 0) { 395 to.tv_sec = timeout_ms / 1000; 396 to.tv_usec = 1000 * (timeout_ms % 1000); 397 } 398 n = select(nat->rfcomm_sock + 1, 399 &rset, 400 &wset, 401 NULL, 402 (timeout_ms < 0 ? NULL : &to)); 403 404 if (timeout_ms > 0) { 405 jint remaining = to.tv_sec*1000 + to.tv_usec/1000; 406 LOGV("Remaining time %ldms", (long)remaining); 407 env->SetIntField(obj, field_mTimeoutRemainingMs, 408 remaining); 409 } 410 411 if (n <= 0) { 412 if (n < 0) { 413 LOGE("select() on RFCOMM socket: %s (%d)", 414 strerror(errno), 415 errno); 416 return -errno; 417 } 418 return 0; 419 } 420 /* n must be equal to 1 and either rset or wset must have the 421 file descriptor set. */ 422 LOGV("select() returned %d.", n); 423 if (FD_ISSET(nat->rfcomm_sock, &rset) || 424 FD_ISSET(nat->rfcomm_sock, &wset)) 425 { 426 /* A trial async read() will tell us if everything is OK. */ 427 { 428 char ch; 429 errno = 0; 430 int nr = read(nat->rfcomm_sock, &ch, 1); 431 /* It should be that nr != 1 because we just opened a socket 432 and we haven't sent anything over it for the other side to 433 respond... but one can't be paranoid enough. 434 */ 435 if (nr >= 0 || errno != EAGAIN) { 436 LOGE("RFCOMM async connect() error: %s (%d), nr = %d\n", 437 strerror(errno), 438 errno, 439 nr); 440 /* Clear the rfcomm_connected flag to cause this function 441 to re-create the socket and re-attempt the connect() 442 the next time it is called. 443 */ 444 nat->rfcomm_connected = 0; 445 /* Restore the blocking properties of the socket. */ 446 fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags); 447 close(nat->rfcomm_sock); 448 nat->rfcomm_sock = -1; 449 return -errno; 450 } 451 } 452 /* Restore the blocking properties of the socket. */ 453 fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags); 454 LOGI("Successful RFCOMM socket connect."); 455 nat->rfcomm_connected = 1; 456 return 1; 457 } 458 } 459 else LOGE("RFCOMM socket file descriptor %d is bad!", 460 nat->rfcomm_sock); 461#endif 462 return -1; 463} 464 465static void disconnectNative(JNIEnv *env, jobject obj) { 466 LOGV(__FUNCTION__); 467#ifdef HAVE_BLUETOOTH 468 native_data_t *nat = get_native_data(env, obj); 469 if (nat->rfcomm_sock >= 0) { 470 close(nat->rfcomm_sock); 471 nat->rfcomm_sock = -1; 472 nat->rfcomm_connected = 0; 473 } 474#endif 475} 476 477static void pretty_log_urc(const char *urc) { 478 size_t i; 479 bool in_line_break = false; 480 char *buf = (char *)calloc(strlen(urc) + 1, sizeof(char)); 481 482 strcpy(buf, urc); 483 for (i = 0; i < strlen(buf); i++) { 484 switch(buf[i]) { 485 case '\r': 486 case '\n': 487 in_line_break = true; 488 buf[i] = ' '; 489 break; 490 default: 491 if (in_line_break) { 492 in_line_break = false; 493 buf[i-1] = '\n'; 494 } 495 } 496 } 497 IF_LOGV() LOG(LOG_VERBOSE, "Bluetooth AT sent", "%s", buf); 498 499 free(buf); 500} 501 502static jboolean sendURCNative(JNIEnv *env, jobject obj, jstring urc) { 503#ifdef HAVE_BLUETOOTH 504 native_data_t *nat = get_native_data(env, obj); 505 if (nat->rfcomm_connected) { 506 const char *c_urc = env->GetStringUTFChars(urc, NULL); 507 jboolean ret = send_line(nat->rfcomm_sock, c_urc) == 0 ? JNI_TRUE : JNI_FALSE; 508 if (ret == JNI_TRUE) pretty_log_urc(c_urc); 509 env->ReleaseStringUTFChars(urc, c_urc); 510 return ret; 511 } 512#endif 513 return JNI_FALSE; 514} 515 516static jstring readNative(JNIEnv *env, jobject obj, jint timeout_ms) { 517#ifdef HAVE_BLUETOOTH 518 { 519 native_data_t *nat = get_native_data(env, obj); 520 if (nat->rfcomm_connected) { 521 char buf[256]; 522 const char *ret = get_line(nat->rfcomm_sock, 523 buf, sizeof(buf), 524 timeout_ms, 525 &nat->last_read_err); 526 return ret ? env->NewStringUTF(ret) : NULL; 527 } 528 return NULL; 529 } 530#else 531 return NULL; 532#endif 533} 534 535static jint getLastReadStatusNative(JNIEnv *env, jobject obj) { 536#ifdef HAVE_BLUETOOTH 537 { 538 native_data_t *nat = get_native_data(env, obj); 539 if (nat->rfcomm_connected) 540 return (jint)nat->last_read_err; 541 return 0; 542 } 543#else 544 return 0; 545#endif 546} 547 548static JNINativeMethod sMethods[] = { 549 /* name, signature, funcPtr */ 550 {"classInitNative", "()V", (void*)classInitNative}, 551 {"initializeNativeDataNative", "(I)V", (void *)initializeNativeDataNative}, 552 {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, 553 {"connectNative", "()Z", (void *)connectNative}, 554 {"connectAsyncNative", "()I", (void *)connectAsyncNative}, 555 {"waitForAsyncConnectNative", "(I)I", (void *)waitForAsyncConnectNative}, 556 {"disconnectNative", "()V", (void *)disconnectNative}, 557 {"sendURCNative", "(Ljava/lang/String;)Z", (void *)sendURCNative}, 558 {"readNative", "(I)Ljava/lang/String;", (void *)readNative}, 559 {"getLastReadStatusNative", "()I", (void *)getLastReadStatusNative}, 560}; 561 562int register_android_bluetooth_HeadsetBase(JNIEnv *env) { 563 return AndroidRuntime::registerNativeMethods(env, 564 "android/bluetooth/HeadsetBase", sMethods, NELEM(sMethods)); 565} 566 567} /* namespace android */ 568