1 /****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 /************************************************************************************ 20 * 21 * Filename: btif_config.c 22 * 23 * Description: Stores the local BT adapter and remote device properties in 24 * NVRAM storage, typically as xml file in the 25 * mobile's filesystem 26 * 27 * 28 ***********************************************************************************/ 29 #include <stdlib.h> 30 #include <time.h> 31 #include <string.h> 32 #include <ctype.h> 33 #include <stdio.h> 34 #include <fcntl.h> 35 #include <errno.h> 36 #include <unistd.h> 37 #include <dirent.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <sys/mman.h> 41 #include <stdlib.h> 42 #include <private/android_filesystem_config.h> 43 44 #define LOG_TAG "btif_config" 45 46 #include <hardware/bluetooth.h> 47 #include "btif_api.h" 48 #include "btif_config.h" 49 #include "btif_config_util.h" 50 #include "btif_sock_thread.h" 51 #include "btif_sock_util.h" 52 53 #define asrt(s) if(!(s)) BTIF_TRACE_ERROR3 ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__) 54 //#define UNIT_TEST 55 #define CFG_PATH "/data/misc/bluedroid/" 56 #define CFG_FILE_NAME "bt_config" 57 #define CFG_FILE_EXT ".xml" 58 #define CFG_FILE_EXT_OLD ".old" 59 #define CFG_FILE_EXT_NEW ".new" 60 #define CFG_GROW_SIZE (10*sizeof(cfg_node)) 61 #define GET_CHILD_MAX_COUNT(node) (short)((int)(node)->bytes / sizeof(cfg_node)) 62 #define IS_EMPTY(node) ((node)->name == NULL) 63 #define GET_NODE_COUNT(bytes) (bytes / sizeof(cfg_node)) 64 #define MAX_NODE_BYTES 32000 65 #define MAX_CACHED_COUNT 150 66 #define CFG_CMD_SAVE 1 67 68 #ifndef FALSE 69 #define TRUE 1 70 #define FALSE 0 71 #endif 72 typedef struct cfg_node_s 73 { 74 const char* name; 75 union 76 { 77 struct cfg_node_s* child; 78 char* value; 79 }; 80 short bytes; 81 short type; 82 short used; 83 short flag; 84 } cfg_node; 85 86 static pthread_mutex_t slot_lock; 87 static int pth = -1; //poll thread handle 88 static cfg_node root; 89 static int cached_change; 90 static void cfg_cmd_callback(int cmd_fd, int type, int flags, uint32_t user_id); 91 static inline short alloc_node(cfg_node* p, short grow); 92 static inline void free_node(cfg_node* p); 93 static inline void free_inode(cfg_node* p, int child); 94 static inline short find_inode(const cfg_node* p, const char* name); 95 static cfg_node* find_node(const char* section, const char* key, const char* name); 96 static int remove_node(const char* section, const char* key, const char* name); 97 static inline cfg_node* find_free_node(cfg_node* p); 98 static int set_node(const char* section, const char* key, const char* name, 99 const char* value, short bytes, short type); 100 static int save_cfg(); 101 static void load_cfg(); 102 static short find_next_node(const cfg_node* p, short start, char* name, int* bytes); 103 static int create_dir(const char* path); 104 #ifdef UNIT_TEST 105 static void cfg_test_load(); 106 static void cfg_test_write(); 107 static void cfg_test_read(); 108 #endif 109 static inline void dump_node(const char* title, const cfg_node* p) 110 { 111 if(p) { 112 BTIF_TRACE_DEBUG4("%s, p->name:%s, child/value:%p, bytes:%d", 113 title, p->name, p->child, p->bytes); 114 BTIF_TRACE_DEBUG3("p->used:%d, type:%x, p->flag:%d", 115 p->used, p->type, p->flag); 116 } else BTIF_TRACE_DEBUG1("%s is NULL", title); 117 } 118 //////////////////////////////////////////////////////////////////////////////////////////////////////////// 119 int btif_config_init() 120 { 121 static int initialized; 122 BTIF_TRACE_DEBUG1("in initialized:%d", initialized); 123 if(!initialized) 124 { 125 initialized = 1; 126 struct stat st; 127 if(stat(CFG_PATH, &st) != 0) 128 BTIF_TRACE_ERROR1("%s does not exist, need provision", CFG_PATH); 129 btsock_thread_init(); 130 init_slot_lock(&slot_lock); 131 lock_slot(&slot_lock); 132 root.name = "Bluedroid"; 133 alloc_node(&root, CFG_GROW_SIZE); 134 dump_node("root", &root); 135 pth = btsock_thread_create(NULL, cfg_cmd_callback); 136 load_cfg(); 137 unlock_slot(&slot_lock); 138 #ifdef UNIT_TEST 139 //cfg_test_load(); 140 cfg_test_write(); 141 cfg_test_read(); 142 #endif 143 } 144 return pth >= 0; 145 } 146 int btif_config_get_int(const char* section, const char* key, const char* name, int* value) 147 { 148 int size = sizeof(*value); 149 int type = BTIF_CFG_TYPE_INT; 150 return btif_config_get(section, key, name, (char*)value, &size, &type); 151 } 152 int btif_config_set_int(const char* section, const char* key, const char* name, int value) 153 { 154 return btif_config_set(section, key, name, (char*)&value, sizeof(value), BTIF_CFG_TYPE_INT); 155 } 156 int btif_config_get_str(const char* section, const char* key, const char* name, char* value, int* size) 157 { 158 int type = BTIF_CFG_TYPE_STR; 159 if(value) 160 *value = 0; 161 return btif_config_get(section, key, name, value, size, &type); 162 } 163 int btif_config_set_str(const char* section, const char* key, const char* name, const char* value) 164 { 165 value = value ? value : ""; 166 return btif_config_set(section, key, name, value, strlen(value) + 1, BTIF_CFG_TYPE_STR); 167 } 168 int btif_config_exist(const char* section, const char* key, const char* name) 169 { 170 int ret = FALSE; 171 if(section && *section && key && *key) 172 { 173 lock_slot(&slot_lock); 174 ret = find_node(section, key, name) != NULL; 175 unlock_slot(&slot_lock); 176 } 177 return ret; 178 } 179 int btif_config_get(const char* section, const char* key, const char* name, char* value, int* bytes, int* type) 180 { 181 int ret = FALSE; 182 asrt(section && *section && key && *key && name && *name && bytes && type); 183 //debug("section:%s, key:%s, name:%s, value:%p, bytes:%d, type:%d", 184 // section, key, name, value, *bytes, *type); 185 if(section && *section && key && *key && name && *name && bytes && type) 186 { 187 lock_slot(&slot_lock); 188 const cfg_node* node = find_node(section, key, name); 189 dump_node("found node", node); 190 if(node) 191 { 192 if(*type == node->type && value && *bytes >= node->used) 193 { 194 if(node->used > 0) 195 memcpy(value, node->value, node->used); 196 ret = TRUE; 197 } 198 *type = node->type; 199 *bytes = node->used; 200 if(ret != TRUE) 201 { 202 if(*type != node->type) 203 BTIF_TRACE_ERROR3("value:%s, wrong type:%d, need to be type: %d", 204 name, *type, node->type); 205 if(value && *bytes < node->used) 206 BTIF_TRACE_ERROR3("value:%s, not enough size: %d bytes, need %d bytes", 207 name, node->used, *bytes); 208 } 209 } 210 unlock_slot(&slot_lock); 211 } 212 //debug("out"); 213 return ret; 214 } 215 int btif_config_set(const char* section, const char* key, const char* name, const char* value, int bytes, int type) 216 { 217 int ret = FALSE; 218 asrt(section && *section && key && *key && name && *name); 219 asrt(bytes < MAX_NODE_BYTES); 220 if(section && *section && key && *key && name && *name && bytes < MAX_NODE_BYTES) 221 { 222 lock_slot(&slot_lock); 223 ret = set_node(section, key, name, value, (short)bytes, (short)type); 224 if(ret && !(type & BTIF_CFG_TYPE_VOLATILE) && ++cached_change > MAX_CACHED_COUNT) 225 { 226 cached_change = 0; 227 btsock_thread_post_cmd(pth, CFG_CMD_SAVE, NULL, 0, 0); 228 } 229 230 unlock_slot(&slot_lock); 231 } 232 return ret; 233 } 234 int btif_config_remove(const char* section, const char* key, const char* name) 235 { 236 asrt(section && *section && key && *key); 237 int ret = FALSE; 238 if(section && *section && key && *key) 239 { 240 lock_slot(&slot_lock); 241 ret = remove_node(section, key, name); 242 if(ret) 243 cached_change++; 244 unlock_slot(&slot_lock); 245 } 246 return ret; 247 } 248 typedef struct { 249 short si; 250 short ki; 251 short vi; 252 short reserved; 253 } cfg_node_pos; 254 short btif_config_next_key(short pos, const char* section, char * name, int* bytes) 255 { 256 int next = -1; 257 lock_slot(&slot_lock); 258 short si = find_inode(&root, section); 259 if(si >= 0) 260 { 261 const cfg_node* section_node = &root.child[si]; 262 next = find_next_node(section_node, pos, name, bytes); 263 } 264 unlock_slot(&slot_lock); 265 return next; 266 } 267 short btif_config_next_value(short pos, const char* section, const char* key, char* name, int* bytes) 268 { 269 int next = -1; 270 lock_slot(&slot_lock); 271 short si = find_inode(&root, section); 272 if(si >= 0) 273 { 274 const cfg_node* section_node = &root.child[si]; 275 short ki = find_inode(section_node, key); 276 if(ki >= 0) 277 { 278 const cfg_node* key_node = §ion_node->child[ki]; 279 next = find_next_node(key_node, pos, name, bytes); 280 } 281 } 282 unlock_slot(&slot_lock); 283 return next; 284 } 285 int btif_config_enum(btif_config_enum_callback cb, void* user_data) 286 { 287 asrt(cb); 288 if(!cb) 289 return FALSE; 290 lock_slot(&slot_lock); 291 int si, ki, vi; 292 cfg_node *section_node, *key_node, *value_node; 293 for(si = 0; si < GET_CHILD_MAX_COUNT(&root); si++) 294 { 295 section_node = &root.child[si]; 296 if(section_node->name && *section_node->name) 297 { 298 for(ki = 0; ki < GET_CHILD_MAX_COUNT(section_node); ki++) 299 { 300 key_node = §ion_node->child[ki]; 301 if(key_node->name && *key_node->name) 302 { 303 for(vi = 0; vi < GET_CHILD_MAX_COUNT(key_node); vi++) 304 { 305 value_node = &key_node->child[vi]; 306 if(value_node->name && *value_node->name) 307 { 308 cb(user_data, section_node->name, key_node->name, value_node->name, 309 value_node->value, value_node->used, value_node->type); 310 } 311 } 312 } 313 } 314 } 315 } 316 unlock_slot(&slot_lock); 317 return TRUE; 318 } 319 int btif_config_save() 320 { 321 lock_slot(&slot_lock); 322 if(cached_change > 0) 323 { 324 cached_change = 0; 325 btsock_thread_post_cmd(pth, CFG_CMD_SAVE, NULL, 0, 0); 326 } 327 unlock_slot(&slot_lock); 328 return TRUE; 329 } 330 void btif_config_flush() 331 { 332 lock_slot(&slot_lock); 333 if(cached_change > 0) 334 save_cfg(); 335 unlock_slot(&slot_lock); 336 } 337 ///////////////////////////////////////////////////////////////////////////////////////////// 338 static inline short alloc_node(cfg_node* p, short grow) 339 { 340 int new_bytes = p->bytes + grow; 341 //debug("in, bytes:%d, new bytes:%d, grow:%d", p->bytes, new_bytes, grow); 342 if(grow > 0 && new_bytes < MAX_NODE_BYTES) 343 { 344 char* value = (char*)realloc(p->value, new_bytes); 345 if(value) 346 { 347 short old_bytes = p->bytes; 348 //clear to zero 349 memset(value + old_bytes, 0, grow); 350 p->bytes = old_bytes + grow; 351 p->value = value; 352 //debug("out"); 353 return old_bytes;//return the previous size 354 } 355 else BTIF_TRACE_ERROR3("realloc failed, old_bytes:%d, grow:%d, total:%d", p->bytes, grow, p->bytes + grow); 356 } 357 //debug("out, alloc failed"); 358 return -1; 359 } 360 static inline void free_node(cfg_node* p) 361 { 362 if(p) 363 { 364 if(p->child) 365 { 366 free(p->child); 367 p->child = NULL; 368 } 369 if(p->name) 370 { 371 free((void*)p->name); 372 p->name = 0; 373 } 374 p->used = p->bytes = p->flag = p->type = 0; 375 } 376 } 377 static inline short find_inode(const cfg_node* p, const char* name) 378 { 379 //debug("in"); 380 if(p && p->child && name && *name) 381 { 382 int i; 383 int count = GET_CHILD_MAX_COUNT(p); 384 //debug("child name:%s, child max count:%d", name, count); 385 for(i = 0; i < count; i++) 386 { 387 if(p->child[i].name && *p->child[i].name && 388 strcmp(p->child[i].name, name) == 0) 389 { 390 //debug("out found child index:%d", i); 391 return (short)i; 392 } 393 } 394 } 395 //debug("out, child name: %s not found", name); 396 return -1; 397 } 398 static inline cfg_node* find_free_node(cfg_node* p) 399 { 400 if(p && p->child) 401 { 402 int i; 403 int count = GET_CHILD_MAX_COUNT(p); 404 //debug("p->name:%s, max child count:%d", p->name, count); 405 for(i = 0; i < count; i++) 406 { 407 if(IS_EMPTY(p->child + i)) 408 return p->child + i; 409 } 410 } 411 return NULL; 412 } 413 static cfg_node* find_add_node(cfg_node* p, const char* name) 414 { 415 int i = -1; 416 cfg_node* node = NULL; 417 //debug("in, p->name:%s, p->bytes:%d, adding child:%s", p->name, p->bytes, name); 418 if((i = find_inode(p, name)) < 0) 419 { 420 if(!(node = find_free_node(p))) 421 { 422 int old_size = alloc_node(p, CFG_GROW_SIZE); 423 if(old_size >= 0) 424 { 425 i = GET_NODE_COUNT(old_size); 426 node = &p->child[i]; 427 } 428 } 429 } 430 else node = &p->child[i]; 431 if(!node->name) 432 node->name = strdup(name); 433 //debug("out"); 434 return node; 435 } 436 static int set_node(const char* section, const char* key, const char* name, 437 const char* value, short bytes, short type) 438 { 439 int si = -1, ki = -1, vi = -1; 440 cfg_node* section_node = NULL; 441 //debug("in"); 442 //dump_node("root", &root); 443 if((section_node = find_add_node(&root, section))) 444 { 445 //dump_node("section node", section_node); 446 cfg_node* key_node; 447 if((key_node = find_add_node(section_node, key))) 448 { 449 //dump_node("key node", key_node); 450 cfg_node* value_node; 451 if((value_node = find_add_node(key_node, name))) 452 { 453 //dump_node("value node", value_node); 454 if(value_node->bytes < bytes) 455 { 456 if(value_node->value) 457 free(value_node->value); 458 value_node->value = (char*)malloc(bytes); 459 if(value_node->value) 460 value_node->bytes = bytes; 461 else 462 { 463 BTIF_TRACE_ERROR0("not enough memory!"); 464 value_node->bytes = 0; 465 return FALSE; 466 } 467 } 468 if(value_node->value && value != NULL && bytes > 0) 469 memcpy(value_node->value, value, bytes); 470 value_node->type = type; 471 value_node->used = bytes; 472 //dump_node("changed value node", value_node); 473 return TRUE; 474 } 475 } 476 } 477 return FALSE; 478 } 479 static cfg_node* find_node(const char* section, const char* key, const char* name) 480 { 481 int si = -1, ki = -1, vi = -1; 482 if((si = find_inode(&root, section)) >= 0) 483 { 484 cfg_node* section_node = &root.child[si]; 485 if(key) 486 { 487 //dump_node("found section node", section_node); 488 if((ki = find_inode(section_node, key)) >= 0) 489 { 490 cfg_node* key_node = §ion_node->child[ki]; 491 //dump_node("found key node", key_node); 492 if(name) 493 { 494 if((vi = find_inode(key_node, name)) >= 0) 495 { 496 //dump_node("found value node", &key_node->child[vi]); 497 return &key_node->child[vi]; 498 } 499 //debug("value node:%s not found", name); 500 return NULL; 501 } 502 return key_node; 503 } 504 //debug("key node:%s not found", key); 505 return NULL; 506 } 507 return section_node; 508 } 509 //debug("section node:%s not found", section); 510 return NULL; 511 } 512 static short find_next_node(const cfg_node* p, short start, char* name, int* bytes) 513 { 514 asrt(0 <= start && start < GET_CHILD_MAX_COUNT(p)); 515 //debug("in, start:%d, max child count:%d", start, GET_CHILD_MAX_COUNT(p)); 516 //dump_node("find_next_node, parent", p); 517 short next = -1; 518 if(name) *name = 0; 519 if(0 <= start && start < GET_CHILD_MAX_COUNT(p)) 520 { 521 int i; 522 for(i = start; i < GET_CHILD_MAX_COUNT(p); i++) 523 { 524 cfg_node* child = &p->child[i]; 525 if(child->name) 526 { 527 int name_bytes = strlen(child->name) + 1; 528 if(name && bytes && *bytes >= name_bytes) 529 { 530 memcpy(name, child->name, name_bytes); 531 if(i + 1 < GET_CHILD_MAX_COUNT(p)) 532 next = (short)(i + 1); 533 *bytes = name_bytes; 534 } 535 else if(bytes) 536 { 537 //debug("not enough room to copy the name, size in:%d, size needed:%d", *bytes, name_bytes); 538 *bytes = name_bytes; 539 } 540 break; 541 } 542 } 543 } 544 return next; 545 } 546 static int remove_node(const char* section, const char* key, const char* name) 547 { 548 short si = -1, ki = -1, vi = -1; 549 if((si = find_inode(&root, section)) >= 0) 550 { 551 cfg_node* section_node = &root.child[si]; 552 if((ki = find_inode(section_node, key)) >= 0) 553 { 554 cfg_node* key_node = §ion_node->child[ki]; 555 if(name == NULL) 556 { 557 int count = GET_CHILD_MAX_COUNT(key_node); 558 int i; 559 for(i = 0; i < count; i++) 560 free_node(&key_node->child[i]); 561 free_node(key_node); 562 return TRUE; 563 } 564 else if((vi = find_inode(key_node, name)) >= 0) 565 { 566 //debug("remove value:%s", key_node->child[vi].name); 567 free_node(&key_node->child[vi]); 568 return TRUE; 569 } 570 } 571 } 572 return FALSE; 573 } 574 static int save_cfg() 575 { 576 const char* file_name = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT; 577 const char* file_name_new = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_NEW; 578 const char* file_name_old = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_OLD; 579 int ret = FALSE; 580 if(access(file_name_old, F_OK) == 0) 581 unlink(file_name_old); 582 if(access(file_name_new, F_OK) == 0) 583 unlink(file_name_new); 584 if(btif_config_save_file(file_name_new)) 585 { 586 cached_change = 0; 587 chown(file_name_new, -1, AID_NET_BT_STACK); 588 chmod(file_name_new, 0660); 589 rename(file_name, file_name_old); 590 rename(file_name_new, file_name); 591 ret = TRUE; 592 } 593 else BTIF_TRACE_ERROR0("btif_config_save_file failed"); 594 return ret; 595 } 596 597 static int load_bluez_cfg() 598 { 599 char adapter_path[256]; 600 if(load_bluez_adapter_info(adapter_path, sizeof(adapter_path))) 601 { 602 if(load_bluez_linkkeys(adapter_path)) 603 return TRUE; 604 } 605 return FALSE; 606 } 607 static void remove_bluez_cfg() 608 { 609 rename(BLUEZ_PATH, BLUEZ_PATH_BAK); 610 } 611 static void clean_newline_char() 612 { 613 char kname[128], vname[128]; 614 short kpos = 0; 615 int kname_size, vname_size; 616 vname[0] = 0; 617 vname_size = sizeof(vname); 618 //BTIF_TRACE_DEBUG0("removing newline at the end of the adapter and device name"); 619 if(btif_config_get_str("Local", "Adapter", "Name", vname, &vname_size) && 620 vname_size > 2) 621 { 622 if(vname[vname_size - 2] == '\n') 623 { 624 BTIF_TRACE_DEBUG1("remove newline at the end of the adapter name:%s", vname); 625 vname[vname_size - 2] = 0; 626 btif_config_set_str("Local", "Adapter", "Name", vname); 627 } 628 } 629 do 630 { 631 kname_size = sizeof(kname); 632 kname[0] = 0; 633 kpos = btif_config_next_key(kpos, "Remote", kname, &kname_size); 634 //BTIF_TRACE_DEBUG2("Remote device:%s, size:%d", kname, kname_size); 635 vname_size = sizeof(vname); 636 vname[0] = 0; 637 if(btif_config_get_str("Remote", kname, "Name", vname, &vname_size) && 638 vname_size > 2) 639 { 640 BTIF_TRACE_DEBUG1("remote device name:%s", vname); 641 if(vname[vname_size - 2] == '\n') 642 { 643 BTIF_TRACE_DEBUG1("remove newline at the end of the device name:%s", vname); 644 vname[vname_size - 2] = 0; 645 btif_config_set_str("Remote", kname, "Name", vname); 646 } 647 } 648 } while(kpos != -1); 649 } 650 static void load_cfg() 651 { 652 const char* file_name = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT; 653 const char* file_name_new = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_NEW; 654 const char* file_name_old = CFG_PATH CFG_FILE_NAME CFG_FILE_EXT_OLD; 655 if(!btif_config_load_file(file_name)) 656 { 657 unlink(file_name); 658 if(!btif_config_load_file(file_name_old)) 659 { 660 unlink(file_name_old); 661 if(load_bluez_cfg() && save_cfg()) 662 remove_bluez_cfg(); 663 } 664 } 665 int bluez_migration_done = 0; 666 btif_config_get_int("Local", "Adapter", "BluezMigrationDone", &bluez_migration_done); 667 if(!bluez_migration_done) 668 { 669 //clean the new line char at the end of the device name. Caused by bluez config import bug 670 clean_newline_char(); 671 btif_config_set_int("Local", "Adapter", "BluezMigrationDone", 1); 672 btif_config_save(); 673 } 674 } 675 static void cfg_cmd_callback(int cmd_fd, int type, int size, uint32_t user_id) 676 { 677 //BTIF_TRACE_DEBUG2("cmd type:%d, size:%d", type, size); 678 switch(type) 679 { 680 case CFG_CMD_SAVE: 681 lock_slot(&slot_lock); 682 save_cfg(); 683 unlock_slot(&slot_lock); 684 break; 685 } 686 } 687 #ifdef UNIT_TEST 688 static void cfg_test_load() 689 { 690 load_cfg(); 691 char kname[128], vname[128]; 692 short kpos, vpos; 693 int kname_size, vname_size; 694 BTIF_TRACE_DEBUG0("list all remote devices values:"); 695 kname_size = sizeof(kname); 696 kname[0] = 0; 697 kpos = 0; 698 do 699 { 700 kpos = btif_config_next_key(kpos, "Remote Devices", kname, &kname_size); 701 BTIF_TRACE_DEBUG2("Remote devices:%s, size:%d", kname, kname_size); 702 vpos = 0; 703 vname[0] = 0; 704 vname_size = sizeof(vname); 705 while((vpos = btif_config_next_value(vpos, "Remote Devices", kname, vname, &vname_size)) != -1) 706 { 707 char v[128] = {0}; 708 int vtype = BTIF_CFG_TYPE_STR; 709 int vsize = sizeof(v); 710 int ret = btif_config_get("Remote Devices", kname, vname, v, &vsize, &vtype); 711 BTIF_TRACE_DEBUG6("btif_config_get return:%d, Remote devices:%s, value name:%s, value:%s, value size:%d, type:0x%x", 712 ret, kname, vname, v, vsize, vtype); 713 714 vname[0] = 0; 715 vname_size = sizeof(vname); 716 } 717 kname[0] = 0; 718 kname_size = sizeof(kname); 719 } while(kpos != -1); 720 } 721 static void cfg_test_write() 722 { 723 int i; 724 725 char key[128]; 726 const char* section; 727 char link_key[64]; 728 for(i = 0; i < (int)sizeof(link_key); i++) 729 link_key[i] = i; 730 for(i = 0; i < 100; i++) 731 { 732 sprintf(key, "00:22:5F:97:56:%02d", i); 733 link_key[0] = i; 734 section = "Remote Devices"; 735 btif_config_set_str(section, key, "class", "smart phone"); 736 btif_config_set(section, key, "link keys", link_key, sizeof(link_key), BTIF_CFG_TYPE_BIN); 737 btif_config_set_int(section, key, "connect time out", i); 738 } 739 btif_config_save(); 740 } 741 static void cfg_test_read() 742 { 743 //debug("in"); 744 char class[128] = {0}; 745 char link_key[128] = {0}; 746 int size, type; 747 char key[128]; 748 const char* section; 749 int ret, i; 750 for(i = 0; i < 100; i++) 751 { 752 sprintf(key, "00:22:5F:97:56:%02d", i); 753 section = "Remote Devices"; 754 size = sizeof(class); 755 ret = btif_config_get_str(section, key, "class", class, &size); 756 BTIF_TRACE_DEBUG3("btif_config_get_str return:%d, Remote devices:%s, class:%s", ret, key, class); 757 758 size = sizeof(link_key); 759 type = BTIF_CFG_TYPE_BIN; 760 ret = btif_config_get(section, key, "link keys", link_key, &size, &type); 761 //debug("btif_config_get return:%d, Remote devices:%s, link key:%x, %x", 762 // ret, key, *(int *)link_key, *((int *)link_key + 1)); 763 764 int timeout; 765 ret = btif_config_get_int(section, key, "connect time out", &timeout); 766 //debug("btif_config_get_int return:%d, Remote devices:%s, connect time out:%d", ret, key, timeout); 767 } 768 769 // debug("testing btif_config_remove"); 770 size = sizeof(class); 771 type = BTIF_CFG_TYPE_STR; 772 btif_config_set("Remote Devices", "00:22:5F:97:56:04", "Class Delete", class, strlen(class) + 1, BTIF_CFG_TYPE_STR); 773 774 btif_config_get("Remote Devices", "00:22:5F:97:56:04", "Class Delete", class, &size, &type); 775 // debug("Remote devices, 00:22:5F:97:56:04 Class Delete:%s", class); 776 btif_config_remove("Remote Devices", "00:22:5F:97:56:04", "Class Delete"); 777 778 size = sizeof(class); 779 type = BTIF_CFG_TYPE_STR; 780 ret = btif_config_get("Remote Devices", "00:22:5F:97:56:04", "Class Delete", class, &size, &type); 781 // debug("after removed, btif_config_get ret:%d, Remote devices, 00:22:5F:97:56:04 Class Delete:%s", ret, class); 782 // debug("out"); 783 } 784 #endif 785