• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
dump_node(const char * title,const cfg_node * p)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 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
btif_config_init()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 }
btif_config_get_int(const char * section,const char * key,const char * name,int * value)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 }
btif_config_set_int(const char * section,const char * key,const char * name,int value)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 }
btif_config_get_str(const char * section,const char * key,const char * name,char * value,int * size)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 }
btif_config_set_str(const char * section,const char * key,const char * name,const char * value)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 }
btif_config_exist(const char * section,const char * key,const char * name)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 }
btif_config_get(const char * section,const char * key,const char * name,char * value,int * bytes,int * type)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 }
btif_config_set(const char * section,const char * key,const char * name,const char * value,int bytes,int type)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 }
btif_config_remove(const char * section,const char * key,const char * name)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;
btif_config_next_key(short pos,const char * section,char * name,int * bytes)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 }
btif_config_next_value(short pos,const char * section,const char * key,char * name,int * bytes)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 = &section_node->child[ki];
279             next = find_next_node(key_node, pos, name, bytes);
280         }
281     }
282     unlock_slot(&slot_lock);
283     return next;
284 }
btif_config_enum(btif_config_enum_callback cb,void * user_data)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 = &section_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 }
btif_config_save()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 }
btif_config_flush()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 /////////////////////////////////////////////////////////////////////////////////////////////
alloc_node(cfg_node * p,short grow)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 }
free_node(cfg_node * p)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 }
find_inode(const cfg_node * p,const char * name)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 }
find_free_node(cfg_node * p)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 }
find_add_node(cfg_node * p,const char * name)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 }
set_node(const char * section,const char * key,const char * name,const char * value,short bytes,short type)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 }
find_node(const char * section,const char * key,const char * name)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 = &section_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 }
find_next_node(const cfg_node * p,short start,char * name,int * bytes)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 }
remove_node(const char * section,const char * key,const char * name)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 = &section_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 }
save_cfg()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 
load_bluez_cfg()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 }
remove_bluez_cfg()607 static void remove_bluez_cfg()
608 {
609     rename(BLUEZ_PATH, BLUEZ_PATH_BAK);
610 }
clean_newline_char()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 }
load_cfg()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 }
cfg_cmd_callback(int cmd_fd,int type,int size,uint32_t user_id)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
cfg_test_load()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 }
cfg_test_write()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 }
cfg_test_read()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