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