|  | /* | 
|  | Copyright Statement: | 
|  |  | 
|  | This software/firmware and related documentation ("MediaTek Software") are | 
|  | protected under relevant copyright laws. The information contained herein is | 
|  | confidential and proprietary to MediaTek Inc. and/or its licensors. Without | 
|  | the prior written permission of MediaTek inc. and/or its licensors, any | 
|  | reproduction, modification, use or disclosure of MediaTek Software, and | 
|  | information contained herein, in whole or in part, shall be strictly | 
|  | prohibited. | 
|  |  | 
|  | MediaTek Inc. (C) 2016. All rights reserved. | 
|  |  | 
|  | BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES | 
|  | THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") | 
|  | RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER | 
|  | ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL | 
|  | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED | 
|  | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR | 
|  | NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH | 
|  | RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, | 
|  | INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES | 
|  | TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. | 
|  | RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO | 
|  | OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK | 
|  | SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE | 
|  | RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR | 
|  | STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S | 
|  | ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE | 
|  | RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE | 
|  | MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE | 
|  | CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. | 
|  |  | 
|  | Auther: Garlic Tseng <garlic.tseng@mediatek.com> | 
|  | */ | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <errno.h> | 
|  | #include <stdio.h> | 
|  | #include <alsa/asoundlib.h> | 
|  | #include "dev_string.h" | 
|  | #define STR_SIZE 128 | 
|  |  | 
|  | //mixer control structure for sound card | 
|  | static snd_mixer_t *g_all_mixer_handler; | 
|  |  | 
|  | static snd_mixer_elem_t *get_mixer_item_handler(const char *mixer_ctrl_name) | 
|  | { | 
|  | snd_mixer_selem_id_t *mixer_select = NULL; | 
|  | snd_mixer_elem_t *mixer_item_handler = NULL; | 
|  | int ret = 0; | 
|  |  | 
|  |  | 
|  | ret = snd_mixer_selem_id_malloc(&mixer_select); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_open failed: %d\n", __func__, ret); | 
|  | goto MIXER_ITEM_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | snd_mixer_selem_id_set_index(mixer_select, 0); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_selem_id_set_index failed: %d\n", | 
|  | __func__, ret); | 
|  | goto MIXER_ITEM_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | snd_mixer_selem_id_set_name(mixer_select, mixer_ctrl_name); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_selem_id_set_name failed: %d\n", | 
|  | __func__, ret); | 
|  | goto MIXER_ITEM_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | mixer_item_handler = snd_mixer_find_selem(g_all_mixer_handler, | 
|  | mixer_select); | 
|  |  | 
|  | if (!mixer_item_handler) { | 
|  | printf("%s, snd_mixer_find_selem not found\n", __func__); | 
|  | } | 
|  |  | 
|  | snd_mixer_selem_id_free(mixer_select); | 
|  | return mixer_item_handler; | 
|  |  | 
|  | MIXER_ITEM_CREATE_ERROR: | 
|  | snd_mixer_selem_id_free(mixer_select); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | static int initial_all_mixer_handler() | 
|  | { | 
|  | int ret = 0; | 
|  | ret = snd_mixer_open(&g_all_mixer_handler, 0); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_open failed: %d\n", __func__, ret); | 
|  | goto ALL_MIXER_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | ret = snd_mixer_attach(g_all_mixer_handler, CARD_NAME); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_attach failed: %d\n", __func__, ret); | 
|  | goto ALL_MIXER_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | ret = snd_mixer_selem_register(g_all_mixer_handler, NULL, NULL); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_selem_register failed: %d\n", __func__, | 
|  | ret); | 
|  | goto ALL_MIXER_CREATE_ERROR; | 
|  | } | 
|  |  | 
|  | ret = snd_mixer_load(g_all_mixer_handler); | 
|  | if (ret) { | 
|  | printf("%s, snd_mixer_load failed: %d\n", __func__, ret); | 
|  | goto ALL_MIXER_CREATE_ERROR; | 
|  | } | 
|  | return 0; | 
|  |  | 
|  | ALL_MIXER_CREATE_ERROR: | 
|  | snd_mixer_close(g_all_mixer_handler); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | int set_mixer_ctrl_value_int(const char *mixer_ctrl_name, | 
|  | const int option_int) | 
|  | { | 
|  | snd_mixer_elem_t *mixer_item_handler = NULL; | 
|  | int ret; | 
|  |  | 
|  | if (!g_all_mixer_handler) | 
|  | initial_all_mixer_handler(); | 
|  |  | 
|  | /* mixer control item */ | 
|  | mixer_item_handler = get_mixer_item_handler(mixer_ctrl_name); | 
|  | if (!mixer_item_handler) { | 
|  | printf("%s, get_mixer_item_handler failed!\n", __func__); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | ret = snd_mixer_selem_set_enum_item(mixer_item_handler, 0, option_int); | 
|  | if (ret) { | 
|  | printf("%s, set_enum_item failed: %d, option_int: %d\n", | 
|  | __func__, ret, option_int); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int set_mixer_ctrl_value_string(const char *mixer_ctrl_name, | 
|  | const char *option_name) | 
|  | { | 
|  | snd_mixer_elem_t *mixer_item_handler = NULL; | 
|  | int mixer_item_option_num = 0; | 
|  | int i, ret; | 
|  | char item_name[STR_SIZE]; | 
|  |  | 
|  | if (!g_all_mixer_handler) | 
|  | initial_all_mixer_handler(); | 
|  |  | 
|  | /* mixer control item */ | 
|  | mixer_item_handler = get_mixer_item_handler(mixer_ctrl_name); | 
|  | if (!mixer_item_handler) { | 
|  | printf("%s, get_mixer_item_handler failed!\n", __func__); | 
|  | return -EINVAL; | 
|  | } | 
|  | mixer_item_option_num = | 
|  | snd_mixer_selem_get_enum_items(mixer_item_handler); | 
|  |  | 
|  | /* if failed, get_enum_items return nagetive error num. */ | 
|  | if (mixer_item_option_num < 0) { | 
|  | printf("%s, snd_mixer_selem_get_enum_items failed: %d\n", | 
|  | __func__, mixer_item_option_num); | 
|  | return mixer_item_option_num; | 
|  | } | 
|  |  | 
|  | /* find option_name index */ | 
|  | for (i = 0; i < mixer_item_option_num; i++) { | 
|  | ret = snd_mixer_selem_get_enum_item_name(mixer_item_handler, i, | 
|  | STR_SIZE, item_name); | 
|  | if (ret) | 
|  | printf("%s, get_enum_item_name failed: %d, i: %d\n", | 
|  | __func__, ret, i); | 
|  | if (!strcmp(option_name, item_name)) | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* not found */ | 
|  | if (i == mixer_item_option_num) { | 
|  | printf("%s, option_name (%s) not found in mixerctrl (%s)!\n", | 
|  | __func__, option_name, mixer_ctrl_name); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /* found: the index is 'i' */ | 
|  | ret = snd_mixer_selem_set_enum_item(mixer_item_handler, 0, i); | 
|  | if (ret) { | 
|  | printf("%s, set_enum_item failed: %d, i: %d\n", | 
|  | __func__, ret, i); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int get_mixer_ctrl_value_int(const char *mixer_ctrl_name) | 
|  | { | 
|  | snd_mixer_elem_t *mixer_item_handler = NULL; | 
|  | unsigned int mixer_item_value[1]; | 
|  | int ret; | 
|  |  | 
|  | if (!g_all_mixer_handler) | 
|  | initial_all_mixer_handler(); | 
|  |  | 
|  | mixer_item_handler = get_mixer_item_handler(mixer_ctrl_name); | 
|  | if (!mixer_item_handler) { | 
|  | printf("%s, get_mixer_item_handler failed!\n", __func__); | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | ret = snd_mixer_selem_get_enum_item(mixer_item_handler, 0, | 
|  | mixer_item_value); | 
|  |  | 
|  | if (ret) { | 
|  | printf("%s, selem_get_enum_item failed: %d\n", __func__, ret); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | return mixer_item_value[0]; | 
|  | } | 
|  |  | 
|  | char *get_mixer_ctrl_value_string(const char *mixer_ctrl_name, | 
|  | char *returned_value_name, | 
|  | int value_name_size) | 
|  | { | 
|  | snd_mixer_elem_t *mixer_item_handler = | 
|  | get_mixer_item_handler(mixer_ctrl_name); | 
|  | int mixer_value_int = get_mixer_ctrl_value_int(mixer_ctrl_name); | 
|  | int ret; | 
|  | char item_name[STR_SIZE]; | 
|  |  | 
|  | ret = snd_mixer_selem_get_enum_item_name(mixer_item_handler, | 
|  | mixer_value_int, | 
|  | STR_SIZE, item_name); | 
|  | if (ret) { | 
|  | printf("%s, get_enum_item_name failed: %d, mixer_value_int: %d\n", | 
|  | __func__, ret, mixer_value_int); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | return strncpy(returned_value_name, item_name, value_name_size); | 
|  | } | 
|  |  |