blob: 99599b880dee36e75c038bb8fe713820ba021cab [file] [log] [blame]
vivek mehta0fb11312017-05-15 19:35:32 -07001/*
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 <stdlib.h>
22#include <stdbool.h>
23#include <dlfcn.h>
24#include <cutils/log.h>
25#include <cutils/str_parms.h>
26#include <system/audio.h>
27#include <tinyalsa/asoundlib.h>
28#include "acdb.h"
29#include <platform_api.h>
30
31#define PLATFORM_CONFIG_KEY_SOUNDCARD_NAME "snd_card_name"
vivek mehta0fb11312017-05-15 19:35:32 -070032
33int acdb_init(int snd_card_num)
34{
35
36 int result = -1;
37 char *cvd_version = NULL;
38
39 char *snd_card_name = NULL;
40 struct mixer *mixer = NULL;
41 struct acdb_platform_data *my_data = NULL;
42
43 if(snd_card_num < 0) {
44 ALOGE("invalid sound card number");
45 return result;
46 }
47
48 mixer = mixer_open(snd_card_num);
49 if (!mixer) {
50 ALOGE("%s: Unable to open the mixer card: %d", __func__,
51 snd_card_num);
52 goto cleanup;
53 }
54
55 my_data = calloc(1, sizeof(struct acdb_platform_data));
56 if (!my_data) {
57 ALOGE("failed to allocate acdb platform data");
58 goto cleanup;
59 }
60
61 list_init(&my_data->acdb_meta_key_list);
62
vivek mehta0fb11312017-05-15 19:35:32 -070063 my_data->acdb_handle = dlopen(LIB_ACDB_LOADER, RTLD_NOW);
64 if (my_data->acdb_handle == NULL) {
65 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_ACDB_LOADER);
66 goto cleanup;
67 }
68
69 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_ACDB_LOADER);
70
71 my_data->acdb_init_v3 = (acdb_init_v3_t)dlsym(my_data->acdb_handle,
72 "acdb_loader_init_v3");
73 if (my_data->acdb_init_v3 == NULL)
74 ALOGE("%s: dlsym error %s for acdb_loader_init_v3", __func__, dlerror());
75
76 my_data->acdb_init_v2 = (acdb_init_v2_cvd_t)dlsym(my_data->acdb_handle,
77 "acdb_loader_init_v2");
78 if (my_data->acdb_init_v2 == NULL)
79 ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
80
81 my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
82 "acdb_loader_init_ACDB");
83 if (my_data->acdb_init == NULL && my_data->acdb_init_v2 == NULL
84 && my_data->acdb_init_v3 == NULL) {
85 ALOGE("%s: dlsym error %s for acdb_loader_init_ACDB", __func__, dlerror());
86 goto cleanup;
87 }
88
89 /* Get CVD version */
90 cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
91 if (!cvd_version) {
92 ALOGE("%s: Failed to allocate cvd version", __func__);
93 goto cleanup;
94 } else {
95 struct mixer_ctl *ctl = NULL;
96 int count = 0;
97
98 ctl = mixer_get_ctl_by_name(mixer, CVD_VERSION_MIXER_CTL);
99 if (!ctl) {
100 ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, CVD_VERSION_MIXER_CTL);
101 goto cleanup;
102 }
103 mixer_ctl_update(ctl);
104
105 count = mixer_ctl_get_num_values(ctl);
106 if (count > MAX_CVD_VERSION_STRING_SIZE)
107 count = MAX_CVD_VERSION_STRING_SIZE;
108
109 result = mixer_ctl_get_array(ctl, cvd_version, count);
110 if (result != 0) {
111 ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__);
112 goto cleanup;
113 }
114 }
115
116 /* Get Sound card name */
117 snd_card_name = strdup(mixer_get_name(mixer));
118 if (!snd_card_name) {
119 ALOGE("failed to allocate memory for snd_card_name");
120 result = -1;
121 goto cleanup;
122 }
123
vivek mehta1ffb5b22017-05-25 14:39:26 -0700124 if (my_data->acdb_init_v3)
vivek mehta0fb11312017-05-15 19:35:32 -0700125 result = my_data->acdb_init_v3(snd_card_name, cvd_version,
126 &my_data->acdb_meta_key_list);
vivek mehta1ffb5b22017-05-25 14:39:26 -0700127 else if (my_data->acdb_init_v2)
128 result = my_data->acdb_init_v2(snd_card_name, cvd_version, 0);
129 else
vivek mehta0fb11312017-05-15 19:35:32 -0700130 result = my_data->acdb_init();
vivek mehta0fb11312017-05-15 19:35:32 -0700131
132cleanup:
133 if (NULL != my_data) {
134 if (my_data->acdb_handle)
135 dlclose(my_data->acdb_handle);
136
137 struct listnode *node;
138 struct meta_key_list *key_info;
139 list_for_each(node, &my_data->acdb_meta_key_list) {
140 key_info = node_to_item(node, struct meta_key_list, list);
141 free(key_info);
142 }
143 free(my_data);
144 }
145
146 mixer_close(mixer);
147 free(cvd_version);
148 free(snd_card_name);
149
150 return result;
151}
152
vivek mehta0fb11312017-05-15 19:35:32 -0700153int acdb_set_parameters(void *platform, struct str_parms *parms)
154{
155 struct acdb_platform_data *my_data = (struct acdb_platform_data *)platform;
156 char value[128];
157 char *kv_pairs = str_parms_to_str(parms);
158 int ret = 0;
159
160 if (kv_pairs == NULL) {
161 ret = -EINVAL;
162 ALOGE("%s: key-value pair is NULL",__func__);
163 goto done;
164 }
165
166 ret = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME,
167 value, sizeof(value));
168 if (ret >= 0) {
169 str_parms_del(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME);
170 my_data->snd_card_name = strdup(value);
171 ALOGV("%s: sound card name %s", __func__, my_data->snd_card_name);
172 }
173
174done:
175 free(kv_pairs);
176
177 return ret;
178}