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 "bluetooth_common.cpp" 18 19 #include "android_bluetooth_common.h" 20 #include "JNIHelp.h" 21 #include "jni.h" 22 #include "utils/Log.h" 23 #include "utils/misc.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <unistd.h> 30 #include <cutils/properties.h> 31 32 #ifdef HAVE_BLUETOOTH 33 #include <dbus/dbus.h> 34 #endif 35 36 namespace android { 37 38 #ifdef HAVE_BLUETOOTH 39 40 static Properties remote_device_properties[] = { 41 {"Address", DBUS_TYPE_STRING}, 42 {"Name", DBUS_TYPE_STRING}, 43 {"Icon", DBUS_TYPE_STRING}, 44 {"Class", DBUS_TYPE_UINT32}, 45 {"UUIDs", DBUS_TYPE_ARRAY}, 46 {"Paired", DBUS_TYPE_BOOLEAN}, 47 {"Connected", DBUS_TYPE_BOOLEAN}, 48 {"Trusted", DBUS_TYPE_BOOLEAN}, 49 {"Blocked", DBUS_TYPE_BOOLEAN}, 50 {"Alias", DBUS_TYPE_STRING}, 51 {"Nodes", DBUS_TYPE_ARRAY}, 52 {"Adapter", DBUS_TYPE_OBJECT_PATH}, 53 {"LegacyPairing", DBUS_TYPE_BOOLEAN}, 54 {"RSSI", DBUS_TYPE_INT16}, 55 {"TX", DBUS_TYPE_UINT32} 56 }; 57 58 static Properties adapter_properties[] = { 59 {"Address", DBUS_TYPE_STRING}, 60 {"Name", DBUS_TYPE_STRING}, 61 {"Class", DBUS_TYPE_UINT32}, 62 {"Powered", DBUS_TYPE_BOOLEAN}, 63 {"Discoverable", DBUS_TYPE_BOOLEAN}, 64 {"DiscoverableTimeout", DBUS_TYPE_UINT32}, 65 {"Pairable", DBUS_TYPE_BOOLEAN}, 66 {"PairableTimeout", DBUS_TYPE_UINT32}, 67 {"Discovering", DBUS_TYPE_BOOLEAN}, 68 {"Devices", DBUS_TYPE_ARRAY}, 69 {"UUIDs", DBUS_TYPE_ARRAY}, 70 }; 71 72 typedef union { 73 char *str_val; 74 int int_val; 75 char **array_val; 76 } property_value; 77 78 jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, 79 const char *mtype) { 80 jfieldID field = env->GetFieldID(clazz, member, mtype); 81 if (field == NULL) { 82 LOGE("Can't find member %s", member); 83 } 84 return field; 85 } 86 87 typedef struct { 88 void (*user_cb)(DBusMessage *, void *, void *); 89 void *user; 90 void *nat; 91 JNIEnv *env; 92 } dbus_async_call_t; 93 94 void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { 95 96 dbus_async_call_t *req = (dbus_async_call_t *)data; 97 DBusMessage *msg; 98 99 /* This is guaranteed to be non-NULL, because this function is called only 100 when once the remote method invokation returns. */ 101 msg = dbus_pending_call_steal_reply(call); 102 103 if (msg) { 104 if (req->user_cb) { 105 // The user may not deref the message object. 106 req->user_cb(msg, req->user, req->nat); 107 } 108 dbus_message_unref(msg); 109 } 110 111 //dbus_message_unref(req->method); 112 dbus_pending_call_cancel(call); 113 dbus_pending_call_unref(call); 114 free(req); 115 } 116 117 static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, 118 DBusConnection *conn, 119 int timeout_ms, 120 void (*user_cb)(DBusMessage *, 121 void *, 122 void*), 123 void *user, 124 void *nat, 125 const char *path, 126 const char *ifc, 127 const char *func, 128 int first_arg_type, 129 va_list args) { 130 DBusMessage *msg = NULL; 131 const char *name; 132 dbus_async_call_t *pending; 133 dbus_bool_t reply = FALSE; 134 135 /* Compose the command */ 136 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); 137 138 if (msg == NULL) { 139 LOGE("Could not allocate D-Bus message object!"); 140 goto done; 141 } 142 143 /* append arguments */ 144 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { 145 LOGE("Could not append argument to method call!"); 146 goto done; 147 } 148 149 /* Make the call. */ 150 pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t)); 151 if (pending) { 152 DBusPendingCall *call; 153 154 pending->env = env; 155 pending->user_cb = user_cb; 156 pending->user = user; 157 pending->nat = nat; 158 //pending->method = msg; 159 160 reply = dbus_connection_send_with_reply(conn, msg, 161 &call, 162 timeout_ms); 163 if (reply == TRUE) { 164 dbus_pending_call_set_notify(call, 165 dbus_func_args_async_callback, 166 pending, 167 NULL); 168 } 169 } 170 171 done: 172 if (msg) dbus_message_unref(msg); 173 return reply; 174 } 175 176 dbus_bool_t dbus_func_args_async(JNIEnv *env, 177 DBusConnection *conn, 178 int timeout_ms, 179 void (*reply)(DBusMessage *, void *, void*), 180 void *user, 181 void *nat, 182 const char *path, 183 const char *ifc, 184 const char *func, 185 int first_arg_type, 186 ...) { 187 dbus_bool_t ret; 188 va_list lst; 189 va_start(lst, first_arg_type); 190 ret = dbus_func_args_async_valist(env, conn, 191 timeout_ms, 192 reply, user, nat, 193 path, ifc, func, 194 first_arg_type, lst); 195 va_end(lst); 196 return ret; 197 } 198 199 // If err is NULL, then any errors will be LOGE'd, and free'd and the reply 200 // will be NULL. 201 // If err is not NULL, then it is assumed that dbus_error_init was already 202 // called, and error's will be returned to the caller without logging. The 203 // return value is NULL iff an error was set. The client must free the error if 204 // set. 205 DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env, 206 DBusConnection *conn, 207 int timeout_ms, 208 DBusError *err, 209 const char *path, 210 const char *ifc, 211 const char *func, 212 int first_arg_type, 213 va_list args) { 214 215 DBusMessage *msg = NULL, *reply = NULL; 216 const char *name; 217 bool return_error = (err != NULL); 218 219 if (!return_error) { 220 err = (DBusError*)malloc(sizeof(DBusError)); 221 dbus_error_init(err); 222 } 223 224 /* Compose the command */ 225 msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); 226 227 if (msg == NULL) { 228 LOGE("Could not allocate D-Bus message object!"); 229 goto done; 230 } 231 232 /* append arguments */ 233 if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { 234 LOGE("Could not append argument to method call!"); 235 goto done; 236 } 237 238 /* Make the call. */ 239 reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err); 240 if (!return_error && dbus_error_is_set(err)) { 241 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg); 242 } 243 244 done: 245 if (!return_error) { 246 free(err); 247 } 248 if (msg) dbus_message_unref(msg); 249 return reply; 250 } 251 252 DBusMessage * dbus_func_args_timeout(JNIEnv *env, 253 DBusConnection *conn, 254 int timeout_ms, 255 const char *path, 256 const char *ifc, 257 const char *func, 258 int first_arg_type, 259 ...) { 260 DBusMessage *ret; 261 va_list lst; 262 va_start(lst, first_arg_type); 263 ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL, 264 path, ifc, func, 265 first_arg_type, lst); 266 va_end(lst); 267 return ret; 268 } 269 270 DBusMessage * dbus_func_args(JNIEnv *env, 271 DBusConnection *conn, 272 const char *path, 273 const char *ifc, 274 const char *func, 275 int first_arg_type, 276 ...) { 277 DBusMessage *ret; 278 va_list lst; 279 va_start(lst, first_arg_type); 280 ret = dbus_func_args_timeout_valist(env, conn, -1, NULL, 281 path, ifc, func, 282 first_arg_type, lst); 283 va_end(lst); 284 return ret; 285 } 286 287 DBusMessage * dbus_func_args_error(JNIEnv *env, 288 DBusConnection *conn, 289 DBusError *err, 290 const char *path, 291 const char *ifc, 292 const char *func, 293 int first_arg_type, 294 ...) { 295 DBusMessage *ret; 296 va_list lst; 297 va_start(lst, first_arg_type); 298 ret = dbus_func_args_timeout_valist(env, conn, -1, err, 299 path, ifc, func, 300 first_arg_type, lst); 301 va_end(lst); 302 return ret; 303 } 304 305 jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) { 306 307 DBusError err; 308 jint ret = -1; 309 310 dbus_error_init(&err); 311 if (!dbus_message_get_args(reply, &err, 312 DBUS_TYPE_INT32, &ret, 313 DBUS_TYPE_INVALID)) { 314 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 315 } 316 dbus_message_unref(reply); 317 return ret; 318 } 319 320 jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) { 321 322 DBusError err; 323 jint ret = -1; 324 325 dbus_error_init(&err); 326 if (!dbus_message_get_args(reply, &err, 327 DBUS_TYPE_UINT32, &ret, 328 DBUS_TYPE_INVALID)) { 329 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 330 } 331 dbus_message_unref(reply); 332 return ret; 333 } 334 335 jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) { 336 337 DBusError err; 338 jstring ret = NULL; 339 const char *name; 340 341 dbus_error_init(&err); 342 if (dbus_message_get_args(reply, &err, 343 DBUS_TYPE_STRING, &name, 344 DBUS_TYPE_INVALID)) { 345 ret = env->NewStringUTF(name); 346 } else { 347 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 348 } 349 dbus_message_unref(reply); 350 351 return ret; 352 } 353 354 jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) { 355 DBusError err; 356 jboolean ret = JNI_FALSE; 357 dbus_bool_t val = FALSE; 358 359 dbus_error_init(&err); 360 361 /* Check the return value. */ 362 if (dbus_message_get_args(reply, &err, 363 DBUS_TYPE_BOOLEAN, &val, 364 DBUS_TYPE_INVALID)) { 365 ret = val == TRUE ? JNI_TRUE : JNI_FALSE; 366 } else { 367 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 368 } 369 370 dbus_message_unref(reply); 371 return ret; 372 } 373 374 static void set_object_array_element(JNIEnv *env, jobjectArray strArray, 375 const char *value, int index) { 376 jstring obj; 377 obj = env->NewStringUTF(value); 378 env->SetObjectArrayElement(strArray, index, obj); 379 env->DeleteLocalRef(obj); 380 } 381 382 jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, 383 DBusMessage *reply) { 384 385 DBusError err; 386 char **list; 387 int i, len; 388 jobjectArray strArray = NULL; 389 390 dbus_error_init(&err); 391 if (dbus_message_get_args (reply, 392 &err, 393 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, 394 &list, &len, 395 DBUS_TYPE_INVALID)) { 396 jclass stringClass; 397 jstring classNameStr; 398 399 stringClass = env->FindClass("java/lang/String"); 400 strArray = env->NewObjectArray(len, stringClass, NULL); 401 402 for (i = 0; i < len; i++) 403 set_object_array_element(env, strArray, list[i], i); 404 } else { 405 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 406 } 407 408 dbus_message_unref(reply); 409 return strArray; 410 } 411 412 jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) { 413 414 DBusError err; 415 char **list; 416 int i, len; 417 jobjectArray strArray = NULL; 418 419 dbus_error_init(&err); 420 if (dbus_message_get_args (reply, 421 &err, 422 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, 423 &list, &len, 424 DBUS_TYPE_INVALID)) { 425 jclass stringClass; 426 jstring classNameStr; 427 428 //LOGV("%s: there are %d elements in string array!", __FUNCTION__, len); 429 430 stringClass = env->FindClass("java/lang/String"); 431 strArray = env->NewObjectArray(len, stringClass, NULL); 432 433 for (i = 0; i < len; i++) 434 set_object_array_element(env, strArray, list[i], i); 435 } else { 436 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 437 } 438 439 dbus_message_unref(reply); 440 return strArray; 441 } 442 443 jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) { 444 445 DBusError err; 446 int i, len; 447 jbyte *list; 448 jbyteArray byteArray = NULL; 449 450 dbus_error_init(&err); 451 if (dbus_message_get_args(reply, &err, 452 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len, 453 DBUS_TYPE_INVALID)) { 454 //LOGV("%s: there are %d elements in byte array!", __FUNCTION__, len); 455 byteArray = env->NewByteArray(len); 456 if (byteArray) 457 env->SetByteArrayRegion(byteArray, 0, len, list); 458 459 } else { 460 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); 461 } 462 463 dbus_message_unref(reply); 464 return byteArray; 465 } 466 467 void append_variant(DBusMessageIter *iter, int type, void *val) 468 { 469 DBusMessageIter value_iter; 470 char var_type[2] = { type, '\0'}; 471 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter); 472 dbus_message_iter_append_basic(&value_iter, type, val); 473 dbus_message_iter_close_container(iter, &value_iter); 474 } 475 476 int get_property(DBusMessageIter iter, Properties *properties, 477 int max_num_properties, int *prop_index, property_value *value, int *len) { 478 DBusMessageIter prop_val, array_val_iter; 479 char *property = NULL; 480 uint32_t array_type; 481 char *str_val; 482 int i, j, type, int_val; 483 484 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 485 return -1; 486 dbus_message_iter_get_basic(&iter, &property); 487 if (!dbus_message_iter_next(&iter)) 488 return -1; 489 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) 490 return -1; 491 for (i = 0; i < max_num_properties; i++) { 492 if (!strncmp(property, properties[i].name, strlen(property))) 493 break; 494 } 495 *prop_index = i; 496 if (i == max_num_properties) 497 return -1; 498 499 dbus_message_iter_recurse(&iter, &prop_val); 500 type = properties[*prop_index].type; 501 if (dbus_message_iter_get_arg_type(&prop_val) != type) { 502 LOGE("Property type mismatch in get_property: %d, expected:%d, index:%d", 503 dbus_message_iter_get_arg_type(&prop_val), type, *prop_index); 504 return -1; 505 } 506 507 switch(type) { 508 case DBUS_TYPE_STRING: 509 case DBUS_TYPE_OBJECT_PATH: 510 dbus_message_iter_get_basic(&prop_val, &value->str_val); 511 *len = 1; 512 break; 513 case DBUS_TYPE_UINT32: 514 case DBUS_TYPE_INT16: 515 case DBUS_TYPE_BOOLEAN: 516 dbus_message_iter_get_basic(&prop_val, &int_val); 517 value->int_val = int_val; 518 *len = 1; 519 break; 520 case DBUS_TYPE_ARRAY: 521 dbus_message_iter_recurse(&prop_val, &array_val_iter); 522 array_type = dbus_message_iter_get_arg_type(&array_val_iter); 523 *len = 0; 524 value->array_val = NULL; 525 if (array_type == DBUS_TYPE_OBJECT_PATH || 526 array_type == DBUS_TYPE_STRING){ 527 j = 0; 528 do { 529 j ++; 530 } while(dbus_message_iter_next(&array_val_iter)); 531 dbus_message_iter_recurse(&prop_val, &array_val_iter); 532 // Allocate an array of char * 533 *len = j; 534 char **tmp = (char **)malloc(sizeof(char *) * *len); 535 if (!tmp) 536 return -1; 537 j = 0; 538 do { 539 dbus_message_iter_get_basic(&array_val_iter, &tmp[j]); 540 j ++; 541 } while(dbus_message_iter_next(&array_val_iter)); 542 value->array_val = tmp; 543 } 544 break; 545 default: 546 return -1; 547 } 548 return 0; 549 } 550 551 void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property, 552 property_value *value, int len, int *array_index ) { 553 char **prop_val = NULL; 554 char buf[32] = {'\0'}, buf1[32] = {'\0'}; 555 int i; 556 557 char *name = property->name; 558 int prop_type = property->type; 559 560 set_object_array_element(env, strArray, name, *array_index); 561 *array_index += 1; 562 563 if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) { 564 sprintf(buf, "%d", value->int_val); 565 set_object_array_element(env, strArray, buf, *array_index); 566 *array_index += 1; 567 } else if (prop_type == DBUS_TYPE_BOOLEAN) { 568 sprintf(buf, "%s", value->int_val ? "true" : "false"); 569 570 set_object_array_element(env, strArray, buf, *array_index); 571 *array_index += 1; 572 } else if (prop_type == DBUS_TYPE_ARRAY) { 573 // Write the length first 574 sprintf(buf1, "%d", len); 575 set_object_array_element(env, strArray, buf1, *array_index); 576 *array_index += 1; 577 578 prop_val = value->array_val; 579 for (i = 0; i < len; i++) { 580 set_object_array_element(env, strArray, prop_val[i], *array_index); 581 *array_index += 1; 582 } 583 } else { 584 set_object_array_element(env, strArray, (const char *) value->str_val, *array_index); 585 *array_index += 1; 586 } 587 } 588 589 jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, 590 const int max_num_properties) { 591 DBusMessageIter dict_entry, dict; 592 jobjectArray strArray = NULL; 593 property_value value; 594 int i, size = 0,array_index = 0; 595 int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type; 596 struct { 597 property_value value; 598 int len; 599 bool used; 600 } values[max_num_properties]; 601 int t, j; 602 603 jclass stringClass = env->FindClass("java/lang/String"); 604 DBusError err; 605 dbus_error_init(&err); 606 607 for (i = 0; i < max_num_properties; i++) { 608 values[i].used = false; 609 } 610 611 if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) 612 goto failure; 613 dbus_message_iter_recurse(iter, &dict); 614 do { 615 len = 0; 616 if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) 617 goto failure; 618 dbus_message_iter_recurse(&dict, &dict_entry); 619 620 if (!get_property(dict_entry, properties, max_num_properties, &prop_index, 621 &value, &len)) { 622 size += 2; 623 if (properties[prop_index].type == DBUS_TYPE_ARRAY) 624 size += len; 625 values[prop_index].value = value; 626 values[prop_index].len = len; 627 values[prop_index].used = true; 628 } else { 629 goto failure; 630 } 631 } while(dbus_message_iter_next(&dict)); 632 633 strArray = env->NewObjectArray(size, stringClass, NULL); 634 635 for (i = 0; i < max_num_properties; i++) { 636 if (values[i].used) { 637 create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len, 638 &array_index); 639 640 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used 641 && values[i].value.array_val != NULL) 642 free(values[i].value.array_val); 643 } 644 645 } 646 return strArray; 647 648 failure: 649 if (dbus_error_is_set(&err)) 650 LOG_AND_FREE_DBUS_ERROR(&err); 651 for (i = 0; i < max_num_properties; i++) 652 if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true 653 && values[i].value.array_val != NULL) 654 free(values[i].value.array_val); 655 return NULL; 656 } 657 658 jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, 659 Properties *properties, int max_num_properties) { 660 DBusMessageIter iter; 661 DBusError err; 662 jobjectArray strArray = NULL; 663 jclass stringClass= env->FindClass("java/lang/String"); 664 int len = 0, prop_index = -1; 665 int array_index = 0, size = 0; 666 property_value value; 667 668 dbus_error_init(&err); 669 if (!dbus_message_iter_init(msg, &iter)) 670 goto failure; 671 672 if (!get_property(iter, properties, max_num_properties, 673 &prop_index, &value, &len)) { 674 size += 2; 675 if (properties[prop_index].type == DBUS_TYPE_ARRAY) 676 size += len; 677 strArray = env->NewObjectArray(size, stringClass, NULL); 678 679 create_prop_array(env, strArray, &properties[prop_index], 680 &value, len, &array_index); 681 682 if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL) 683 free(value.array_val); 684 685 return strArray; 686 } 687 failure: 688 LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); 689 return NULL; 690 } 691 692 jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) { 693 return parse_property_change(env, msg, (Properties *) &adapter_properties, 694 sizeof(adapter_properties) / sizeof(Properties)); 695 } 696 697 jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) { 698 return parse_property_change(env, msg, (Properties *) &remote_device_properties, 699 sizeof(remote_device_properties) / sizeof(Properties)); 700 } 701 702 jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) { 703 return parse_properties(env, iter, (Properties *) &adapter_properties, 704 sizeof(adapter_properties) / sizeof(Properties)); 705 } 706 707 jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) { 708 return parse_properties(env, iter, (Properties *) &remote_device_properties, 709 sizeof(remote_device_properties) / sizeof(Properties)); 710 } 711 712 int get_bdaddr(const char *str, bdaddr_t *ba) { 713 char *d = ((char *)ba) + 5, *endp; 714 int i; 715 for(i = 0; i < 6; i++) { 716 *d-- = strtol(str, &endp, 16); 717 if (*endp != ':' && i != 5) { 718 memset(ba, 0, sizeof(bdaddr_t)); 719 return -1; 720 } 721 str = endp + 1; 722 } 723 return 0; 724 } 725 726 void get_bdaddr_as_string(const bdaddr_t *ba, char *str) { 727 const uint8_t *b = (const uint8_t *)ba; 728 sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", 729 b[5], b[4], b[3], b[2], b[1], b[0]); 730 } 731 732 bool debug_no_encrypt() { 733 return false; 734 #if 0 735 char value[PROPERTY_VALUE_MAX] = ""; 736 737 property_get("debug.bt.no_encrypt", value, ""); 738 if (!strncmp("true", value, PROPERTY_VALUE_MAX) || 739 !strncmp("1", value, PROPERTY_VALUE_MAX)) { 740 LOGD("mandatory bluetooth encryption disabled"); 741 return true; 742 } else { 743 return false; 744 } 745 #endif 746 } 747 #endif 748 749 } /* namespace android */ 750