Android BlueDroid分析: 配置文件(bt_stack.conf bt_vendor.conf )的加载与分析

说明

在Android BlueDroid启动,即stack启动的时候,回去加载好几个配置文件, 然后BlueDroid Stack根据这几个配置文件会进行调整, 例如Device ID(did), Log相关的Trace Level, COD(即Class of Device), BT snoop log相关配置等等.下面结合代码和配置文件一起来说明分析.

配置文件说明

配置文件分为运行时动态加载和编译的时候直接解析使用的.主要有下面三个, 冒号后面是简要的作用说明.

编译完成后,这些配置文件都是位于: /system/etc/bluetooth/

如果是编译之前,那么是在device相关的vendor board中, 或者是默认的stack里面自带的文件.


 bt_stack.conf: 对stack进行配置, 包括不同的stack里面的log level, bt snoop的控制

 bt_did.conf : 记录和配置BLE Controller的信息, 例如VendorID可能是QualComm也可以是Broadcom等等.

 auto_pair_devlist.conf: 将某些slave/peripheral加入到BlackList中不让其配对

config格式

绝大部分都是用等号表示的string=value对, 也有使用{}与逗号区分的一串数据, 例如COD.

代码分析

配置文件的解析位于bte_config.c中, 其含有下面这些函数:

▼ functions
    device_name_cfg(char *p_conf_name, char *p_conf_value)
    device_class_cfg(char *p_conf_name, char *p_conf_value)
    logging_cfg_onoff(char *p_conf_name, char *p_conf_value)
    logging_set_filepath(char *p_conf_name, char *p_conf_value)
    trace_cfg_onoff(char *p_conf_name, char *p_conf_value)
    bte_load_conf(const char *p_path)
   -bte_parse_did_conf(const char *p_path, UINT32 num, tKEY_VALUE_PAIRS *conf_pairs, UINT32 conf_pairs_num)
    bte_load_did_conf(const char *p_path)

其中有trace log level解析相关的函数, 对于不同的文件解析使用的函数不同, 例如did使用did相关函数, 而bt_stack.conf使用bte_load_conf来解析.

而代码的实现也比较简单, 使用最多的函数就是strtok, 即对token的解析(可以参考C++程序设计原理与实践). 

解析完成后进行赋值完事.

那么对于did都有哪些assignment item:

/*******************************************************************************
**
** 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= 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

上面的代码看起来有一片,但是根据数组的下表宏,可以很清晰的知道只有这么几个:

▼ __anon3* : enum
    [enumerators]
   -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

对应的意义如下:

static tKEY_VALUE_PAIRS did_conf_pairs[CONF_DID_MAX] = {
    { "[DID]",               "" },
    { "recordNumber",        "" },
    { "primaryRecord",       "" },
    { "vendorId",            "" },
    { "vendorIdSource",      "" },
    { "productId",           "" },
    { "version",             "" },
    { "clientExecutableURL", "" },
    { "serviceDescription",  "" },
    { "documentationURL",    "" },
};

对于bt_stack.conf的解析分为两类, 一类是Trace Log Level, 还有就是其他的,具体见下面代码中的注释, 下面就是所有的可用被用来配置的string:

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}
};
解析的代码如下:

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)//判断是否是前面list中的
                {
                    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)) //判断是否是TraceLevel
            {
                /* 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);
    }
}

总结

实际上,除了上面三个conf文件, 我们还会看到一个额外的bt_vendor.conf, 在某些设备上面, 这个配置文件是给libbt-vendor.so中用的,用来配置串口与firmware. 

你可能感兴趣的:(Android)