blob: 58631f272fabb4e763fe72d2dd8405db70a3bc1a [file] [log] [blame]
Haynes Mathew George5bc18842014-06-16 16:36:20 -07001/*
Haynes Mathew George569b7482017-05-08 14:44:27 -07002 * Copyright (C) 2014 The Android Open Source Project
Haynes Mathew George5bc18842014-06-16 16:36:20 -07003 *
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 "platform_info"
18#define LOG_NDDEBUG 0
19
20#include <errno.h>
21#include <stdio.h>
22#include <expat.h>
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080023#include <log/log.h>
Haynes Mathew George5bc18842014-06-16 16:36:20 -070024#include <audio_hw.h>
25#include "platform_api.h"
26#include <platform.h>
vivek mehtaa8d7c922016-05-25 14:40:44 -070027#include <math.h>
Haynes Mathew George5bc18842014-06-16 16:36:20 -070028
Haynes Mathew George98c95622014-06-20 19:14:25 -070029typedef enum {
30 ROOT,
31 ACDB,
32 PCM_ID,
33 BACKEND_NAME,
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070034 CONFIG_PARAMS,
keunhui.park2f7306a2015-07-16 16:48:06 +090035 OPERATOR_SPECIFIC,
vivek mehtaa8d7c922016-05-25 14:40:44 -070036 GAIN_LEVEL_MAPPING,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -080037 APP_TYPE,
jiabin8962a4d2018-03-19 18:21:24 -070038 MICROPHONE_CHARACTERISTIC,
Haynes Mathew George98c95622014-06-20 19:14:25 -070039} section_t;
40
41typedef void (* section_process_fn)(const XML_Char **attr);
42
43static void process_acdb_id(const XML_Char **attr);
44static void process_pcm_id(const XML_Char **attr);
45static void process_backend_name(const XML_Char **attr);
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070046static void process_config_params(const XML_Char **attr);
Haynes Mathew George98c95622014-06-20 19:14:25 -070047static void process_root(const XML_Char **attr);
keunhui.park2f7306a2015-07-16 16:48:06 +090048static void process_operator_specific(const XML_Char **attr);
vivek mehtaa8d7c922016-05-25 14:40:44 -070049static void process_gain_db_to_level_map(const XML_Char **attr);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -080050static void process_app_type(const XML_Char **attr);
jiabin8962a4d2018-03-19 18:21:24 -070051static void process_microphone_characteristic(const XML_Char **attr);
Haynes Mathew George98c95622014-06-20 19:14:25 -070052
53static section_process_fn section_table[] = {
54 [ROOT] = process_root,
55 [ACDB] = process_acdb_id,
56 [PCM_ID] = process_pcm_id,
57 [BACKEND_NAME] = process_backend_name,
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070058 [CONFIG_PARAMS] = process_config_params,
keunhui.park2f7306a2015-07-16 16:48:06 +090059 [OPERATOR_SPECIFIC] = process_operator_specific,
vivek mehtaa8d7c922016-05-25 14:40:44 -070060 [GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map,
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -080061 [APP_TYPE] = process_app_type,
jiabin8962a4d2018-03-19 18:21:24 -070062 [MICROPHONE_CHARACTERISTIC] = process_microphone_characteristic,
Haynes Mathew George98c95622014-06-20 19:14:25 -070063};
64
vivek mehta0fb11312017-05-15 19:35:32 -070065static set_parameters_fn set_parameters = &platform_set_parameters;
66
Haynes Mathew George98c95622014-06-20 19:14:25 -070067static section_t section;
68
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070069struct platform_info {
vivek mehta0fb11312017-05-15 19:35:32 -070070 bool do_full_parse;
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070071 void *platform;
72 struct str_parms *kvpairs;
73};
74
vivek mehta0fb11312017-05-15 19:35:32 -070075static struct platform_info my_data = {true, NULL, NULL};
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -070076
jiabin8962a4d2018-03-19 18:21:24 -070077struct audio_string_to_enum {
78 const char* name;
79 unsigned int value;
80};
81
82static const struct audio_string_to_enum mic_locations[AUDIO_MICROPHONE_LOCATION_CNT] = {
83 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_UNKNOWN),
84 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY),
85 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE),
86 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_PERIPHERAL),
87};
88
89static const struct audio_string_to_enum mic_directionalities[AUDIO_MICROPHONE_DIRECTIONALITY_CNT] = {
90 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_OMNI),
91 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL),
92 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN),
93 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID),
94 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID),
95 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID),
96};
97
98static const struct audio_string_to_enum device_in_types[] = {
99 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
100 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
101 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
102 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
103 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
104 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
105 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
106 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
107 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
108 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
109 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
110 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
111 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
112 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
113 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
114 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
115 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
116 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
117 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
118 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
119 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
120 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
121 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
122 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
123 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
124 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
125 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
126};
127
jiabina43dd882018-05-07 10:52:37 -0700128enum {
129 AUDIO_MICROPHONE_CHARACTERISTIC_NONE = 0u, // 0x0
130 AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY = 1u, // 0x1
131 AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL = 2u, // 0x2
132 AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL = 4u, // 0x4
133 AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION = 8u, // 0x8
134 AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION = 16u, // 0x10
135 AUDIO_MICROPHONE_CHARACTERISTIC_ALL = 31u, /* ((((SENSITIVITY | MAX_SPL) | MIN_SPL)
136 | ORIENTATION) | GEOMETRIC_LOCATION) */
137};
138
jiabin8962a4d2018-03-19 18:21:24 -0700139static bool find_enum_by_string(const struct audio_string_to_enum * table, const char * name,
140 int32_t len, unsigned int *value)
141{
142 if (table == NULL) {
143 ALOGE("%s: table is NULL", __func__);
144 return false;
145 }
146
147 if (name == NULL) {
148 ALOGE("null key");
149 return false;
150 }
151
152 for (int i = 0; i < len; i++) {
153 if (!strcmp(table[i].name, name)) {
154 *value = table[i].value;
155 return true;
156 }
157 }
158 return false;
159}
160
Haynes Mathew George98c95622014-06-20 19:14:25 -0700161/*
162 * <audio_platform_info>
163 * <acdb_ids>
164 * <device name="???" acdb_id="???"/>
165 * ...
166 * ...
167 * </acdb_ids>
168 * <backend_names>
169 * <device name="???" backend="???"/>
170 * ...
171 * ...
172 * </backend_names>
173 * <pcm_ids>
174 * <usecase name="???" type="in/out" id="???"/>
175 * ...
176 * ...
177 * </pcm_ids>
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700178 * <config_params>
179 * <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/>
keunhui.park2f7306a2015-07-16 16:48:06 +0900180 * <param key="operator_info" value="tmus;aa;bb;cc"/>
181 * <param key="operator_info" value="sprint;xx;yy;zz"/>
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700182 * ...
183 * ...
184 * </config_params>
185 *
keunhui.park2f7306a2015-07-16 16:48:06 +0900186 * <operator_specific>
187 * <device name="???" operator="???" mixer_path="???" acdb_id="???"/>
188 * ...
189 * ...
190 * </operator_specific>
191 *
Haynes Mathew George98c95622014-06-20 19:14:25 -0700192 * </audio_platform_info>
193 */
194
195static void process_root(const XML_Char **attr __unused)
196{
197}
198
199/* mapping from usecase to pcm dev id */
200static void process_pcm_id(const XML_Char **attr)
201{
202 int index;
203
204 if (strcmp(attr[0], "name") != 0) {
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700205 ALOGE("%s: 'name' not found, no pcm_id set!", __func__);
Haynes Mathew George98c95622014-06-20 19:14:25 -0700206 goto done;
207 }
208
209 index = platform_get_usecase_index((char *)attr[1]);
210 if (index < 0) {
211 ALOGE("%s: usecase %s in %s not found!",
212 __func__, attr[1], PLATFORM_INFO_XML_PATH);
213 goto done;
214 }
215
216 if (strcmp(attr[2], "type") != 0) {
217 ALOGE("%s: usecase type not mentioned", __func__);
218 goto done;
219 }
220
221 int type = -1;
222
223 if (!strcasecmp((char *)attr[3], "in")) {
224 type = 1;
225 } else if (!strcasecmp((char *)attr[3], "out")) {
226 type = 0;
227 } else {
228 ALOGE("%s: type must be IN or OUT", __func__);
229 goto done;
230 }
231
232 if (strcmp(attr[4], "id") != 0) {
233 ALOGE("%s: usecase id not mentioned", __func__);
234 goto done;
235 }
236
237 int id = atoi((char *)attr[5]);
238
239 if (platform_set_usecase_pcm_id(index, type, id) < 0) {
240 ALOGE("%s: usecase %s in %s, type %d id %d was not set!",
241 __func__, attr[1], PLATFORM_INFO_XML_PATH, type, id);
242 goto done;
243 }
244
245done:
246 return;
247}
248
249/* backend to be used for a device */
250static void process_backend_name(const XML_Char **attr)
251{
252 int index;
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700253 char *hw_interface = NULL;
Haynes Mathew George98c95622014-06-20 19:14:25 -0700254
255 if (strcmp(attr[0], "name") != 0) {
256 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
257 goto done;
258 }
259
260 index = platform_get_snd_device_index((char *)attr[1]);
261 if (index < 0) {
262 ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
263 __func__, attr[1], PLATFORM_INFO_XML_PATH);
264 goto done;
265 }
266
267 if (strcmp(attr[2], "backend") != 0) {
268 ALOGE("%s: Device %s in %s has no backed set!",
269 __func__, attr[1], PLATFORM_INFO_XML_PATH);
270 goto done;
271 }
272
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700273 if (attr[4] != NULL) {
274 if (strcmp(attr[4], "interface") != 0) {
275 hw_interface = NULL;
276 } else {
277 hw_interface = (char *)attr[5];
278 }
279 }
280
281 if (platform_set_snd_device_backend(index, attr[3], hw_interface) < 0) {
Haynes Mathew George98c95622014-06-20 19:14:25 -0700282 ALOGE("%s: Device %s in %s, backend %s was not set!",
283 __func__, attr[1], PLATFORM_INFO_XML_PATH, attr[3]);
284 goto done;
285 }
286
287done:
288 return;
289}
290
vivek mehtaa8d7c922016-05-25 14:40:44 -0700291static void process_gain_db_to_level_map(const XML_Char **attr)
292{
293 struct amp_db_and_gain_table tbl_entry;
294
295 if ((strcmp(attr[0], "db") != 0) ||
296 (strcmp(attr[2], "level") != 0)) {
297 ALOGE("%s: invalid attribute passed %s %sexpected amp db level",
298 __func__, attr[0], attr[2]);
299 goto done;
300 }
301
302 tbl_entry.db = atof(attr[1]);
303 tbl_entry.amp = exp(tbl_entry.db * 0.115129f);
304 tbl_entry.level = atoi(attr[3]);
305
vivek mehta40125092017-08-21 18:48:51 -0700306 //custome level should be > 0. Level 0 is fixed for default
307 CHECK(tbl_entry.level > 0);
308
vivek mehtaa8d7c922016-05-25 14:40:44 -0700309 ALOGV("%s: amp [%f] db [%f] level [%d]", __func__,
310 tbl_entry.amp, tbl_entry.db, tbl_entry.level);
311 platform_add_gain_level_mapping(&tbl_entry);
312
313done:
314 return;
315}
316
Haynes Mathew George98c95622014-06-20 19:14:25 -0700317static void process_acdb_id(const XML_Char **attr)
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700318{
319 int index;
320
321 if (strcmp(attr[0], "name") != 0) {
322 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
323 goto done;
324 }
325
326 index = platform_get_snd_device_index((char *)attr[1]);
327 if (index < 0) {
328 ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
329 __func__, attr[1], PLATFORM_INFO_XML_PATH);
330 goto done;
331 }
332
333 if (strcmp(attr[2], "acdb_id") != 0) {
334 ALOGE("%s: Device %s in %s has no acdb_id, no ACDB ID set!",
335 __func__, attr[1], PLATFORM_INFO_XML_PATH);
336 goto done;
337 }
338
Haynes Mathew George98c95622014-06-20 19:14:25 -0700339 if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700340 ALOGE("%s: Device %s in %s, ACDB ID %d was not set!",
341 __func__, attr[1], PLATFORM_INFO_XML_PATH, atoi((char *)attr[3]));
342 goto done;
343 }
344
345done:
346 return;
347}
348
keunhui.park2f7306a2015-07-16 16:48:06 +0900349
350static void process_operator_specific(const XML_Char **attr)
351{
352 snd_device_t snd_device = SND_DEVICE_NONE;
353
354 if (strcmp(attr[0], "name") != 0) {
355 ALOGE("%s: 'name' not found", __func__);
356 goto done;
357 }
358
359 snd_device = platform_get_snd_device_index((char *)attr[1]);
360 if (snd_device < 0) {
361 ALOGE("%s: Device %s in %s not found, no ACDB ID set!",
362 __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH);
363 goto done;
364 }
365
366 if (strcmp(attr[2], "operator") != 0) {
367 ALOGE("%s: 'operator' not found", __func__);
368 goto done;
369 }
370
371 if (strcmp(attr[4], "mixer_path") != 0) {
372 ALOGE("%s: 'mixer_path' not found", __func__);
373 goto done;
374 }
375
376 if (strcmp(attr[6], "acdb_id") != 0) {
377 ALOGE("%s: 'acdb_id' not found", __func__);
378 goto done;
379 }
380
381 platform_add_operator_specific_device(snd_device, (char *)attr[3], (char *)attr[5], atoi((char *)attr[7]));
382
383done:
384 return;
385}
386
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700387/* platform specific configuration key-value pairs */
388static void process_config_params(const XML_Char **attr)
389{
390 if (strcmp(attr[0], "key") != 0) {
391 ALOGE("%s: 'key' not found", __func__);
392 goto done;
393 }
394
395 if (strcmp(attr[2], "value") != 0) {
396 ALOGE("%s: 'value' not found", __func__);
397 goto done;
398 }
399
400 str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]);
vivek mehta0fb11312017-05-15 19:35:32 -0700401 set_parameters(my_data.platform, my_data.kvpairs);
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700402done:
403 return;
404}
405
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800406static void process_app_type(const XML_Char **attr)
407{
408 if (strcmp(attr[0], "uc_type")) {
409 ALOGE("%s: uc_type not found", __func__);
410 goto done;
411 }
412
vivek mehtaa68fea62017-06-08 19:04:02 -0700413 if (strcmp(attr[2], "mode")) {
414 ALOGE("%s: mode not found", __func__);
415 goto done;
416 }
417
418 if (strcmp(attr[4], "bit_width")) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800419 ALOGE("%s: bit_width not found", __func__);
420 goto done;
421 }
422
vivek mehtaa68fea62017-06-08 19:04:02 -0700423 if (strcmp(attr[6], "id")) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800424 ALOGE("%s: id not found", __func__);
425 goto done;
426 }
427
vivek mehtaa68fea62017-06-08 19:04:02 -0700428 if (strcmp(attr[8], "max_rate")) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800429 ALOGE("%s: max rate not found", __func__);
430 goto done;
431 }
432
vivek mehtaa68fea62017-06-08 19:04:02 -0700433 platform_add_app_type(attr[1], attr[3], atoi(attr[5]), atoi(attr[7]),
434 atoi(attr[9]));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800435done:
436 return;
437}
438
jiabin8962a4d2018-03-19 18:21:24 -0700439static void process_microphone_characteristic(const XML_Char **attr) {
440 struct audio_microphone_characteristic_t microphone;
441 uint32_t curIdx = 0;
442
443 if (strcmp(attr[curIdx++], "valid_mask")) {
444 ALOGE("%s: valid_mask not found", __func__);
445 goto done;
446 }
jiabina43dd882018-05-07 10:52:37 -0700447 uint32_t valid_mask = atoi(attr[curIdx++]);
jiabin8962a4d2018-03-19 18:21:24 -0700448
449 if (strcmp(attr[curIdx++], "device_id")) {
450 ALOGE("%s: device_id not found", __func__);
451 goto done;
452 }
453 if (strlen(attr[curIdx]) > AUDIO_MICROPHONE_ID_MAX_LEN) {
454 ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
455 goto done;
456 }
457 strcpy(microphone.device_id, attr[curIdx++]);
458
459 if (strcmp(attr[curIdx++], "type")) {
460 ALOGE("%s: device not found", __func__);
461 goto done;
462 }
463 if (!find_enum_by_string(device_in_types, (char*)attr[curIdx++],
464 ARRAY_SIZE(device_in_types), &microphone.device)) {
465 ALOGE("%s: type %s in %s not found!",
466 __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
467 goto done;
468 }
469
470 if (strcmp(attr[curIdx++], "address")) {
471 ALOGE("%s: address not found", __func__);
472 goto done;
473 }
474 if (strlen(attr[curIdx]) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
475 ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
476 goto done;
477 }
478 strcpy(microphone.address, attr[curIdx++]);
479 if (strlen(microphone.address) == 0) {
480 // If the address is empty, populate the address according to device type.
481 if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
482 strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
483 } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
484 strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
485 }
486 }
487
488 if (strcmp(attr[curIdx++], "location")) {
489 ALOGE("%s: location not found", __func__);
490 goto done;
491 }
492 if (!find_enum_by_string(mic_locations, (char*)attr[curIdx++],
493 AUDIO_MICROPHONE_LOCATION_CNT, &microphone.location)) {
494 ALOGE("%s: location %s in %s not found!",
495 __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
496 goto done;
497 }
498
499 if (strcmp(attr[curIdx++], "group")) {
500 ALOGE("%s: group not found", __func__);
501 goto done;
502 }
503 microphone.group = atoi(attr[curIdx++]);
504
505 if (strcmp(attr[curIdx++], "index_in_the_group")) {
506 ALOGE("%s: index_in_the_group not found", __func__);
507 goto done;
508 }
509 microphone.index_in_the_group = atoi(attr[curIdx++]);
510
511 if (strcmp(attr[curIdx++], "directionality")) {
512 ALOGE("%s: directionality not found", __func__);
513 goto done;
514 }
515 if (!find_enum_by_string(mic_directionalities, (char*)attr[curIdx++],
516 AUDIO_MICROPHONE_DIRECTIONALITY_CNT, &microphone.directionality)) {
517 ALOGE("%s: directionality %s in %s not found!",
518 __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
519 goto done;
520 }
521
522 if (strcmp(attr[curIdx++], "num_frequency_responses")) {
523 ALOGE("%s: num_frequency_responses not found", __func__);
524 goto done;
525 }
526 microphone.num_frequency_responses = atoi(attr[curIdx++]);
527 if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
528 ALOGE("%s: num_frequency_responses is too large", __func__);
529 goto done;
530 }
531 if (microphone.num_frequency_responses > 0) {
532 if (strcmp(attr[curIdx++], "frequencies")) {
533 ALOGE("%s: frequencies not found", __func__);
534 goto done;
535 }
jiabin196df232018-05-03 14:00:20 -0700536 char *token = strtok((char *)attr[curIdx++], " ");
jiabin8962a4d2018-03-19 18:21:24 -0700537 uint32_t num_frequencies = 0;
538 while (token) {
539 microphone.frequency_responses[0][num_frequencies++] = atof(token);
540 if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
541 ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
542 goto done;
543 }
jiabin196df232018-05-03 14:00:20 -0700544 token = strtok(NULL, " ");
jiabin8962a4d2018-03-19 18:21:24 -0700545 }
546
547 if (strcmp(attr[curIdx++], "responses")) {
548 ALOGE("%s: responses not found", __func__);
549 goto done;
550 }
jiabin196df232018-05-03 14:00:20 -0700551 token = strtok((char *)attr[curIdx++], " ");
jiabin8962a4d2018-03-19 18:21:24 -0700552 uint32_t num_responses = 0;
553 while (token) {
554 microphone.frequency_responses[1][num_responses++] = atof(token);
555 if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
556 ALOGE("%s: num %u of response is too large", __func__, num_responses);
557 goto done;
558 }
jiabin196df232018-05-03 14:00:20 -0700559 token = strtok(NULL, " ");
jiabin8962a4d2018-03-19 18:21:24 -0700560 }
561
562 if (num_frequencies != num_responses
563 || num_frequencies != microphone.num_frequency_responses) {
564 ALOGE("%s: num of frequency and response not match: %u, %u, %u",
565 __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
566 goto done;
567 }
568 }
569
jiabina43dd882018-05-07 10:52:37 -0700570 if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY) {
jiabin8962a4d2018-03-19 18:21:24 -0700571 if (strcmp(attr[curIdx++], "sensitivity")) {
572 ALOGE("%s: sensitivity not found", __func__);
573 goto done;
574 }
575 microphone.sensitivity = atof(attr[curIdx++]);
576 } else {
577 microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
578 }
579
jiabina43dd882018-05-07 10:52:37 -0700580 if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL) {
jiabin8962a4d2018-03-19 18:21:24 -0700581 if (strcmp(attr[curIdx++], "max_spl")) {
582 ALOGE("%s: max_spl not found", __func__);
583 goto done;
584 }
585 microphone.max_spl = atof(attr[curIdx++]);
586 } else {
587 microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
588 }
589
jiabina43dd882018-05-07 10:52:37 -0700590 if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL) {
jiabin8962a4d2018-03-19 18:21:24 -0700591 if (strcmp(attr[curIdx++], "min_spl")) {
592 ALOGE("%s: min_spl not found", __func__);
593 goto done;
594 }
595 microphone.min_spl = atof(attr[curIdx++]);
596 } else {
597 microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
598 }
599
jiabina43dd882018-05-07 10:52:37 -0700600 if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION) {
jiabin8962a4d2018-03-19 18:21:24 -0700601 if (strcmp(attr[curIdx++], "orientation")) {
602 ALOGE("%s: orientation not found", __func__);
603 goto done;
604 }
jiabin196df232018-05-03 14:00:20 -0700605 char *token = strtok((char *)attr[curIdx++], " ");
jiabin8962a4d2018-03-19 18:21:24 -0700606 float orientation[3];
607 uint32_t idx = 0;
608 while (token) {
609 orientation[idx++] = atof(token);
610 if (idx > 3) {
611 ALOGE("%s: orientation invalid", __func__);
612 goto done;
613 }
jiabin196df232018-05-03 14:00:20 -0700614 token = strtok(NULL, " ");
jiabin8962a4d2018-03-19 18:21:24 -0700615 }
616 if (idx != 3) {
617 ALOGE("%s: orientation invalid", __func__);
618 goto done;
619 }
620 microphone.orientation.x = orientation[0];
621 microphone.orientation.y = orientation[1];
622 microphone.orientation.z = orientation[2];
623 } else {
624 microphone.orientation.x = 0.0f;
625 microphone.orientation.y = 0.0f;
626 microphone.orientation.z = 0.0f;
627 }
628
jiabina43dd882018-05-07 10:52:37 -0700629 if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION) {
jiabin8962a4d2018-03-19 18:21:24 -0700630 if (strcmp(attr[curIdx++], "geometric_location")) {
631 ALOGE("%s: geometric_location not found", __func__);
632 goto done;
633 }
jiabin196df232018-05-03 14:00:20 -0700634 char *token = strtok((char *)attr[curIdx++], " ");
jiabin8962a4d2018-03-19 18:21:24 -0700635 float geometric_location[3];
636 uint32_t idx = 0;
637 while (token) {
638 geometric_location[idx++] = atof(token);
639 if (idx > 3) {
640 ALOGE("%s: geometric_location invalid", __func__);
641 goto done;
642 }
jiabin196df232018-05-03 14:00:20 -0700643 token = strtok(NULL, " ");
jiabin8962a4d2018-03-19 18:21:24 -0700644 }
645 if (idx != 3) {
646 ALOGE("%s: geometric_location invalid", __func__);
647 goto done;
648 }
649 microphone.geometric_location.x = geometric_location[0];
650 microphone.geometric_location.y = geometric_location[1];
651 microphone.geometric_location.z = geometric_location[2];
652 } else {
653 microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
654 microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
655 microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
656 }
657
658 platform_set_microphone_characteristic(my_data.platform, microphone);
659done:
660 return;
661}
662
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700663static void start_tag(void *userdata __unused, const XML_Char *tag_name,
664 const XML_Char **attr)
665{
666 const XML_Char *attr_name = NULL;
667 const XML_Char *attr_value = NULL;
668 unsigned int i;
669
Haynes Mathew George98c95622014-06-20 19:14:25 -0700670
vivek mehta0fb11312017-05-15 19:35:32 -0700671 if (my_data.do_full_parse) {
672 if (strcmp(tag_name, "acdb_ids") == 0) {
673 section = ACDB;
674 } else if (strcmp(tag_name, "pcm_ids") == 0) {
675 section = PCM_ID;
676 } else if (strcmp(tag_name, "backend_names") == 0) {
677 section = BACKEND_NAME;
678 } else if (strcmp(tag_name, "config_params") == 0) {
679 section = CONFIG_PARAMS;
680 } else if (strcmp(tag_name, "operator_specific") == 0) {
681 section = OPERATOR_SPECIFIC;
682 } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
683 section = GAIN_LEVEL_MAPPING;
684 } else if (strcmp(tag_name, "app_types") == 0) {
685 section = APP_TYPE;
jiabin8962a4d2018-03-19 18:21:24 -0700686 } else if (strcmp(tag_name, "microphone_characteristics") == 0) {
687 section = MICROPHONE_CHARACTERISTIC;
vivek mehta0fb11312017-05-15 19:35:32 -0700688 } else if (strcmp(tag_name, "device") == 0) {
689 if ((section != ACDB) && (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) {
690 ALOGE("device tag only supported for acdb/backend names");
691 return;
692 }
Haynes Mathew George98c95622014-06-20 19:14:25 -0700693
vivek mehta0fb11312017-05-15 19:35:32 -0700694 /* call into process function for the current section */
695 section_process_fn fn = section_table[section];
696 fn(attr);
697 } else if (strcmp(tag_name, "usecase") == 0) {
698 if (section != PCM_ID) {
699 ALOGE("usecase tag only supported with PCM_ID section");
700 return;
701 }
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700702
vivek mehta0fb11312017-05-15 19:35:32 -0700703 section_process_fn fn = section_table[PCM_ID];
704 fn(attr);
705 } else if (strcmp(tag_name, "param") == 0) {
706 if (section != CONFIG_PARAMS) {
707 ALOGE("param tag only supported with CONFIG_PARAMS section");
708 return;
709 }
vivek mehtaa8d7c922016-05-25 14:40:44 -0700710
vivek mehta0fb11312017-05-15 19:35:32 -0700711 section_process_fn fn = section_table[section];
712 fn(attr);
713 } else if (strcmp(tag_name, "gain_level_map") == 0) {
714 if (section != GAIN_LEVEL_MAPPING) {
jiabin8962a4d2018-03-19 18:21:24 -0700715 ALOGE("gain_level_map tag only supported with GAIN_LEVEL_MAPPING section");
vivek mehta0fb11312017-05-15 19:35:32 -0700716 return;
717 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800718
vivek mehta0fb11312017-05-15 19:35:32 -0700719 section_process_fn fn = section_table[GAIN_LEVEL_MAPPING];
720 fn(attr);
721 } else if (!strcmp(tag_name, "app")) {
722 if (section != APP_TYPE) {
723 ALOGE("app tag only valid in section APP_TYPE");
724 return;
725 }
726
727 section_process_fn fn = section_table[APP_TYPE];
728 fn(attr);
jiabin8962a4d2018-03-19 18:21:24 -0700729 } else if (strcmp(tag_name, "microphone") == 0) {
730 if (section != MICROPHONE_CHARACTERISTIC) {
731 ALOGE("microphone tag only supported with MICROPHONE_CHARACTERISTIC section");
732 return;
733 }
734 section_process_fn fn = section_table[MICROPHONE_CHARACTERISTIC];
735 fn(attr);
vivek mehta0fb11312017-05-15 19:35:32 -0700736 }
737 } else {
738 if(strcmp(tag_name, "config_params") == 0) {
739 section = CONFIG_PARAMS;
740 } else if (strcmp(tag_name, "param") == 0) {
741 if (section != CONFIG_PARAMS) {
742 ALOGE("param tag only supported with CONFIG_PARAMS section");
743 return;
744 }
745
746 section_process_fn fn = section_table[section];
747 fn(attr);
748 }
Haynes Mathew George98c95622014-06-20 19:14:25 -0700749 }
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700750
751 return;
752}
753
Haynes Mathew George98c95622014-06-20 19:14:25 -0700754static void end_tag(void *userdata __unused, const XML_Char *tag_name)
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700755{
Haynes Mathew George98c95622014-06-20 19:14:25 -0700756 if (strcmp(tag_name, "acdb_ids") == 0) {
757 section = ROOT;
758 } else if (strcmp(tag_name, "pcm_ids") == 0) {
759 section = ROOT;
760 } else if (strcmp(tag_name, "backend_names") == 0) {
761 section = ROOT;
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700762 } else if (strcmp(tag_name, "config_params") == 0) {
763 section = ROOT;
keunhui.park2f7306a2015-07-16 16:48:06 +0900764 } else if (strcmp(tag_name, "operator_specific") == 0) {
765 section = ROOT;
vivek mehtaa8d7c922016-05-25 14:40:44 -0700766 } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) {
767 section = ROOT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800768 } else if (strcmp(tag_name, "app_types") == 0) {
769 section = ROOT;
jiabin8962a4d2018-03-19 18:21:24 -0700770 } else if (strcmp(tag_name, "microphone_characteristics") == 0) {
771 section = ROOT;
Haynes Mathew George98c95622014-06-20 19:14:25 -0700772 }
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700773}
774
vivek mehta0fb11312017-05-15 19:35:32 -0700775int snd_card_info_init(const char *filename, void *platform, set_parameters_fn fn)
776{
777 set_parameters = fn;
778 my_data.do_full_parse = false;
779 return platform_info_init(filename, platform);
780}
781
vivek mehtade4849c2016-03-03 17:23:38 -0800782int platform_info_init(const char *filename, void *platform)
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700783{
784 XML_Parser parser;
785 FILE *file;
786 int ret = 0;
787 int bytes_read;
788 void *buf;
789 static const uint32_t kBufSize = 1024;
vivek mehtade4849c2016-03-03 17:23:38 -0800790 char platform_info_file_name[MIXER_PATH_MAX_LENGTH]= {0};
Haynes Mathew George98c95622014-06-20 19:14:25 -0700791 section = ROOT;
792
vivek mehtade4849c2016-03-03 17:23:38 -0800793 if (filename == NULL) {
794 strlcpy(platform_info_file_name, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH);
795 } else {
796 strlcpy(platform_info_file_name, filename, MIXER_PATH_MAX_LENGTH);
797 }
798
799 ALOGV("%s: platform info file name is %s", __func__, platform_info_file_name);
800
801 file = fopen(platform_info_file_name, "r");
802
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700803 if (!file) {
804 ALOGD("%s: Failed to open %s, using defaults.",
vivek mehtade4849c2016-03-03 17:23:38 -0800805 __func__, platform_info_file_name);
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700806 ret = -ENODEV;
807 goto done;
808 }
809
810 parser = XML_ParserCreate(NULL);
811 if (!parser) {
812 ALOGE("%s: Failed to create XML parser!", __func__);
813 ret = -ENODEV;
814 goto err_close_file;
815 }
816
Ravi Kumar Alamandac4f57312015-06-26 17:41:02 -0700817 my_data.platform = platform;
818 my_data.kvpairs = str_parms_create();
819
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700820 XML_SetElementHandler(parser, start_tag, end_tag);
821
822 while (1) {
823 buf = XML_GetBuffer(parser, kBufSize);
824 if (buf == NULL) {
825 ALOGE("%s: XML_GetBuffer failed", __func__);
826 ret = -ENOMEM;
827 goto err_free_parser;
828 }
829
830 bytes_read = fread(buf, 1, kBufSize, file);
831 if (bytes_read < 0) {
832 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read);
833 ret = bytes_read;
834 goto err_free_parser;
835 }
836
837 if (XML_ParseBuffer(parser, bytes_read,
838 bytes_read == 0) == XML_STATUS_ERROR) {
839 ALOGE("%s: XML_ParseBuffer failed, for %s",
vivek mehtade4849c2016-03-03 17:23:38 -0800840 __func__, platform_info_file_name);
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700841 ret = -EINVAL;
842 goto err_free_parser;
843 }
844
845 if (bytes_read == 0)
846 break;
847 }
848
vivek mehta0fb11312017-05-15 19:35:32 -0700849 set_parameters = &platform_set_parameters;
850 my_data.do_full_parse = true;
851
Haynes Mathew George5bc18842014-06-16 16:36:20 -0700852err_free_parser:
853 XML_ParserFree(parser);
854err_close_file:
855 fclose(file);
856done:
857 return ret;
858}