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