• 高通 mixer_paths.xml 音频配置文件 初始化过程


    记录一下高通音频配置文件mixer_paths.xml初始化过程。参考代码基于Android O。

    hardware/qcom/audio/hal/audio_hw.c

    struct audio_module HAL_MODULE_INFO_SYM = {
        .common = {
            .tag = HARDWARE_MODULE_TAG,
            .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
            .hal_api_version = HARDWARE_HAL_API_VERSION,
            .id = AUDIO_HARDWARE_MODULE_ID,
            .name = "QCOM Audio HAL",
            .author = "The Linux Foundation",
            .methods = &hal_module_methods,
        },   
    };
    
    
    对应操作方法
    static struct hw_module_methods_t hal_module_methods = {
        .open = adev_open,
    };
    
    
    static int adev_open(const hw_module_t *module, const char *name,
                         hw_device_t **device)
    {
    	......
        adev->platform = platform_init(adev);			// 平台初始化函数
        if (!adev->platform) {
            free(adev->snd_dev_ref_cnt);
            free(adev);
            ALOGE("%s: Failed to init platform data, aborting.", __func__);
            *device = NULL;
            pthread_mutex_unlock(&adev_init_lock);
            pthread_mutex_destroy(&adev->lock);
            return -EINVAL;
        }
    	......
    }
    

    根据不同的芯片找到对应的文件
    hardware/qcom/audio/hal/msm8916/platform.c

    void *platform_init(struct audio_device *adev)
    {
        char value[PROPERTY_VALUE_MAX];
        struct platform_data *my_data = NULL;
        int snd_card_num = 0;
        const char *snd_card_name;
        char mixer_xml_path[MAX_MIXER_XML_PATH],ffspEnable[PROPERTY_VALUE_MAX];
        const char *mixer_ctl_name = "Set HPX ActiveBe";
        struct mixer_ctl *ctl = NULL;
        int idx;
        int wsaCount =0;
        bool is_wsa_combo_supported = false;
    
        snd_card_num = audio_extn_utils_get_snd_card_num();     //获取声卡的的编号
        if(snd_card_num < 0) {
            ALOGE("%s: Unable to find correct sound card", __func__);
            return NULL;
        }
    
        adev->snd_card = snd_card_num;
        ALOGD("%s: Opened sound card:%d", __func__, snd_card_num);
    
        adev->mixer = mixer_open(snd_card_num);
    	    if (!adev->mixer) {
            ALOGE("%s: Unable to open the mixer card: %d", __func__,
                   snd_card_num);
            return NULL;
        }
    
        snd_card_name = mixer_get_name(adev->mixer);
        ALOGD("%s: snd_card_name: %s", __func__, snd_card_name);
    
        my_data = calloc(1, sizeof(struct platform_data));
    
        if (!my_data) {
            ALOGE("failed to allocate platform data");
            return NULL;
        }
    
        my_data->hw_info = hw_info_init(snd_card_name);     //初始化hw_info结构体
        if (!my_data->hw_info) {
            ALOGE("%s: Failed to init hardware info", __func__);
            free(my_data);
            return NULL;
        }
    
        query_platform(snd_card_name, mixer_xml_path);                              //query_platform,根据设备名称找到xml文件的路径
        ALOGD("%s: mixer path file is %s", __func__,
                                mixer_xml_path);
        if (audio_extn_read_xml(adev, snd_card_num, mixer_xml_path,
                                MIXER_XML_PATH_AUXPCM) == -ENOSYS) {
            adev->audio_route = audio_route_init(snd_card_num,					// 解析xml文件
                                             mixer_xml_path);
        }
        if (!adev->audio_route) {
            ALOGE("%s: Failed to init audio route controls, aborting.",
                   __func__);
    			           free(my_data);
            mixer_close(adev->mixer);
            return NULL;
        }
        update_codec_type(snd_card_name);
        update_interface(snd_card_name);
        ......
     
    }
    

    query_platform定义如下

    static void query_platform(const char *snd_card_name,
                                          char *mixer_xml_path)
    {
        if (!strncmp(snd_card_name, "msm8x16-snd-card-mtp",
                     sizeof("msm8x16-snd-card-mtp"))) {
            strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
                    sizeof(MIXER_XML_PATH_MTP));
    
            msm_device_to_be_id = msm_device_to_be_id_internal_codec;
            msm_be_id_array_len  =
                sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
    
    		......
    				
    	} else if (!strncmp(snd_card_name, "msm8953-snd-card-mtp",                            // 根据设备名称使用不同的xml文件
                     sizeof("msm8953-snd-card-mtp"))) {
            strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
                    sizeof(MIXER_XML_PATH_MTP));
            msm_device_to_be_id = msm_device_to_be_id_internal_codec;
            msm_be_id_array_len  =
                sizeof(msm_device_to_be_id_internal_codec) / sizeof(msm_device_to_be_id_internal_codec[0]);
    		
    		......
    }
    

    设备名称通过可以在adb中查看cat /proc/asound/cards,如下:

    Tony:/ # cat /proc/asound/cards
    cat /proc/asound/cards
     0 [msm8953sndcardm]: msm8953-snd-car - msm8953-snd-card-mtp
                          msm8953-snd-card-mtp	
    

    因此可以知道选取的文件
    #define MIXER_XML_PATH_MTP "/etc/mixer_paths_mtp.xml"

    xml文件解析函数位于system/media/audio_route/audio_route.c

    struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
    {
        struct config_parse_state state;
        XML_Parser parser;
        FILE *file;
        int bytes_read;
        void *buf;
        struct audio_route *ar;
    
        ar = calloc(1, sizeof(struct audio_route));
        if (!ar)
            goto err_calloc;
    
        ar->mixer = mixer_open(card);
        if (!ar->mixer) {
            ALOGE("Unable to open the mixer, aborting.");
            goto err_mixer_open;
        }   
    
        ar->mixer_path = NULL;
        ar->mixer_path_size = 0;
        ar->num_mixer_paths = 0;
    
        /* allocate space for and read current mixer settings */
        if (alloc_mixer_state(ar) < 0)
            goto err_mixer_state;
    
        /* use the default XML path if none is provided */
        if (xml_path == NULL)
            xml_path = MIXER_XML_PATH;
    
        file = fopen(xml_path, "r");
    
        if (!file) {
            ALOGE("Failed to open %s: %s", xml_path, strerror(errno));
    		    parser = XML_ParserCreate(NULL);
        if (!parser) {
            ALOGE("Failed to create XML parser");
            goto err_parser_create;
        }
    
        memset(&state, 0, sizeof(state));
        state.ar = ar;
        XML_SetUserData(parser, &state);
        XML_SetElementHandler(parser, start_tag, end_tag);
    
        for (;;) {
            buf = XML_GetBuffer(parser, BUF_SIZE);
            if (buf == NULL)
                goto err_parse;
    
            bytes_read = fread(buf, 1, BUF_SIZE, file);
            if (bytes_read < 0)
                goto err_parse;
    
            if (XML_ParseBuffer(parser, bytes_read,
                                bytes_read == 0) == XML_STATUS_ERROR) {
                ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH);
                goto err_parse;
            }
    
            if (bytes_read == 0)
                break;
        }
    
        /* apply the initial mixer values, and save them so we can reset the
           mixer to the original values */
        audio_route_update_mixer(ar);
        save_mixer_state(ar);
    
        XML_ParserFree(parser);
    	    fclose(file);
        return ar;
        ......
    }
    

    xml位于源码位置hardware/qcom/audio/configs/msm8953/

    xml文件存放的路径更改了,android O的路径位于/vendor/etc/下面,android N位于/system/etc/

    mixer_paths_mtp.xml分析,可参考http://bbs.gfan.com/android-7626545-1-1.html

    文件的开头会写一些默认的参数,也就是里面的内容,就是默认的参数。

    然后不同的设备,也就是不同的标签里面的内容,标签中的值表示不同的设备。

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <mixer>
        <!-- These are the initial mixer settings -->
        <ctl name="Voice Rx Device Mute" id="0" value="0" />
        <ctl name="Voice Rx Device Mute" id="1" value="-1" />
        <ctl name="Voice Rx Device Mute" id="2" value="20" />
        <ctl name="Voice Tx Mute" id="0" value="0" />
        <ctl name="Voice Tx Mute" id="1" value="-1" />
        <ctl name="Voice Tx Mute" id="2" value="500" />
        <ctl name="Voice Rx Gain" id="0" value="0" />
        <ctl name="Voice Rx Gain" id="1" value="-1" />
        <ctl name="Voice Rx Gain" id="2" value="20" />
    	......
    	    <path name="handset">						<!-- 电话听筒 -->
            <ctl name="RX1 MIX1 INP1" value="RX1" />
            <ctl name="RDAC2 MUX" value="RX1" />
            <ctl name="RX1 Digital Volume" value="84" />
            <ctl name="EAR PA Gain" value="POS_6_DB" />
            <ctl name="EAR_S" value="Switch" />
        </path>
    
        <path name="handset-mic">						
            <path name="adc1" />
            <ctl name="IIR1 INP1 MUX" value="DEC1" />
        </path>
    
        <path name="headphones">						<!-- 耳机 -->
            <ctl name="MI2S_RX Channels" value="Two" />
            <ctl name="RX1 MIX1 INP1" value="RX1" />
            <ctl name="RX2 MIX1 INP1" value="RX2" />
            <ctl name="RX HPH Mode" value="HD2" />
            <ctl name="COMP0 RX1" value="1" />
            <ctl name="COMP0 RX2" value="1" />
            <ctl name="RDAC2 MUX" value="RX2" />
            <ctl name="HPHL" value="Switch" />
            <ctl name="HPHR" value="Switch" />
        </path>
    
        <path name="headset-mic">
            <path name="adc2" />
            <ctl name="ADC2 MUX" value="INP2" />
            <ctl name="IIR1 INP1 MUX" value="DEC1" />
        </path>
    	......
    
    

    Tony Liu

    2018-1-29

  • 相关阅读:
    Brunch with a Friend 与朋友共进午餐
    Linux使用tcpdump抓取网络数据包示例
    Linux LVM逻辑卷配置过程详解
    Linux不停往外发包
    jumpserver遇到的坑
    Python3.5 使用Sqlite3
    git rebase小计(转)
    pip3 更改安装源
    jquery ajax(3).post
    jquery ajax (2)实例 .GET
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/8378604.html
Copyright © 2020-2023  润新知