1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "audio_hw_acdb" 18 //#define LOG_NDEBUG 0 19 #define LOG_NDDEBUG 0 20 21 #include <errno.h> 22 #include <stdlib.h> 23 #include <stdbool.h> 24 #include <dlfcn.h> 25 #include <log/log.h> 26 #include <cutils/str_parms.h> 27 #include <system/audio.h> 28 #include <tinyalsa/asoundlib.h> 29 #include "acdb.h" 30 #include <platform_api.h> 31 32 #define PLATFORM_CONFIG_KEY_SOUNDCARD_NAME "snd_card_name" 33 34 int acdb_init(int snd_card_num) 35 { 36 37 int result = -1; 38 char *cvd_version = NULL; 39 40 char *snd_card_name = NULL; 41 struct mixer *mixer = NULL; 42 struct acdb_platform_data *my_data = NULL; 43 44 if(snd_card_num < 0) { 45 ALOGE("invalid sound card number"); 46 return result; 47 } 48 49 mixer = mixer_open(snd_card_num); 50 if (!mixer) { 51 ALOGE("%s: Unable to open the mixer card: %d", __func__, 52 snd_card_num); 53 goto cleanup; 54 } 55 56 my_data = calloc(1, sizeof(struct acdb_platform_data)); 57 if (!my_data) { 58 ALOGE("failed to allocate acdb platform data"); 59 goto cleanup; 60 } 61 62 list_init(&my_data->acdb_meta_key_list); 63 64 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW); 65 if (my_data->acdb_handle == NULL) { 66 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER); 67 goto cleanup; 68 } 69 70 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER); 71 72 my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle, 73 "acdb_loader_init_v3"); 74 if (my_data->acdb_init_v3 == NULL) 75 ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror()); 76 77 my_data->acdb_init_v2 = (acdb_init_v2_cvd_t)dlsym(my_data->acdb_handle, 78 "acdb_loader_init_v2"); 79 if (my_data->acdb_init_v2 == NULL) 80 ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror()); 81 82 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle, 83 "acdb_loader_init_ACDB"); 84 if (my_data->acdb_init == NULL && my_data->acdb_init_v2 == NULL 85 && my_data->acdb_init_v3 == NULL) { 86 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror()); 87 goto cleanup; 88 } 89 90 /* Get CVD version */ 91 cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE); 92 if (!cvd_version) { 93 ALOGE("%s: Failed to allocate cvd version", __func__); 94 goto cleanup; 95 } else { 96 struct mixer_ctl *ctl = NULL; 97 int count = 0; 98 99 ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL); 100 if (!ctl) { 101 ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, CVD_VERSION_MIXER_CTL); 102 goto cleanup; 103 } 104 mixer_ctl_update(ctl); 105 106 count = mixer_ctl_get_num_values(ctl); 107 if (count > MAX_CVD_VERSION_STRING_SIZE) 108 count = MAX_CVD_VERSION_STRING_SIZE; 109 110 result = mixer_ctl_get_array(ctl, cvd_version, count); 111 if (result != 0) { 112 ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__); 113 goto cleanup; 114 } 115 } 116 117 /* Get Sound card name */ 118 snd_card_name = strdup(mixer_get_name(mixer)); 119 if (!snd_card_name) { 120 ALOGE("failed to allocate memory for snd_card_name"); 121 result = -1; 122 goto cleanup; 123 } 124 125 if (my_data->acdb_init_v3) 126 result = my_data->acdb_init_v3(snd_card_name, cvd_version, 127 &my_data->acdb_meta_key_list); 128 else if (my_data->acdb_init_v2) 129 result = my_data->acdb_init_v2(snd_card_name, cvd_version, 0); 130 else 131 result = my_data->acdb_init(); 132 133 cleanup: 134 if (NULL != my_data) { 135 if (my_data->acdb_handle) 136 dlclose(my_data->acdb_handle); 137 138 struct listnode *node; 139 struct meta_key_list *key_info; 140 list_for_each(node, &my_data->acdb_meta_key_list) { 141 key_info = node_to_item(node, struct meta_key_list, list); 142 free(key_info); 143 } 144 free(my_data); 145 } 146 147 mixer_close(mixer); 148 free(cvd_version); 149 free(snd_card_name); 150 151 return result; 152 } 153 154 int acdb_set_parameters(void *platform, struct str_parms *parms) 155 { 156 struct acdb_platform_data *my_data = (struct acdb_platform_data *)platform; 157 char value[128]; 158 char *kv_pairs = str_parms_to_str(parms); 159 int ret = 0; 160 161 if (kv_pairs == NULL) { 162 ret = -EINVAL; 163 ALOGE("%s: key-value pair is NULL",__func__); 164 goto done; 165 } 166 167 ret = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME, 168 value, sizeof(value)); 169 if (ret >= 0) { 170 str_parms_del(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME); 171 my_data->snd_card_name = strdup(value); 172 ALOGV("%s: sound card name %s", __func__, my_data->snd_card_name); 173 } 174 175 done: 176 free(kv_pairs); 177 178 return ret; 179 } 180