diff options
Diffstat (limited to 'main/bte_conf.c')
-rw-r--r-- | main/bte_conf.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/main/bte_conf.c b/main/bte_conf.c new file mode 100644 index 0000000..e001d59 --- /dev/null +++ b/main/bte_conf.c @@ -0,0 +1,449 @@ +/****************************************************************************** + * + * Copyright (C) 2009-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Filename: bte_conf.c + * + * Description: Contains functions to conduct run-time module configuration + * based on entries present in the .conf file + * + ******************************************************************************/ + +#define LOG_TAG "bte_conf" + +#include <utils/Log.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "bt_target.h" +#include "bta_api.h" + +/****************************************************************************** +** Externs +******************************************************************************/ +extern BOOLEAN hci_logging_enabled; +extern char hci_logfile[256]; +extern BOOLEAN trace_conf_enabled; +void bte_trace_conf(char *p_name, char *p_conf_value); +int device_name_cfg(char *p_conf_name, char *p_conf_value); +int device_class_cfg(char *p_conf_name, char *p_conf_value); +int logging_cfg_onoff(char *p_conf_name, char *p_conf_value); +int logging_set_filepath(char *p_conf_name, char *p_conf_value); +int trace_cfg_onoff(char *p_conf_name, char *p_conf_value); + +BD_NAME local_device_default_name = BTM_DEF_LOCAL_NAME; +DEV_CLASS local_device_default_class = {0x40, 0x02, 0x0C}; + +/****************************************************************************** +** Local type definitions +******************************************************************************/ +#define CONF_DBG 0 +#define info(format, ...) ALOGI (format, ## __VA_ARGS__) +#define debug(format, ...) if (CONF_DBG) ALOGD (format, ## __VA_ARGS__) +#define error(format, ...) ALOGE (format, ## __VA_ARGS__) + +#define CONF_KEY_LEN 32 +#define CONF_VALUE_LEN 96 + +#define CONF_COMMENT '#' +#define CONF_DELIMITERS " =\n\r\t" +#define CONF_VALUES_DELIMITERS "\"=\n\r\t" +#define CONF_COD_DELIMITERS " {,}\t" +#define CONF_MAX_LINE_LEN 255 + +typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value); + +typedef struct { + const char *conf_entry; + conf_action_t *p_action; +} conf_entry_t; + +typedef struct { + char key[CONF_KEY_LEN]; + char value[CONF_VALUE_LEN]; +} tKEY_VALUE_PAIRS; + +enum { + CONF_DID, + CONF_DID_RECORD_NUM, + CONF_DID_PRIMARY_RECORD, + CONF_DID_VENDOR_ID, + CONF_DID_VENDOR_ID_SOURCE, + CONF_DID_PRODUCT_ID, + CONF_DID_VERSION, + CONF_DID_CLIENT_EXECUTABLE_URL, + CONF_DID_SERVICE_DESCRIPTION, + CONF_DID_DOCUMENTATION_URL, + CONF_DID_MAX +}; +typedef UINT8 tCONF_DID; +/****************************************************************************** +** Static variables +******************************************************************************/ + +/* + * Current supported entries and corresponding action functions + */ +/* TODO: Name and Class are duplicated with NVRAM adapter_info. Need to be sorted out */ +static const conf_entry_t conf_table[] = { + /*{"Name", device_name_cfg}, + {"Class", device_class_cfg},*/ + {"BtSnoopLogOutput", logging_cfg_onoff}, + {"BtSnoopFileName", logging_set_filepath}, + {"TraceConf", trace_cfg_onoff}, + {(const char *) NULL, NULL} +}; + +static tKEY_VALUE_PAIRS did_conf_pairs[CONF_DID_MAX] = { + { "[DID]", "" }, + { "recordNumber", "" }, + { "primaryRecord", "" }, + { "vendorId", "" }, + { "vendorIdSource", "" }, + { "productId", "" }, + { "version", "" }, + { "clientExecutableURL", "" }, + { "serviceDescription", "" }, + { "documentationURL", "" }, +}; +/***************************************************************************** +** FUNCTIONS +*****************************************************************************/ + +int device_name_cfg(char *p_conf_name, char *p_conf_value) +{ + strcpy((char *)local_device_default_name, p_conf_value); + return 0; +} + +int device_class_cfg(char *p_conf_name, char *p_conf_value) +{ + char *p_token; + unsigned int x; + + p_token = strtok(p_conf_value, CONF_COD_DELIMITERS); + sscanf(p_token, "%x", &x); + local_device_default_class[0] = (UINT8) x; + p_token = strtok(NULL, CONF_COD_DELIMITERS); + sscanf(p_token, "%x", &x); + local_device_default_class[1] = (UINT8) x; + p_token = strtok(NULL, CONF_COD_DELIMITERS); + sscanf(p_token, "%x", &x); + local_device_default_class[2] = (UINT8) x; + + return 0; +} + +int logging_cfg_onoff(char *p_conf_name, char *p_conf_value) +{ + if (strcmp(p_conf_value, "true") == 0) + hci_logging_enabled = TRUE; + else + hci_logging_enabled = FALSE; + return 0; +} + +int logging_set_filepath(char *p_conf_name, char *p_conf_value) +{ + strcpy(hci_logfile, p_conf_value); + return 0; +} + +int trace_cfg_onoff(char *p_conf_name, char *p_conf_value) +{ + trace_conf_enabled = (strcmp(p_conf_value, "true") == 0) ? TRUE : FALSE; + return 0; +} + +/***************************************************************************** +** CONF INTERFACE FUNCTIONS +*****************************************************************************/ + +/******************************************************************************* +** +** Function bte_load_conf +** +** Description Read conf entry from p_path file one by one and call +** the corresponding config function +** +** Returns None +** +*******************************************************************************/ +void bte_load_conf(const char *p_path) +{ + FILE *p_file; + char *p_name; + char *p_value; + conf_entry_t *p_entry; + char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */ + BOOLEAN name_matched; + + ALOGI("Attempt to load stack conf from %s", p_path); + + if ((p_file = fopen(p_path, "r")) != NULL) + { + /* read line by line */ + while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL) + { + if (line[0] == CONF_COMMENT) + continue; + + p_name = strtok(line, CONF_DELIMITERS); + + if (NULL == p_name) + { + continue; + } + + p_value = strtok(NULL, CONF_VALUES_DELIMITERS); + + if (NULL == p_value) + { + ALOGW("bte_load_conf: missing value for name: %s", p_name); + continue; + } + + name_matched = FALSE; + p_entry = (conf_entry_t *)conf_table; + + while (p_entry->conf_entry != NULL) + { + if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0) + { + name_matched = TRUE; + if (p_entry->p_action != NULL) + p_entry->p_action(p_name, p_value); + break; + } + + p_entry++; + } + + if ((name_matched == FALSE) && (trace_conf_enabled == TRUE)) + { + /* Check if this is a TRC config item */ + bte_trace_conf(p_name, p_value); + } + } + + fclose(p_file); + } + else + { + ALOGI( "bte_load_conf file >%s< not found", p_path); + } +} + +/******************************************************************************* +** +** Function bte_parse_did_conf +** +** Description Read conf entry from p_path file one by one and get +** the corresponding config value +** +** Returns TRUE if success, else FALSE +** +*******************************************************************************/ +static BOOLEAN bte_parse_did_conf (const char *p_path, UINT32 num, + tKEY_VALUE_PAIRS *conf_pairs, UINT32 conf_pairs_num) +{ + UINT32 i, param_num=0, count=0, start_count=0, end_count=0, conf_num=0; + BOOLEAN key=TRUE, conf_found=FALSE; + + FILE *p_file; + char *p; + char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */ + + ALOGI("Attempt to load did conf from %s", p_path); + + if ((p_file = fopen(p_path, "r")) != NULL) + { + /* read line by line */ + while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL) + { + count++; + if (line[0] == CONF_COMMENT) + continue; + + if (conf_found && (conf_num == num) && (*line == '[')) { + conf_found = FALSE; + end_count = count-1; + break; + } + + p = strtok(line, CONF_DELIMITERS); + while (p != NULL) { + if (conf_num <= num) { + if (key) { + if (!strcmp(p, conf_pairs[0].key)) { + if (++conf_num == num) { + conf_found = TRUE; + start_count = count; + strncpy(conf_pairs[0].value, "1", CONF_VALUE_LEN); + } + } else { + if (conf_num == num) { + for (i=1; i<conf_pairs_num; i++) { + if (!strcmp(p, conf_pairs[i].key)) { + param_num = i; + break; + } + } + if (i == conf_pairs_num) { + error("Attribute %s does not belong to %s configuration", + p, conf_pairs[0].key); + fclose(p_file); + return FALSE; + } + } + key = FALSE; + } + } else { + if ((conf_num == num) && param_num) { + strncpy(conf_pairs[param_num].value, p, CONF_VALUE_LEN-1); + param_num = 0; + } + key = TRUE; + } + } + p = strtok(NULL, CONF_DELIMITERS); + } + } + + fclose(p_file); + } + else + { + ALOGI( "bte_parse_did_conf file >%s< not found", p_path); + } + if (!end_count) + end_count = count; + + if (start_count) { + debug("Read %s configuration #%u from lines %u to %u in file %s", + conf_pairs[0].key, (unsigned int)num, (unsigned int)start_count, + (unsigned int)end_count, p_path); + return TRUE; + } + + error("%s configuration not found in file %s", conf_pairs[0].key, p_path); + return FALSE; +} + +/******************************************************************************* +** +** Function bte_load_did_conf +** +** Description Set local Device ID records, reading from configuration files +** +** Returns None +** +*******************************************************************************/ + +void bte_load_did_conf (const char *p_path) +{ + tBTA_DI_RECORD rec; + UINT32 rec_num, i, j; + + for (i=1; i<=BTA_DI_NUM_MAX; i++) { + for (j=0; j<CONF_DID_MAX; j++) { + *did_conf_pairs[j].value = 0; + } + + if (bte_parse_did_conf(p_path, i, did_conf_pairs, CONF_DID_MAX)) { + memset(&rec, 0, sizeof(rec)); + + if (*did_conf_pairs[CONF_DID_RECORD_NUM].value) { + rec_num = (UINT32)(strtoul(did_conf_pairs[CONF_DID_RECORD_NUM].value, NULL, 0)-1); + } else { + debug("[%d] Unknown %s", (unsigned int)i, did_conf_pairs[CONF_DID_RECORD_NUM].key); + continue; + } + + if (*did_conf_pairs[CONF_DID_VENDOR_ID].value) { + rec.vendor = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID].value, NULL, 0); + } else { + rec.vendor = LMP_COMPID_BROADCOM; + } + + if (*did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value) { + rec.vendor_id_source = (UINT16)strtoul(did_conf_pairs[CONF_DID_VENDOR_ID_SOURCE].value, NULL, 0); + } else { + rec.vendor_id_source = DI_VENDOR_ID_SOURCE_BTSIG; + } + + if ((*did_conf_pairs[CONF_DID].value == 0) || + (rec_num >= BTA_DI_NUM_MAX) || + (!((rec.vendor_id_source >= DI_VENDOR_ID_SOURCE_BTSIG) && + (rec.vendor_id_source <= DI_VENDOR_ID_SOURCE_USBIF))) || + (rec.vendor == DI_VENDOR_ID_DEFAULT)) { + + error("DID record #%u not set", (unsigned int)i); + for (j=0; j<CONF_DID_MAX; j++) { + error("%s:%s", did_conf_pairs[j].key, did_conf_pairs[j].value); + } + continue; + } + + rec.product = (UINT16)strtoul(did_conf_pairs[CONF_DID_PRODUCT_ID].value, NULL, 0); + rec.version = (UINT16)strtoul(did_conf_pairs[CONF_DID_VERSION].value, NULL, 0); + + strncpy(rec.client_executable_url, + did_conf_pairs[CONF_DID_CLIENT_EXECUTABLE_URL].value, + SDP_MAX_ATTR_LEN); + strncpy(rec.service_description, + did_conf_pairs[CONF_DID_SERVICE_DESCRIPTION].value, + SDP_MAX_ATTR_LEN); + strncpy(rec.documentation_url, + did_conf_pairs[CONF_DID_DOCUMENTATION_URL].value, + SDP_MAX_ATTR_LEN); + + for (j=0; j<strlen(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value); j++) { + did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j] = + tolower(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value[j]); + } + if ((!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "true")) || + (!strcmp(did_conf_pairs[CONF_DID_PRIMARY_RECORD].value, "1"))) { + rec.primary_record = TRUE; + } else { + rec.primary_record = FALSE; + } + + info("[%u] primary_record=%d vendor_id=0x%04X vendor_id_source=0x%04X product_id=0x%04X version=0x%04X", + (unsigned int)rec_num+1, rec.primary_record, rec.vendor, + rec.vendor_id_source, rec.product, rec.version); + if (*rec.client_executable_url) { + info(" client_executable_url=%s", rec.client_executable_url); + } + if (*rec.service_description) { + info(" service_description=%s", rec.service_description); + } + if (*rec.documentation_url) { + info(" documentation_url=%s", rec.documentation_url); + } + + if (BTA_DmSetLocalDiRecord(&rec, &rec_num) != BTA_SUCCESS) { + error("SetLocalDiInfo failed for #%u!", (unsigned int)i); + } + } + } +} + |