Android BlueDroid分析:プロファイル(bt_stack.conf bt_vendor.conf)のロードと分析

6845 ワード

説明
Android BlueDroidが起動する、すなわちstackが起動するときに、いくつかのプロファイルを再ロードしてから、BlueDroid Stackはこれらのプロファイルに基づいて、DeviceID(did)、Log関連のTrace Level、COD(Class of Device)、BT snoop log関連のプロファイルなどの調整を行う.次に、コードとプロファイルを組み合わせて分析を説明する.
プロファイルの説明
プロファイルは、実行時の動的ロードとコンパイル時に直接解析するために使用される.主に以下の3つがあり、コロンの後には簡単な作用説明がある.
コンパイルが完了すると、これらのプロファイルは/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の解析は2つのクラスに分けられ、1つは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);
    }
}

まとめ
実際には、上の3つのconfファイルのほかに、追加のbt_も見られます.vendor.conf、いくつかのデバイスの上で、このプロファイルはlibbt-vendorに与えられます.soで使用する、シリアルポートとfirmwareを構成するために使用される.