blob: 86d53b41ecdd5efac1f018f9f08ad121ae8f37e7 [file] [log] [blame]
justinwengc6347db2019-02-21 18:49:00 +08001/*
2 * Copyright (C) 2019 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_audiozoom"
18/*#define LOG_NDEBUG 0*/
19
20#include <errno.h>
21#include <log/log.h>
22#include <stdlib.h>
23#include <expat.h>
24#include <audio_hw.h>
25#include <system/audio.h>
26#include <platform_api.h>
27#include "audio_extn.h"
28
29#include "audiozoom.h"
30
31#include <resolv.h>
32
33#define AUDIOZOOM_PRESET_FILE "/vendor/etc/audiozoom.xml"
34#define MIN_BUFSIZE 8
35
36typedef struct qdsp_audiozoom_cfg {
37 uint32_t topo_id;
38 uint32_t module_id;
39 uint32_t instance_id;
40 uint32_t zoom_param_id;
41 uint32_t wide_param_id;
42 uint32_t dir_param_id;
43 uint32_t app_type;
44} qdsp_audiozoom_cfg_t;
45
46static qdsp_audiozoom_cfg_t qdsp_audiozoom;
47
48static void start_tag(void *userdata __unused, const XML_Char *tag_name,
49 const XML_Char **attr)
50{
51 uint32_t index = 0;
52
53 if (!attr) {
54 ALOGE("%s: NULL platform/tag_name/attr", __func__);
55 return;
56 }
57
58 if (strcmp(tag_name, "topo") == 0) {
59 if (strcmp(attr[0], "id") == 0) {
60 if (attr[1])
61 qdsp_audiozoom.topo_id = atoi(attr[1]);
62 }
63 } else if (strcmp(tag_name, "module") == 0) {
64 if (strcmp(attr[0], "id") == 0) {
65 if (attr[1])
66 qdsp_audiozoom.module_id = atoi(attr[1]);
67 }
68 } else if (strcmp(tag_name, "param") == 0) {
69 while (attr[index] != NULL) {
70 if (strcmp(attr[index], "zoom_id") == 0) {
71 index++;
72 if (attr[index])
73 qdsp_audiozoom.zoom_param_id = atoi(attr[index]);
74 else
75 break;
76 } else if (strcmp(attr[index], "wide_id") == 0) {
77 index++;
78 if (attr[index])
79 qdsp_audiozoom.wide_param_id = atoi(attr[index]);
80 else
81 break;
82 } else if (strcmp(attr[index], "dir_id") == 0) {
83 index++;
84 if (attr[index])
85 qdsp_audiozoom.dir_param_id = atoi(attr[index]);
86 else
87 break;
88 }
89 index++;
90 }
91 } else if (strcmp(tag_name, "app_type") == 0) {
92 if (strcmp(attr[0], "id") == 0) {
93 if (attr[1])
94 qdsp_audiozoom.app_type = atoi(attr[1]);
95 }
96 } else if (strcmp(tag_name, "instance") == 0) {
97 if (strcmp(attr[0], "id") == 0) {
98 if (attr[1])
99 qdsp_audiozoom.instance_id = atoi(attr[1]);
100 }
101 } else {
102 ALOGE("%s: %s is not a supported tag", __func__, tag_name);
103 }
104
105 return;
106}
107
108static void end_tag(void *userdata __unused, const XML_Char *tag_name)
109{
110 if (strcmp(tag_name, "topo") == 0) {
111 } else if (strcmp(tag_name, "module") == 0) {
112 } else if (strcmp(tag_name, "param") == 0) {
113 } else if (strcmp(tag_name, "app_type") == 0) {
114 } else if (strcmp(tag_name, "instance") == 0) {
115 } else {
116 ALOGE("%s: %s is not a supported tag", __func__, tag_name);
117 }
118}
119
120static int audio_extn_audiozoom_parse_info(const char *filename)
121{
122 XML_Parser parser;
123 FILE *file;
124 int ret = 0;
125 int bytes_read;
126 void *buf;
127 static const uint32_t kBufSize = 1024;
128
129 file = fopen(filename, "r");
130 if (!file) {
131 ALOGE("%s: Failed to open %s", __func__, filename);
132 ret = -ENODEV;
133 goto done;
134 }
135
136 parser = XML_ParserCreate(NULL);
137 if (!parser) {
138 ALOGE("%s: Failed to create XML parser!", __func__);
139 ret = -ENODEV;
140 goto err_close_file;
141 }
142
143 XML_SetElementHandler(parser, start_tag, end_tag);
144
145 while (1) {
146 buf = XML_GetBuffer(parser, kBufSize);
147 if (buf == NULL) {
148 ALOGE("%s: XML_GetBuffer failed", __func__);
149 ret = -ENOMEM;
150 goto err_free_parser;
151 }
152
153 bytes_read = fread(buf, 1, kBufSize, file);
154 if (bytes_read < 0) {
155 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read);
156 ret = bytes_read;
157 goto err_free_parser;
158 }
159
160 if (XML_ParseBuffer(parser, bytes_read,
161 bytes_read == 0) == XML_STATUS_ERROR) {
162 ALOGE("%s: XML_ParseBuffer failed, for %s",
163 __func__, filename);
164 ret = -EINVAL;
165 goto err_free_parser;
166 }
167
168 if (bytes_read == 0)
169 break;
170 }
171
172err_free_parser:
173 XML_ParserFree(parser);
174err_close_file:
175 fclose(file);
176done:
177 return ret;
178}
179
180int audio_extn_audiozoom_set_microphone_direction(
181 struct stream_in *in, audio_microphone_direction_t dir)
182{
183 (void)in;
184 (void)dir;
185 return 0;
186}
187
188static int audio_extn_audiozoom_set_microphone_field_dimension_zoom(
189 struct stream_in *in, float zoom)
190{
191 struct audio_device *adev = in->dev;
192 struct str_parms *parms = str_parms_create();
193 uint8_t value[MIN_BUFSIZE] = {0};
194 char data[MIN_BUFSIZE * 2] = {0};
195 int32_t ret;
196
197 if (zoom > 1.0 || zoom < 0)
198 return -EINVAL;
199
200 if (qdsp_audiozoom.topo_id == 0 || qdsp_audiozoom.module_id == 0 ||
201 qdsp_audiozoom.zoom_param_id == 0)
202 return -ENOSYS;
203
204 str_parms_add_int(parms, "cal_devid", in->device);
205 str_parms_add_int(parms, "cal_apptype", in->app_type_cfg.app_type);
206 str_parms_add_int(parms, "cal_topoid", qdsp_audiozoom.topo_id);
207 str_parms_add_int(parms, "cal_moduleid", qdsp_audiozoom.module_id);
208 str_parms_add_int(parms, "cal_instanceid", qdsp_audiozoom.instance_id);
209 str_parms_add_int(parms, "cal_paramid", qdsp_audiozoom.zoom_param_id);
210
211 zoom *= 255;
212 value[0] = (uint8_t) zoom; /* Valid value is 0 to 255 */
213
214 ret = b64_ntop(value, sizeof(value), data, sizeof(data));
215 if (ret > 0) {
216 str_parms_add_str(parms, "cal_data", data);
217
218 platform_set_parameters(adev->platform, parms);
219 } else {
220 ALOGE("%s: failed to convert data to string, ret %d", __func__, ret);
221 }
222
223 str_parms_destroy(parms);
224
225 return 0;
226}
227
228static int audio_extn_audiozoom_set_microphone_field_dimension_wide_angle(
229 struct stream_in *in, float zoom)
230{
231 (void)in;
232 (void)zoom;
233 return 0;
234}
235
236int audio_extn_audiozoom_set_microphone_field_dimension(
237 struct stream_in *in, float zoom)
238{
239 if (zoom > 1.0 || zoom < -1.0)
240 return -EINVAL;
241
242 if (zoom >= 0 && zoom <= 1.0)
243 return audio_extn_audiozoom_set_microphone_field_dimension_zoom(in, zoom);
244
245 if (zoom >= -1.0 && zoom <= 0)
246 return audio_extn_audiozoom_set_microphone_field_dimension_wide_angle(in, zoom);
247
248 return 0;
249}
250
251int audio_extn_audiozoom_init()
252{
253 audio_extn_audiozoom_parse_info(AUDIOZOOM_PRESET_FILE);
254
255 ALOGV("%s: topo_id=%d, module_id=%d, instance_id=%d, zoom__id=%d, dir_id=%d, app_type=%d",
256 __func__, qdsp_audiozoom.topo_id, qdsp_audiozoom.module_id, qdsp_audiozoom.instance_id,
257 qdsp_audiozoom.zoom_param_id, qdsp_audiozoom.dir_param_id,qdsp_audiozoom.app_type);
258
259 return 0;
260}