1 /* 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 35 typedef struct qdsp_audiozoom_cfg { 36 uint32_t topo_id; 37 uint32_t module_id; 38 uint32_t instance_id; 39 uint32_t zoom_param_id; 40 uint32_t wide_param_id; 41 uint32_t dir_param_id; 42 uint32_t app_type; 43 } qdsp_audiozoom_cfg_t; 44 45 static qdsp_audiozoom_cfg_t qdsp_audiozoom; 46 47 static void start_tag(void *userdata __unused, const XML_Char *tag_name, 48 const XML_Char **attr) 49 { 50 uint32_t index = 0; 51 52 if (!attr) { 53 ALOGE("%s: NULL platform/tag_name/attr", __func__); 54 return; 55 } 56 57 if (strcmp(tag_name, "topo") == 0) { 58 if (strcmp(attr[0], "id") == 0) { 59 if (attr[1]) 60 qdsp_audiozoom.topo_id = atoi(attr[1]); 61 } 62 } else if (strcmp(tag_name, "module") == 0) { 63 if (strcmp(attr[0], "id") == 0) { 64 if (attr[1]) 65 qdsp_audiozoom.module_id = atoi(attr[1]); 66 } 67 } else if (strcmp(tag_name, "param") == 0) { 68 while (attr[index] != NULL) { 69 if (strcmp(attr[index], "zoom_id") == 0) { 70 index++; 71 if (attr[index]) 72 qdsp_audiozoom.zoom_param_id = atoi(attr[index]); 73 else 74 break; 75 } else if (strcmp(attr[index], "wide_id") == 0) { 76 index++; 77 if (attr[index]) 78 qdsp_audiozoom.wide_param_id = atoi(attr[index]); 79 else 80 break; 81 } else if (strcmp(attr[index], "dir_id") == 0) { 82 index++; 83 if (attr[index]) 84 qdsp_audiozoom.dir_param_id = atoi(attr[index]); 85 else 86 break; 87 } 88 index++; 89 } 90 } else if (strcmp(tag_name, "app_type") == 0) { 91 if (strcmp(attr[0], "id") == 0) { 92 if (attr[1]) 93 qdsp_audiozoom.app_type = atoi(attr[1]); 94 } 95 } else if (strcmp(tag_name, "instance") == 0) { 96 if (strcmp(attr[0], "id") == 0) { 97 if (attr[1]) 98 qdsp_audiozoom.instance_id = atoi(attr[1]); 99 } 100 } else { 101 ALOGE("%s: %s is not a supported tag", __func__, tag_name); 102 } 103 104 return; 105 } 106 107 static void end_tag(void *userdata __unused, const XML_Char *tag_name) 108 { 109 if (strcmp(tag_name, "topo") == 0) { 110 } else if (strcmp(tag_name, "module") == 0) { 111 } else if (strcmp(tag_name, "param") == 0) { 112 } else if (strcmp(tag_name, "app_type") == 0) { 113 } else if (strcmp(tag_name, "instance") == 0) { 114 } else { 115 ALOGE("%s: %s is not a supported tag", __func__, tag_name); 116 } 117 } 118 119 static int audio_extn_audiozoom_parse_info(const char *filename) 120 { 121 XML_Parser parser; 122 FILE *file; 123 int ret = 0; 124 int bytes_read; 125 void *buf; 126 static const uint32_t kBufSize = 1024; 127 128 file = fopen(filename, "r"); 129 if (!file) { 130 ALOGE("%s: Failed to open %s", __func__, filename); 131 ret = -ENODEV; 132 goto done; 133 } 134 135 parser = XML_ParserCreate(NULL); 136 if (!parser) { 137 ALOGE("%s: Failed to create XML parser!", __func__); 138 ret = -ENODEV; 139 goto err_close_file; 140 } 141 142 XML_SetElementHandler(parser, start_tag, end_tag); 143 144 while (1) { 145 buf = XML_GetBuffer(parser, kBufSize); 146 if (buf == NULL) { 147 ALOGE("%s: XML_GetBuffer failed", __func__); 148 ret = -ENOMEM; 149 goto err_free_parser; 150 } 151 152 bytes_read = fread(buf, 1, kBufSize, file); 153 if (bytes_read < 0) { 154 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read); 155 ret = bytes_read; 156 goto err_free_parser; 157 } 158 159 if (XML_ParseBuffer(parser, bytes_read, 160 bytes_read == 0) == XML_STATUS_ERROR) { 161 ALOGE("%s: XML_ParseBuffer failed, for %s", 162 __func__, filename); 163 ret = -EINVAL; 164 goto err_free_parser; 165 } 166 167 if (bytes_read == 0) 168 break; 169 } 170 171 err_free_parser: 172 XML_ParserFree(parser); 173 err_close_file: 174 fclose(file); 175 done: 176 return ret; 177 } 178 179 int audio_extn_audiozoom_set_microphone_direction( 180 struct stream_in *in, audio_microphone_direction_t dir) 181 { 182 (void)in; 183 (void)dir; 184 return 0; 185 } 186 187 static int audio_extn_audiozoom_set_microphone_field_dimension_zoom( 188 struct stream_in *in, float zoom) 189 { 190 struct audio_device *adev = in->dev; 191 struct str_parms *parms = str_parms_create(); 192 /* The encoding process in b64_ntop represents 24-bit groups of input bits 193 as output strings of 4 encoded characters. */ 194 char data[((sizeof(zoom) + 2) / 3) * 4 + 1] = {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 ret = b64_ntop((uint8_t*)&zoom, sizeof(zoom), data, sizeof(data)); 212 if (ret > 0) { 213 str_parms_add_str(parms, "cal_data", data); 214 215 platform_set_parameters(adev->platform, parms); 216 } else { 217 ALOGE("%s: failed to convert data to string, ret %d", __func__, ret); 218 } 219 220 str_parms_destroy(parms); 221 222 return 0; 223 } 224 225 static int audio_extn_audiozoom_set_microphone_field_dimension_wide_angle( 226 struct stream_in *in, float zoom) 227 { 228 (void)in; 229 (void)zoom; 230 return 0; 231 } 232 233 int audio_extn_audiozoom_set_microphone_field_dimension( 234 struct stream_in *in, float zoom) 235 { 236 if (zoom > 1.0 || zoom < -1.0) 237 return -EINVAL; 238 239 if (zoom >= 0 && zoom <= 1.0) 240 return audio_extn_audiozoom_set_microphone_field_dimension_zoom(in, zoom); 241 242 if (zoom >= -1.0 && zoom <= 0) 243 return audio_extn_audiozoom_set_microphone_field_dimension_wide_angle(in, zoom); 244 245 return 0; 246 } 247 248 int audio_extn_audiozoom_init() 249 { 250 audio_extn_audiozoom_parse_info(AUDIOZOOM_PRESET_FILE); 251 252 ALOGV("%s: topo_id=%d, module_id=%d, instance_id=%d, zoom__id=%d, dir_id=%d, app_type=%d", 253 __func__, qdsp_audiozoom.topo_id, qdsp_audiozoom.module_id, qdsp_audiozoom.instance_id, 254 qdsp_audiozoom.zoom_param_id, qdsp_audiozoom.dir_param_id,qdsp_audiozoom.app_type); 255 256 return 0; 257 } 258