1 /******************************************************************************
3 * Copyright (C) 2009-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * Filename: bte_conf.c
23 * Description: Contains functions to conduct run-time module configuration
24 * based on entries present in the .conf file
26 ******************************************************************************/
28 #define LOG_TAG "bte_conf"
30 #include <utils/Log.h>
36 #include "bt_target.h"
40 /******************************************************************************
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);
53 BD_NAME local_device_default_name = BTM_DEF_LOCAL_NAME;
54 DEV_CLASS local_device_default_class = {0x40, 0x02, 0x0C};
56 /******************************************************************************
57 ** Local type definitions
58 ******************************************************************************/
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__)
64 #define CONF_KEY_LEN 32
65 #define CONF_VALUE_LEN 96
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
73 typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value);
76 const char *conf_entry;
77 conf_action_t *p_action;
81 char key[CONF_KEY_LEN];
82 char value[CONF_VALUE_LEN];
88 CONF_DID_PRIMARY_RECORD,
90 CONF_DID_VENDOR_ID_SOURCE,
93 CONF_DID_CLIENT_EXECUTABLE_URL,
94 CONF_DID_SERVICE_DESCRIPTION,
95 CONF_DID_DOCUMENTATION_URL,
98 typedef UINT8 tCONF_DID;
99 /******************************************************************************
101 ******************************************************************************/
104 * Current supported entries and corresponding action functions
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}
116 static tKEY_VALUE_PAIRS did_conf_pairs[CONF_DID_MAX] = {
118 { "recordNumber", "" },
119 { "primaryRecord", "" },
121 { "vendorIdSource", "" },
124 { "clientExecutableURL", "" },
125 { "serviceDescription", "" },
126 { "documentationURL", "" },
128 /*****************************************************************************
130 *****************************************************************************/
132 int device_name_cfg(char *p_conf_name, char *p_conf_value)
135 strcpy((char *)local_device_default_name, p_conf_value);
139 int device_class_cfg(char *p_conf_name, char *p_conf_value)
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;
158 int logging_cfg_onoff(char *p_conf_name, char *p_conf_value)
161 if (strcmp(p_conf_value, "true") == 0)
162 hci_logging_enabled = TRUE;
164 hci_logging_enabled = FALSE;
168 int logging_set_filepath(char *p_conf_name, char *p_conf_value)
171 strcpy(hci_logfile, p_conf_value);
175 int trace_cfg_onoff(char *p_conf_name, char *p_conf_value)
178 trace_conf_enabled = (strcmp(p_conf_value, "true") == 0) ? TRUE : FALSE;
182 /*****************************************************************************
183 ** CONF INTERFACE FUNCTIONS
184 *****************************************************************************/
186 /*******************************************************************************
188 ** Function bte_load_conf
190 ** Description Read conf entry from p_path file one by one and call
191 ** the corresponding config function
195 *******************************************************************************/
196 void bte_load_conf(const char *p_path)
201 conf_entry_t *p_entry;
202 char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
203 BOOLEAN name_matched;
205 ALOGI("Attempt to load stack conf from %s", p_path);
207 if ((p_file = fopen(p_path, "r")) != NULL)
209 /* read line by line */
210 while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
212 if (line[0] == CONF_COMMENT)
215 p_name = strtok(line, CONF_DELIMITERS);
222 p_value = strtok(NULL, CONF_VALUES_DELIMITERS);
226 ALOGW("bte_load_conf: missing value for name: %s", p_name);
230 name_matched = FALSE;
231 p_entry = (conf_entry_t *)conf_table;
233 while (p_entry->conf_entry != NULL)
235 if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0)
238 if (p_entry->p_action != NULL)
239 p_entry->p_action(p_name, p_value);
246 if ((name_matched == FALSE) && (trace_conf_enabled == TRUE))
248 /* Check if this is a TRC config item */
249 bte_trace_conf(p_name, p_value);
257 ALOGI( "bte_load_conf file >%s< not found", p_path);
261 /*******************************************************************************
263 ** Function bte_parse_did_conf
265 ** Description Read conf entry from p_path file one by one and get
266 ** the corresponding config value
268 ** Returns TRUE if success, else FALSE
270 *******************************************************************************/
271 static BOOLEAN bte_parse_did_conf (const char *p_path, UINT32 num,
272 tKEY_VALUE_PAIRS *conf_pairs, UINT32 conf_pairs_num)
274 UINT32 i, param_num=0, count=0, start_count=0, end_count=0, conf_num=0;
275 BOOLEAN key=TRUE, conf_found=FALSE;
279 char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
281 ALOGI("Attempt to load did conf from %s", p_path);
283 if ((p_file = fopen(p_path, "r")) != NULL)
285 /* read line by line */
286 while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
289 if (line[0] == CONF_COMMENT)
292 if (conf_found && (conf_num == num) && (*line == '[')) {
298 p = strtok(line, CONF_DELIMITERS);
300 if (conf_num <= num) {
302 if (!strcmp(p, conf_pairs[0].key)) {
303 if (++conf_num == num) {
306 strncpy(conf_pairs[0].value, "1", CONF_VALUE_LEN);
309 if (conf_num == num) {
310 for (i=1; i<conf_pairs_num; i++) {
311 if (!strcmp(p, conf_pairs[i].key)) {
316 if (i == conf_pairs_num) {
317 error("Attribute %s does not belong to %s configuration",
318 p, conf_pairs[0].key);
326 if ((conf_num == num) && param_num) {
327 strncpy(conf_pairs[param_num].value, p, CONF_VALUE_LEN-1);
333 p = strtok(NULL, CONF_DELIMITERS);
341 ALOGI( "bte_parse_did_conf file >%s< not found", p_path);
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);
353 error("%s configuration not found in file %s", conf_pairs[0].key, p_path);
357 /*******************************************************************************
359 ** Function bte_load_did_conf
361 ** Description Set local Device ID records, reading from configuration files
365 *******************************************************************************/
367 void bte_load_did_conf (const char *p_path)
370 UINT32 rec_num, i, j;
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;
377 if (bte_parse_did_conf(p_path, i, did_conf_pairs, CONF_DID_MAX)) {
378 memset(&rec, 0, sizeof(rec));
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);
383 debug("[%d] Unknown %s", (unsigned int)i, did_conf_pairs[CONF_DID_RECORD_NUM].key);
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);
390 rec.vendor = LMP_COMPID_BROADCOM;
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);
396 rec.vendor_id_source = DI_VENDOR_ID_SOURCE_BTSIG;
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)) {
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);
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);
415 strncpy(rec.client_executable_url,
416 did_conf_pairs[CONF_DID_CLIENT_EXECUTABLE_URL].value,
418 strncpy(rec.service_description,
419 did_conf_pairs[CONF_DID_SERVICE_DESCRIPTION].value,
421 strncpy(rec.documentation_url,
422 did_conf_pairs[CONF_DID_DOCUMENTATION_URL].value,
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]);
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;
433 rec.primary_record = FALSE;
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);
442 if (*rec.service_description) {
443 info(" service_description=%s", rec.service_description);
445 if (*rec.documentation_url) {
446 info(" documentation_url=%s", rec.documentation_url);
449 if (BTA_DmSetLocalDiRecord(&rec, &rec_num) != BTA_SUCCESS) {
450 error("SetLocalDiInfo failed for #%u!", (unsigned int)i);