OSDN Git Service

am 65aec3a3: am 6d429d9d: (-s ours) am 3efb9e2e: DO NOT MERGE Change pairing_cb to...
[android-x86/system-bt.git] / main / bte_conf.c
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:      bte_conf.c
22  *
23  *  Description:   Contains functions to conduct run-time module configuration
24  *                 based on entries present in the .conf file
25  *
26  ******************************************************************************/
27
28 #define LOG_TAG "bte_conf"
29
30 #include <utils/Log.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35
36 #include "bt_target.h"
37 #include "bta_api.h"
38 #include "bt_utils.h"
39
40 /******************************************************************************
41 **  Externs
42 ******************************************************************************/
43 extern BOOLEAN hci_logging_enabled;
44 extern char hci_logfile[256];
45 extern BOOLEAN trace_conf_enabled;
46 void bte_trace_conf(char *p_name, char *p_conf_value);
47 int device_name_cfg(char *p_conf_name, char *p_conf_value);
48 int device_class_cfg(char *p_conf_name, char *p_conf_value);
49 int logging_cfg_onoff(char *p_conf_name, char *p_conf_value);
50 int logging_set_filepath(char *p_conf_name, char *p_conf_value);
51 int trace_cfg_onoff(char *p_conf_name, char *p_conf_value);
52
53 BD_NAME local_device_default_name = BTM_DEF_LOCAL_NAME;
54 DEV_CLASS local_device_default_class = {0x40, 0x02, 0x0C};
55
56 /******************************************************************************
57 **  Local type definitions
58 ******************************************************************************/
59 #define CONF_DBG          0
60 #define info(format, ...) ALOGI (format, ## __VA_ARGS__)
61 #define debug(format, ...) if (CONF_DBG) ALOGD (format, ## __VA_ARGS__)
62 #define error(format, ...) ALOGE (format, ## __VA_ARGS__)
63
64 #define CONF_KEY_LEN   32
65 #define CONF_VALUE_LEN 96
66
67 #define CONF_COMMENT '#'
68 #define CONF_DELIMITERS " =\n\r\t"
69 #define CONF_VALUES_DELIMITERS "\"=\n\r\t"
70 #define CONF_COD_DELIMITERS " {,}\t"
71 #define CONF_MAX_LINE_LEN 255
72
73 typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value);
74
75 typedef struct {
76     const char *conf_entry;
77     conf_action_t *p_action;
78 } conf_entry_t;
79
80 typedef struct {
81     char key[CONF_KEY_LEN];
82     char value[CONF_VALUE_LEN];
83 } tKEY_VALUE_PAIRS;
84
85 enum {
86     CONF_DID,
87     CONF_DID_RECORD_NUM,
88     CONF_DID_PRIMARY_RECORD,
89     CONF_DID_VENDOR_ID,
90     CONF_DID_VENDOR_ID_SOURCE,
91     CONF_DID_PRODUCT_ID,
92     CONF_DID_VERSION,
93     CONF_DID_CLIENT_EXECUTABLE_URL,
94     CONF_DID_SERVICE_DESCRIPTION,
95     CONF_DID_DOCUMENTATION_URL,
96     CONF_DID_MAX
97 };
98 typedef UINT8 tCONF_DID;
99 /******************************************************************************
100 **  Static variables
101 ******************************************************************************/
102
103 /*
104  * Current supported entries and corresponding action functions
105  */
106 /* TODO: Name and Class are duplicated with NVRAM adapter_info. Need to be sorted out */
107 static const conf_entry_t conf_table[] = {
108     /*{"Name", device_name_cfg},
109     {"Class", device_class_cfg},*/
110     {"BtSnoopLogOutput", logging_cfg_onoff},
111     {"BtSnoopFileName", logging_set_filepath},
112     {"TraceConf", trace_cfg_onoff},
113     {(const char *) NULL, NULL}
114 };
115
116 static tKEY_VALUE_PAIRS did_conf_pairs[CONF_DID_MAX] = {
117     { "[DID]",               "" },
118     { "recordNumber",        "" },
119     { "primaryRecord",       "" },
120     { "vendorId",            "" },
121     { "vendorIdSource",      "" },
122     { "productId",           "" },
123     { "version",             "" },
124     { "clientExecutableURL", "" },
125     { "serviceDescription",  "" },
126     { "documentationURL",    "" },
127 };
128 /*****************************************************************************
129 **   FUNCTIONS
130 *****************************************************************************/
131
132 int device_name_cfg(char *p_conf_name, char *p_conf_value)
133 {
134     UNUSED(p_conf_name);
135     strcpy((char *)local_device_default_name, p_conf_value);
136     return 0;
137 }
138
139 int device_class_cfg(char *p_conf_name, char *p_conf_value)
140 {
141     char *p_token;
142     unsigned int x;
143     UNUSED(p_conf_name);
144
145     p_token = strtok(p_conf_value, CONF_COD_DELIMITERS);
146     sscanf(p_token, "%x", &x);
147     local_device_default_class[0] = (UINT8) x;
148     p_token = strtok(NULL, CONF_COD_DELIMITERS);
149     sscanf(p_token, "%x", &x);
150     local_device_default_class[1] = (UINT8) x;
151     p_token = strtok(NULL, CONF_COD_DELIMITERS);
152     sscanf(p_token, "%x", &x);
153     local_device_default_class[2] = (UINT8) x;
154
155     return 0;
156 }
157
158 int logging_cfg_onoff(char *p_conf_name, char *p_conf_value)
159 {
160     UNUSED(p_conf_name);
161     if (strcmp(p_conf_value, "true") == 0)
162         hci_logging_enabled = TRUE;
163     else
164         hci_logging_enabled = FALSE;
165     return 0;
166 }
167
168 int logging_set_filepath(char *p_conf_name, char *p_conf_value)
169 {
170     UNUSED(p_conf_name);
171     strcpy(hci_logfile, p_conf_value);
172     return 0;
173 }
174
175 int trace_cfg_onoff(char *p_conf_name, char *p_conf_value)
176 {
177     UNUSED(p_conf_name);
178     trace_conf_enabled = (strcmp(p_conf_value, "true") == 0) ? TRUE : FALSE;
179     return 0;
180 }
181
182 /*****************************************************************************
183 **   CONF INTERFACE FUNCTIONS
184 *****************************************************************************/
185
186 /*******************************************************************************
187 **
188 ** Function        bte_load_conf
189 **
190 ** Description     Read conf entry from p_path file one by one and call
191 **                 the corresponding config function
192 **
193 ** Returns         None
194 **
195 *******************************************************************************/
196 void bte_load_conf(const char *p_path)
197 {
198     FILE    *p_file;
199     char    *p_name;
200     char    *p_value;
201     conf_entry_t    *p_entry;
202     char    line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
203     BOOLEAN name_matched;
204
205     ALOGI("Attempt to load stack conf from %s", p_path);
206
207     if ((p_file = fopen(p_path, "r")) != NULL)
208     {
209         /* read line by line */
210         while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
211         {
212             if (line[0] == CONF_COMMENT)
213                 continue;
214
215             p_name = strtok(line, CONF_DELIMITERS);
216
217             if (NULL == p_name)
218             {
219                 continue;
220             }
221
222             p_value = strtok(NULL, CONF_VALUES_DELIMITERS);
223
224             if (NULL == p_value)
225             {
226                 ALOGW("bte_load_conf: missing value for name: %s", p_name);
227                 continue;
228             }
229
230             name_matched = FALSE;
231             p_entry = (conf_entry_t *)conf_table;
232
233             while (p_entry->conf_entry != NULL)
234             {
235                 if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0)
236                 {
237                     name_matched = TRUE;
238                     if (p_entry->p_action != NULL)
239                         p_entry->p_action(p_name, p_value);
240                     break;
241                 }
242
243                 p_entry++;
244             }
245
246             if ((name_matched == FALSE) && (trace_conf_enabled == TRUE))
247             {
248                 /* Check if this is a TRC config item */
249                 bte_trace_conf(p_name, p_value);
250             }
251         }
252
253         fclose(p_file);
254     }
255     else
256     {
257         ALOGI( "bte_load_conf file >%s< not found", p_path);
258     }
259 }
260
261 /*******************************************************************************
262 **
263 ** Function        bte_parse_did_conf
264 **
265 ** Description     Read conf entry from p_path file one by one and get
266 **                 the corresponding config value
267 **
268 ** Returns         TRUE if success, else FALSE
269 **
270 *******************************************************************************/
271 static BOOLEAN bte_parse_did_conf (const char *p_path, UINT32 num,
272     tKEY_VALUE_PAIRS *conf_pairs, UINT32 conf_pairs_num)
273 {
274     UINT32 i, param_num=0, count=0, start_count=0, end_count=0, conf_num=0;
275     BOOLEAN key=TRUE, conf_found=FALSE;
276
277     FILE    *p_file;
278     char    *p;
279     char    line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
280
281     ALOGI("Attempt to load did conf from %s", p_path);
282
283     if ((p_file = fopen(p_path, "r")) != NULL)
284     {
285         /* read line by line */
286         while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
287         {
288             count++;
289             if (line[0] == CONF_COMMENT)
290                 continue;
291
292             if (conf_found && (conf_num == num) && (*line == '[')) {
293                 conf_found = FALSE;
294                 end_count = count-1;
295                 break;
296             }
297
298             p = strtok(line, CONF_DELIMITERS);
299             while (p != NULL) {
300                 if (conf_num <= num) {
301                     if (key) {
302                         if (!strcmp(p, conf_pairs[0].key)) {
303                             if (++conf_num == num) {
304                                 conf_found = TRUE;
305                                 start_count = count;
306                                 strncpy(conf_pairs[0].value, "1", CONF_VALUE_LEN);
307                             }
308                         } else {
309                             if (conf_num == num) {
310                                 for (i=1; i<conf_pairs_num; i++) {
311                                     if (!strcmp(p, conf_pairs[i].key)) {
312                                         param_num = i;
313                                         break;
314                                     }
315                                 }
316                                 if (i == conf_pairs_num) {
317                                     error("Attribute %s does not belong to %s configuration",
318                                         p, conf_pairs[0].key);
319                                     fclose(p_file);
320                                     return FALSE;
321                                 }
322                             }
323                             key = FALSE;
324                         }
325                     } else {
326                         if ((conf_num == num) && param_num) {
327                             strncpy(conf_pairs[param_num].value, p, CONF_VALUE_LEN-1);
328                             param_num = 0;
329                         }
330                         key = TRUE;
331                     }
332                 }
333                 p = strtok(NULL, CONF_DELIMITERS);
334             }
335         }
336
337         fclose(p_file);
338    }
339    else
340    {
341         ALOGI( "bte_parse_did_conf file >%s< not found", p_path);
342    }
343    if (!end_count)
344        end_count = count;
345
346    if (start_count) {
347         debug("Read %s configuration #%u from lines %u to %u in file %s",
348             conf_pairs[0].key, (unsigned int)num, (unsigned int)start_count,
349             (unsigned int)end_count, p_path);
350         return TRUE;
351    }
352
353    error("%s configuration not found in file %s", conf_pairs[0].key, p_path);
354         return FALSE;
355 }
356
357 /*******************************************************************************
358 **
359 ** Function        bte_load_did_conf
360 **
361 ** Description     Set local Device ID records, reading from configuration files
362 **
363 ** Returns         None
364 **
365 *******************************************************************************/
366
367 void bte_load_did_conf (const char *p_path)
368 {
369     tBTA_DI_RECORD rec;
370     UINT32 rec_num, i, j;
371
372     for (i=1; i<=BTA_DI_NUM_MAX; i++) {
373         for (j=0; j<CONF_DID_MAX; j++) {
374             *did_conf_pairs[j].value = 0;
375         }
376
377         if (bte_parse_did_conf(p_path, i, did_conf_pairs, CONF_DID_MAX)) {
378             memset(&rec, 0, sizeof(rec));
379
380             if (*did_conf_pairs[CONF_DID_RECORD_NUM].value) {
381                 rec_num = (UINT32)(strtoul(did_conf_pairs[CONF_DID_RECORD_NUM].value, NULL, 0)-1);
382             } else {
383                 debug("[%d] Unknown %s", (unsigned int)i, did_conf_pairs[CONF_DID_RECORD_NUM].key);
384                 continue;
385             }
386
387             if (*did_conf_pairs[CONF_DID_VENDOR_ID].value) {
388                 rec.vendor = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID].value, NULL, 0);
389             } else {
390                 rec.vendor = LMP_COMPID_BROADCOM;
391             }
392
393             if (*did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value) {
394                 rec.vendor_id_source = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value, NULL, 0);
395             } else {
396                 rec.vendor_id_source = DI_VENDOR_ID_SOURCE_BTSIG;
397             }
398
399             if ((*did_conf_pairs[CONF_DID].value == 0) ||
400                 (rec_num >= BTA_DI_NUM_MAX) ||
401                 (!((rec.vendor_id_source >= DI_VENDOR_ID_SOURCE_BTSIG) &&
402                    (rec.vendor_id_source <= DI_VENDOR_ID_SOURCE_USBIF))) ||
403                 (rec.vendor == DI_VENDOR_ID_DEFAULT)) {
404
405                 error("DID record #%u not set", (unsigned int)i);
406                 for (j=0; j<CONF_DID_MAX; j++) {
407                     error("%s:%s", did_conf_pairs[j].key, did_conf_pairs[j].value);
408                 }
409                 continue;
410             }
411
412             rec.product = (UINT16)strtoul(did_conf_pairs[CONF_DID_PRODUCT_ID].value, NULL, 0);
413             rec.version = (UINT16)strtoul(did_conf_pairs[CONF_DID_VERSION].value, NULL, 0);
414
415             strncpy(rec.client_executable_url,
416                 did_conf_pairs[CONF_DID_CLIENT_EXECUTABLE_URL].value,
417                 SDP_MAX_ATTR_LEN);
418             strncpy(rec.service_description,
419                 did_conf_pairs[CONF_DID_SERVICE_DESCRIPTION].value,
420                 SDP_MAX_ATTR_LEN);
421             strncpy(rec.documentation_url,
422                 did_conf_pairs[CONF_DID_DOCUMENTATION_URL].value,
423                 SDP_MAX_ATTR_LEN);
424
425             for (j=0; j<strlen(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value); j++) {
426                 did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j] =
427                     tolower(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j]);
428             }
429             if ((!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "true")) ||
430                 (!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "1"))) {
431                 rec.primary_record = TRUE;
432             } else {
433                 rec.primary_record = FALSE;
434             }
435
436             info("[%u] primary_record=%d vendor_id=0x%04X vendor_id_source=0x%04X product_id=0x%04X version=0x%04X",
437                 (unsigned int)rec_num+1, rec.primary_record, rec.vendor,
438                 rec.vendor_id_source, rec.product, rec.version);
439             if (*rec.client_executable_url) {
440                 info(" client_executable_url=%s", rec.client_executable_url);
441             }
442             if (*rec.service_description) {
443                 info(" service_description=%s", rec.service_description);
444             }
445             if (*rec.documentation_url) {
446                 info(" documentation_url=%s", rec.documentation_url);
447             }
448
449             if (BTA_DmSetLocalDiRecord(&rec, &rec_num) != BTA_SUCCESS) {
450                 error("SetLocalDiInfo failed for #%u!", (unsigned int)i);
451             }
452         }
453     }
454 }
455