1 /* 2 * Copyright (C) 2014 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 "platform_info" 18 #define LOG_NDDEBUG 0 19 20 #include <errno.h> 21 #include <stdio.h> 22 #include <expat.h> 23 #include <log/log.h> 24 #include <audio_hw.h> 25 #include "platform_api.h" 26 #include <platform.h> 27 #include <math.h> 28 #include <pthread.h> 29 30 /* 31 * Mandatory microphone characteristics include: device_id, type, address, location, group, 32 * index_in_the_group, directionality, num_frequency_responses, frequencies and responses. 33 * MANDATORY_MICROPHONE_CHARACTERISTICS should be updated when mandatory microphone 34 * characteristics are changed. 35 */ 36 #define MANDATORY_MICROPHONE_CHARACTERISTICS (1 << 10) - 1 37 38 typedef enum { 39 ROOT, 40 ACDB, 41 MODULE, 42 AEC, 43 NS, 44 PCM_ID, 45 BACKEND_NAME, 46 CONFIG_PARAMS, 47 OPERATOR_SPECIFIC, 48 GAIN_LEVEL_MAPPING, 49 APP_TYPE, 50 MICROPHONE_CHARACTERISTIC, 51 SND_DEVICES, 52 INPUT_SND_DEVICE, 53 INPUT_SND_DEVICE_TO_MIC_MAPPING, 54 SND_DEV, 55 MIC_INFO, 56 ACDB_METAINFO_KEY, 57 EXTERNAL_DEVICE_SPECIFIC, 58 } section_t; 59 60 typedef void (* section_process_fn)(const XML_Char **attr); 61 62 static void process_acdb_id(const XML_Char **attr); 63 static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type); 64 static void process_effect_aec(const XML_Char **attr); 65 static void process_effect_ns(const XML_Char **attr); 66 static void process_pcm_id(const XML_Char **attr); 67 static void process_backend_name(const XML_Char **attr); 68 static void process_config_params(const XML_Char **attr); 69 static void process_root(const XML_Char **attr); 70 static void process_operator_specific(const XML_Char **attr); 71 static void process_gain_db_to_level_map(const XML_Char **attr); 72 static void process_app_type(const XML_Char **attr); 73 static void process_microphone_characteristic(const XML_Char **attr); 74 static void process_snd_dev(const XML_Char **attr); 75 static void process_mic_info(const XML_Char **attr); 76 static void process_acdb_metainfo_key(const XML_Char **attr); 77 static void process_external_dev(const XML_Char **attr); 78 79 static section_process_fn section_table[] = { 80 [ROOT] = process_root, 81 [ACDB] = process_acdb_id, 82 [AEC] = process_effect_aec, 83 [NS] = process_effect_ns, 84 [PCM_ID] = process_pcm_id, 85 [BACKEND_NAME] = process_backend_name, 86 [CONFIG_PARAMS] = process_config_params, 87 [OPERATOR_SPECIFIC] = process_operator_specific, 88 [GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map, 89 [APP_TYPE] = process_app_type, 90 [MICROPHONE_CHARACTERISTIC] = process_microphone_characteristic, 91 [SND_DEV] = process_snd_dev, 92 [MIC_INFO] = process_mic_info, 93 [ACDB_METAINFO_KEY] = process_acdb_metainfo_key, 94 [EXTERNAL_DEVICE_SPECIFIC] = process_external_dev, 95 }; 96 97 static section_t section; 98 99 struct platform_info { 100 pthread_mutex_t lock; 101 bool do_full_parse; 102 void *platform; 103 struct str_parms *kvpairs; 104 set_parameters_fn set_parameters; 105 }; 106 107 static struct platform_info my_data = {PTHREAD_MUTEX_INITIALIZER, 108 true, NULL, NULL, 109 &platform_set_parameters}; 110 111 struct audio_string_to_enum { 112 const char* name; 113 unsigned int value; 114 }; 115 116 static snd_device_t in_snd_device; 117 118 static const struct audio_string_to_enum mic_locations[AUDIO_MICROPHONE_LOCATION_CNT] = { 119 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_UNKNOWN), 120 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY), 121 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE), 122 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_PERIPHERAL), 123 }; 124 125 static const struct audio_string_to_enum mic_directionalities[AUDIO_MICROPHONE_DIRECTIONALITY_CNT] = { 126 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_OMNI), 127 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL), 128 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN), 129 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID), 130 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID), 131 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID), 132 }; 133 134 static const struct audio_string_to_enum mic_channel_mapping[AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT] = { 135 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED), 136 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT), 137 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED), 138 }; 139 140 static const struct audio_string_to_enum device_in_types[] = { 141 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT), 142 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION), 143 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), 144 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), 145 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET), 146 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL), 147 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI), 148 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL), 149 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX), 150 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC), 151 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX), 152 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET), 153 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET), 154 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY), 155 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE), 156 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER), 157 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER), 158 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE), 159 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF), 160 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP), 161 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK), 162 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP), 163 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS), 164 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY), 165 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET), 166 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE), 167 AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT), 168 }; 169 170 static bool find_enum_by_string(const struct audio_string_to_enum * table, const char * name, 171 int32_t len, unsigned int *value) 172 { 173 if (table == NULL) { 174 ALOGE("%s: table is NULL", __func__); 175 return false; 176 } 177 178 if (name == NULL) { 179 ALOGE("null key"); 180 return false; 181 } 182 183 for (int i = 0; i < len; i++) { 184 if (!strcmp(table[i].name, name)) { 185 *value = table[i].value; 186 return true; 187 } 188 } 189 return false; 190 } 191 192 /* 193 * <audio_platform_info> 194 * <acdb_ids> 195 * <device name="???" acdb_id="???"/> 196 * ... 197 * ... 198 * </acdb_ids> 199 * <module_ids> 200 * <device name="???" module_id="???"/> 201 * ... 202 * ... 203 * </module_ids> 204 * <backend_names> 205 * <device name="???" backend="???"/> 206 * ... 207 * ... 208 * </backend_names> 209 * <pcm_ids> 210 * <usecase name="???" type="in/out" id="???"/> 211 * ... 212 * ... 213 * </pcm_ids> 214 * <config_params> 215 * <param key="snd_card_name" value="msm8994-tomtom-mtp-snd-card"/> 216 * <param key="operator_info" value="tmus;aa;bb;cc"/> 217 * <param key="operator_info" value="sprint;xx;yy;zz"/> 218 * ... 219 * ... 220 * </config_params> 221 * 222 * <operator_specific> 223 * <device name="???" operator="???" mixer_path="???" acdb_id="???"/> 224 * ... 225 * ... 226 * </operator_specific> 227 * 228 * </audio_platform_info> 229 */ 230 231 static void process_root(const XML_Char **attr __unused) 232 { 233 } 234 235 static void process_audio_effect(const XML_Char **attr, effect_type_t effect_type) 236 { 237 int index; 238 struct audio_effect_config effect_config; 239 240 if (strncmp(attr[0], "name", strlen("name")) != 0) { 241 ALOGE("%s: 'name' not found, no MODULE ID set!", __func__); 242 goto done; 243 } 244 245 index = platform_get_snd_device_index((char *)attr[1]); 246 if (index < 0) { 247 ALOGE("%s: Device %s in platform info xml not found, no MODULE ID set!", 248 __func__, attr[1]); 249 goto done; 250 } 251 252 if (strncmp(attr[2], "module_id", strlen("module_id")) != 0) { 253 ALOGE("%s: Device %s in platform info xml has no module_id, no MODULE ID set!", 254 __func__, attr[2]); 255 goto done; 256 } 257 258 if (strncmp(attr[4], "instance_id", strlen("instance_id")) != 0) { 259 ALOGE("%s: Device %s in platform info xml has no instance_id, no INSTANCE ID set!", 260 __func__, attr[4]); 261 goto done; 262 } 263 264 if (strncmp(attr[6], "param_id", strlen("param_id")) != 0) { 265 ALOGE("%s: Device %s in platform info xml has no param_id, no PARAM ID set!", 266 __func__, attr[6]); 267 goto done; 268 } 269 270 if (strncmp(attr[8], "param_value", strlen("param_value")) != 0) { 271 ALOGE("%s: Device %s in platform info xml has no param_value, no PARAM VALUE set!", 272 __func__, attr[8]); 273 goto done; 274 } 275 276 effect_config = (struct audio_effect_config){strtol((char *)attr[3], NULL, 0), 277 strtol((char *)attr[5], NULL, 0), 278 strtol((char *)attr[7], NULL, 0), 279 strtol((char *)attr[9], NULL, 0)}; 280 281 282 if (platform_set_effect_config_data(index, effect_config, effect_type) < 0) { 283 ALOGE("%s: Effect = %d Device %s, MODULE/INSTANCE/PARAM ID %u %u %u %u was not set!", 284 __func__, effect_type, attr[1], effect_config.module_id, 285 effect_config.instance_id, effect_config.param_id, 286 effect_config.param_value); 287 goto done; 288 } 289 290 done: 291 return; 292 } 293 294 static void process_effect_aec(const XML_Char **attr) 295 { 296 process_audio_effect(attr, EFFECT_AEC); 297 return; 298 } 299 300 static void process_effect_ns(const XML_Char **attr) 301 { 302 process_audio_effect(attr, EFFECT_NS); 303 return; 304 } 305 306 /* mapping from usecase to pcm dev id */ 307 static void process_pcm_id(const XML_Char **attr) 308 { 309 int index; 310 311 if (strcmp(attr[0], "name") != 0) { 312 ALOGE("%s: 'name' not found, no pcm_id set!", __func__); 313 goto done; 314 } 315 316 index = platform_get_usecase_index((char *)attr[1]); 317 if (index < 0) { 318 ALOGE("%s: usecase %s in %s not found!", 319 __func__, attr[1], PLATFORM_INFO_XML_PATH); 320 goto done; 321 } 322 323 if (strcmp(attr[2], "type") != 0) { 324 ALOGE("%s: usecase type not mentioned", __func__); 325 goto done; 326 } 327 328 int type = -1; 329 330 if (!strcasecmp((char *)attr[3], "in")) { 331 type = 1; 332 } else if (!strcasecmp((char *)attr[3], "out")) { 333 type = 0; 334 } else { 335 ALOGE("%s: type must be IN or OUT", __func__); 336 goto done; 337 } 338 339 if (strcmp(attr[4], "id") != 0) { 340 ALOGE("%s: usecase id not mentioned", __func__); 341 goto done; 342 } 343 344 int id = atoi((char *)attr[5]); 345 346 if (platform_set_usecase_pcm_id(index, type, id) < 0) { 347 ALOGE("%s: usecase %s in %s, type %d id %d was not set!", 348 __func__, attr[1], PLATFORM_INFO_XML_PATH, type, id); 349 goto done; 350 } 351 352 done: 353 return; 354 } 355 356 /* backend to be used for a device */ 357 static void process_backend_name(const XML_Char **attr) 358 { 359 int index; 360 char *hw_interface = NULL; 361 362 if (strcmp(attr[0], "name") != 0) { 363 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__); 364 goto done; 365 } 366 367 index = platform_get_snd_device_index((char *)attr[1]); 368 if (index < 0) { 369 ALOGE("%s: Device %s in %s not found, no ACDB ID set!", 370 __func__, attr[1], PLATFORM_INFO_XML_PATH); 371 goto done; 372 } 373 374 if (strcmp(attr[2], "backend") != 0) { 375 ALOGE("%s: Device %s in %s has no backed set!", 376 __func__, attr[1], PLATFORM_INFO_XML_PATH); 377 goto done; 378 } 379 380 if (attr[4] != NULL) { 381 if (strcmp(attr[4], "interface") != 0) { 382 hw_interface = NULL; 383 } else { 384 hw_interface = (char *)attr[5]; 385 } 386 } 387 388 if (platform_set_snd_device_backend(index, attr[3], hw_interface) < 0) { 389 ALOGE("%s: Device %s in %s, backend %s was not set!", 390 __func__, attr[1], PLATFORM_INFO_XML_PATH, attr[3]); 391 goto done; 392 } 393 394 done: 395 return; 396 } 397 398 static void process_gain_db_to_level_map(const XML_Char **attr) 399 { 400 struct amp_db_and_gain_table tbl_entry; 401 402 if ((strcmp(attr[0], "db") != 0) || 403 (strcmp(attr[2], "level") != 0)) { 404 ALOGE("%s: invalid attribute passed %s %sexpected amp db level", 405 __func__, attr[0], attr[2]); 406 goto done; 407 } 408 409 tbl_entry.db = atof(attr[1]); 410 tbl_entry.amp = exp(tbl_entry.db * 0.115129f); 411 tbl_entry.level = atoi(attr[3]); 412 413 //custome level should be > 0. Level 0 is fixed for default 414 CHECK(tbl_entry.level > 0); 415 416 ALOGV("%s: amp [%f] db [%f] level [%d]", __func__, 417 tbl_entry.amp, tbl_entry.db, tbl_entry.level); 418 platform_add_gain_level_mapping(&tbl_entry); 419 420 done: 421 return; 422 } 423 424 static void process_acdb_id(const XML_Char **attr) 425 { 426 int index; 427 428 if (strcmp(attr[0], "name") != 0) { 429 ALOGE("%s: 'name' not found, no ACDB ID set!", __func__); 430 goto done; 431 } 432 433 index = platform_get_snd_device_index((char *)attr[1]); 434 if (index < 0) { 435 ALOGE("%s: Device %s in %s not found, no ACDB ID set!", 436 __func__, attr[1], PLATFORM_INFO_XML_PATH); 437 goto done; 438 } 439 440 if (strcmp(attr[2], "acdb_id") != 0) { 441 ALOGE("%s: Device %s in %s has no acdb_id, no ACDB ID set!", 442 __func__, attr[1], PLATFORM_INFO_XML_PATH); 443 goto done; 444 } 445 446 if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) { 447 ALOGE("%s: Device %s in %s, ACDB ID %d was not set!", 448 __func__, attr[1], PLATFORM_INFO_XML_PATH, atoi((char *)attr[3])); 449 goto done; 450 } 451 452 done: 453 return; 454 } 455 456 457 static void process_operator_specific(const XML_Char **attr) 458 { 459 snd_device_t snd_device = SND_DEVICE_NONE; 460 461 if (strcmp(attr[0], "name") != 0) { 462 ALOGE("%s: 'name' not found", __func__); 463 goto done; 464 } 465 466 snd_device = platform_get_snd_device_index((char *)attr[1]); 467 if (snd_device < 0) { 468 ALOGE("%s: Device %s in %s not found, no ACDB ID set!", 469 __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH); 470 goto done; 471 } 472 473 if (strcmp(attr[2], "operator") != 0) { 474 ALOGE("%s: 'operator' not found", __func__); 475 goto done; 476 } 477 478 if (strcmp(attr[4], "mixer_path") != 0) { 479 ALOGE("%s: 'mixer_path' not found", __func__); 480 goto done; 481 } 482 483 if (strcmp(attr[6], "acdb_id") != 0) { 484 ALOGE("%s: 'acdb_id' not found", __func__); 485 goto done; 486 } 487 488 platform_add_operator_specific_device(snd_device, (char *)attr[3], (char *)attr[5], atoi((char *)attr[7])); 489 490 done: 491 return; 492 } 493 494 static void process_external_dev(const XML_Char **attr) 495 { 496 snd_device_t snd_device = SND_DEVICE_NONE; 497 498 if (strcmp(attr[0], "name") != 0) { 499 ALOGE("%s: 'name' not found", __func__); 500 goto done; 501 } 502 503 snd_device = platform_get_snd_device_index((char *)attr[1]); 504 if (snd_device < 0) { 505 ALOGE("%s: Device %s in %s not found, no ACDB ID set!", 506 __func__, (char *)attr[3], PLATFORM_INFO_XML_PATH); 507 goto done; 508 } 509 510 if (strcmp(attr[2], "usbid") != 0) { 511 ALOGE("%s: 'usbid' not found", __func__); 512 goto done; 513 } 514 515 if (strcmp(attr[4], "acdb_id") != 0) { 516 ALOGE("%s: 'acdb_id' not found", __func__); 517 goto done; 518 } 519 520 platform_add_external_specific_device(snd_device, (char *)attr[3], atoi((char *)attr[5])); 521 522 done: 523 return; 524 } 525 526 /* platform specific configuration key-value pairs */ 527 static void process_config_params(const XML_Char **attr) 528 { 529 if (strcmp(attr[0], "key") != 0) { 530 ALOGE("%s: 'key' not found", __func__); 531 goto done; 532 } 533 534 if (strcmp(attr[2], "value") != 0) { 535 ALOGE("%s: 'value' not found", __func__); 536 goto done; 537 } 538 539 str_parms_add_str(my_data.kvpairs, (char*)attr[1], (char*)attr[3]); 540 my_data.set_parameters(my_data.platform, my_data.kvpairs); 541 done: 542 return; 543 } 544 545 static void process_app_type(const XML_Char **attr) 546 { 547 if (strcmp(attr[0], "uc_type")) { 548 ALOGE("%s: uc_type not found", __func__); 549 goto done; 550 } 551 552 if (strcmp(attr[2], "mode")) { 553 ALOGE("%s: mode not found", __func__); 554 goto done; 555 } 556 557 if (strcmp(attr[4], "bit_width")) { 558 ALOGE("%s: bit_width not found", __func__); 559 goto done; 560 } 561 562 if (strcmp(attr[6], "id")) { 563 ALOGE("%s: id not found", __func__); 564 goto done; 565 } 566 567 if (strcmp(attr[8], "max_rate")) { 568 ALOGE("%s: max rate not found", __func__); 569 goto done; 570 } 571 572 platform_add_app_type(attr[1], attr[3], atoi(attr[5]), atoi(attr[7]), 573 atoi(attr[9])); 574 done: 575 return; 576 } 577 578 static void process_microphone_characteristic(const XML_Char **attr) { 579 struct audio_microphone_characteristic_t microphone; 580 uint32_t index = 0; 581 uint32_t found_mandatory_characteristics = 0; 582 uint32_t num_frequencies = 0; 583 uint32_t num_responses = 0; 584 microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN; 585 microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN; 586 microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN; 587 microphone.orientation.x = 0.0f; 588 microphone.orientation.y = 0.0f; 589 microphone.orientation.z = 0.0f; 590 microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN; 591 microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN; 592 microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN; 593 594 while (attr[index] != NULL) { 595 const char *attribute = attr[index++]; 596 char value[strlen(attr[index]) + 1]; 597 strcpy(value, attr[index++]); 598 if (strcmp(attribute, "device_id") == 0) { 599 if (strlen(value) > AUDIO_MICROPHONE_ID_MAX_LEN) { 600 ALOGE("%s: device_id %s is too long", __func__, value); 601 goto done; 602 } 603 strcpy(microphone.device_id, value); 604 found_mandatory_characteristics |= 1; 605 } else if (strcmp(attribute, "type") == 0) { 606 if (!find_enum_by_string(device_in_types, value, 607 ARRAY_SIZE(device_in_types), µphone.device)) { 608 ALOGE("%s: type %s in %s not found!", 609 __func__, value, PLATFORM_INFO_XML_PATH); 610 goto done; 611 } 612 found_mandatory_characteristics |= (1 << 1); 613 } else if (strcmp(attribute, "address") == 0) { 614 if (strlen(value) > AUDIO_DEVICE_MAX_ADDRESS_LEN) { 615 ALOGE("%s, address %s is too long", __func__, value); 616 goto done; 617 } 618 strcpy(microphone.address, value); 619 if (strlen(microphone.address) == 0) { 620 // If the address is empty, populate the address according to device type. 621 if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) { 622 strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS); 623 } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) { 624 strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS); 625 } 626 } 627 found_mandatory_characteristics |= (1 << 2); 628 } else if (strcmp(attribute, "location") == 0) { 629 if (!find_enum_by_string(mic_locations, value, 630 AUDIO_MICROPHONE_LOCATION_CNT, µphone.location)) { 631 ALOGE("%s: location %s in %s not found!", 632 __func__, value, PLATFORM_INFO_XML_PATH); 633 goto done; 634 } 635 found_mandatory_characteristics |= (1 << 3); 636 } else if (strcmp(attribute, "group") == 0) { 637 microphone.group = atoi(value); 638 found_mandatory_characteristics |= (1 << 4); 639 } else if (strcmp(attribute, "index_in_the_group") == 0) { 640 microphone.index_in_the_group = atoi(value); 641 found_mandatory_characteristics |= (1 << 5); 642 } else if (strcmp(attribute, "directionality") == 0) { 643 if (!find_enum_by_string(mic_directionalities, value, 644 AUDIO_MICROPHONE_DIRECTIONALITY_CNT, µphone.directionality)) { 645 ALOGE("%s: directionality %s in %s not found!", 646 __func__, attr[index], PLATFORM_INFO_XML_PATH); 647 goto done; 648 } 649 found_mandatory_characteristics |= (1 << 6); 650 } else if (strcmp(attribute, "num_frequency_responses") == 0) { 651 microphone.num_frequency_responses = atoi(value); 652 if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) { 653 ALOGE("%s: num_frequency_responses is too large", __func__); 654 goto done; 655 } 656 found_mandatory_characteristics |= (1 << 7); 657 } else if (strcmp(attribute, "frequencies") == 0) { 658 char *token = strtok(value, " "); 659 while (token) { 660 microphone.frequency_responses[0][num_frequencies++] = atof(token); 661 if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) { 662 ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies); 663 goto done; 664 } 665 token = strtok(NULL, " "); 666 } 667 found_mandatory_characteristics |= (1 << 8); 668 } else if (strcmp(attribute, "responses") == 0) { 669 char *token = strtok(value, " "); 670 while (token) { 671 microphone.frequency_responses[1][num_responses++] = atof(token); 672 if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) { 673 ALOGE("%s: num %u of response is too large", __func__, num_responses); 674 goto done; 675 } 676 token = strtok(NULL, " "); 677 } 678 found_mandatory_characteristics |= (1 << 9); 679 } else if (strcmp(attribute, "sensitivity") == 0) { 680 microphone.sensitivity = atof(value); 681 } else if (strcmp(attribute, "max_spl") == 0) { 682 microphone.max_spl = atof(value); 683 } else if (strcmp(attribute, "min_spl") == 0) { 684 microphone.min_spl = atof(value); 685 } else if (strcmp(attribute, "orientation") == 0) { 686 char *token = strtok(value, " "); 687 float orientation[3]; 688 uint32_t idx = 0; 689 while (token) { 690 orientation[idx++] = atof(token); 691 if (idx > 3) { 692 ALOGE("%s: orientation invalid", __func__); 693 goto done; 694 } 695 token = strtok(NULL, " "); 696 } 697 if (idx != 3) { 698 ALOGE("%s: orientation invalid", __func__); 699 goto done; 700 } 701 microphone.orientation.x = orientation[0]; 702 microphone.orientation.y = orientation[1]; 703 microphone.orientation.z = orientation[2]; 704 } else if (strcmp(attribute, "geometric_location") == 0) { 705 char *token = strtok(value, " "); 706 float geometric_location[3]; 707 uint32_t idx = 0; 708 while (token) { 709 geometric_location[idx++] = atof(token); 710 if (idx > 3) { 711 ALOGE("%s: geometric_location invalid", __func__); 712 goto done; 713 } 714 token = strtok(NULL, " "); 715 } 716 if (idx != 3) { 717 ALOGE("%s: geometric_location invalid", __func__); 718 goto done; 719 } 720 microphone.geometric_location.x = geometric_location[0]; 721 microphone.geometric_location.y = geometric_location[1]; 722 microphone.geometric_location.z = geometric_location[2]; 723 } else { 724 ALOGW("%s: unknown attribute of microphone characteristics: %s", 725 __func__, attribute); 726 } 727 } 728 729 if (num_frequencies != num_responses 730 || num_frequencies != microphone.num_frequency_responses) { 731 ALOGE("%s: num of frequency and response not match: %u, %u, %u", 732 __func__, num_frequencies, num_responses, microphone.num_frequency_responses); 733 goto done; 734 } 735 736 if (found_mandatory_characteristics != MANDATORY_MICROPHONE_CHARACTERISTICS) { 737 ALOGE("%s: some of mandatory microphone characteriscts are missed: %u", 738 __func__, found_mandatory_characteristics); 739 } 740 741 platform_set_microphone_characteristic(my_data.platform, microphone); 742 done: 743 return; 744 } 745 746 static void process_snd_dev(const XML_Char **attr) 747 { 748 uint32_t curIdx = 0; 749 in_snd_device = SND_DEVICE_NONE; 750 751 if (strcmp(attr[curIdx++], "in_snd_device")) { 752 ALOGE("%s: snd_device not found", __func__); 753 return; 754 } 755 in_snd_device = platform_get_snd_device_index((char *)attr[curIdx++]); 756 if (in_snd_device < SND_DEVICE_IN_BEGIN || 757 in_snd_device >= SND_DEVICE_IN_END) { 758 ALOGE("%s: Sound device not valid", __func__); 759 in_snd_device = SND_DEVICE_NONE; 760 } 761 762 return; 763 } 764 765 static void process_mic_info(const XML_Char **attr) 766 { 767 uint32_t curIdx = 0; 768 struct mic_info microphone; 769 770 memset(µphone.channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED, 771 sizeof(microphone.channel_mapping)); 772 773 if (strcmp(attr[curIdx++], "mic_device_id")) { 774 ALOGE("%s: mic_device_id not found", __func__); 775 goto on_error; 776 } 777 strlcpy(microphone.device_id, 778 (char *)attr[curIdx++], AUDIO_MICROPHONE_ID_MAX_LEN); 779 780 if (strcmp(attr[curIdx++], "channel_mapping")) { 781 ALOGE("%s: channel_mapping not found", __func__); 782 goto on_error; 783 } 784 const char *token = strtok((char *)attr[curIdx++], " "); 785 uint32_t idx = 0; 786 while (token) { 787 if (!find_enum_by_string(mic_channel_mapping, token, 788 AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT, 789 µphone.channel_mapping[idx++])) { 790 ALOGE("%s: channel_mapping %s in %s not found!", 791 __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH); 792 goto on_error; 793 } 794 token = strtok(NULL, " "); 795 } 796 microphone.channel_count = idx; 797 798 platform_set_microphone_map(my_data.platform, in_snd_device, 799 µphone); 800 return; 801 on_error: 802 in_snd_device = SND_DEVICE_NONE; 803 return; 804 } 805 806 /* process acdb meta info key value */ 807 static void process_acdb_metainfo_key(const XML_Char **attr) 808 { 809 if (strcmp(attr[0], "name") != 0) { 810 ALOGE("%s: 'name' not found", __func__); 811 goto done; 812 } 813 if (strcmp(attr[2], "value") != 0) { 814 ALOGE("%s: 'value' not found", __func__); 815 goto done; 816 } 817 818 int key = atoi((char *)attr[3]); 819 if (platform_set_acdb_metainfo_key(my_data.platform, 820 (char*)attr[1], key) < 0) { 821 ALOGE("%s: key %d was not set!", __func__, key); 822 } 823 824 done: 825 return; 826 } 827 828 static void start_tag(void *userdata __unused, const XML_Char *tag_name, 829 const XML_Char **attr) 830 { 831 const XML_Char *attr_name = NULL; 832 const XML_Char *attr_value = NULL; 833 unsigned int i; 834 835 836 if (my_data.do_full_parse) { 837 if (strcmp(tag_name, "acdb_ids") == 0) { 838 section = ACDB; 839 } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) { 840 section = MODULE; 841 } else if (strcmp(tag_name, "pcm_ids") == 0) { 842 section = PCM_ID; 843 } else if (strcmp(tag_name, "backend_names") == 0) { 844 section = BACKEND_NAME; 845 } else if (strcmp(tag_name, "config_params") == 0) { 846 section = CONFIG_PARAMS; 847 } else if (strcmp(tag_name, "operator_specific") == 0) { 848 section = OPERATOR_SPECIFIC; 849 } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) { 850 section = GAIN_LEVEL_MAPPING; 851 } else if (strcmp(tag_name, "app_types") == 0) { 852 section = APP_TYPE; 853 } else if (strcmp(tag_name, "microphone_characteristics") == 0) { 854 section = MICROPHONE_CHARACTERISTIC; 855 } else if (strcmp(tag_name, "snd_devices") == 0) { 856 section = SND_DEVICES; 857 } else if(strcmp(tag_name, "acdb_metainfo_key") == 0) { 858 section = ACDB_METAINFO_KEY; 859 } else if (strcmp(tag_name, "device") == 0) { 860 if ((section != ACDB) && (section != AEC) && (section != NS) && 861 (section != BACKEND_NAME) && (section != OPERATOR_SPECIFIC)) { 862 ALOGE("device tag only supported for acdb/backend/aec/ns/operator_specific names"); 863 return; 864 } 865 866 /* call into process function for the current section */ 867 section_process_fn fn = section_table[section]; 868 fn(attr); 869 } else if (strcmp(tag_name, "usecase") == 0) { 870 if (section != PCM_ID) { 871 ALOGE("usecase tag only supported with PCM_ID section"); 872 return; 873 } 874 875 section_process_fn fn = section_table[PCM_ID]; 876 fn(attr); 877 } else if (strcmp(tag_name, "param") == 0) { 878 if ((section != CONFIG_PARAMS) && (section != ACDB_METAINFO_KEY)) { 879 ALOGE("param tag only supported with CONFIG_PARAMS section"); 880 return; 881 } 882 883 section_process_fn fn = section_table[section]; 884 fn(attr); 885 } else if (strcmp(tag_name, "gain_level_map") == 0) { 886 if (section != GAIN_LEVEL_MAPPING) { 887 ALOGE("gain_level_map tag only supported with GAIN_LEVEL_MAPPING section"); 888 return; 889 } 890 891 section_process_fn fn = section_table[GAIN_LEVEL_MAPPING]; 892 fn(attr); 893 } else if (!strcmp(tag_name, "app")) { 894 if (section != APP_TYPE) { 895 ALOGE("app tag only valid in section APP_TYPE"); 896 return; 897 } 898 899 section_process_fn fn = section_table[APP_TYPE]; 900 fn(attr); 901 } else if (strcmp(tag_name, "microphone") == 0) { 902 if (section != MICROPHONE_CHARACTERISTIC) { 903 ALOGE("microphone tag only supported with MICROPHONE_CHARACTERISTIC section"); 904 return; 905 } 906 section_process_fn fn = section_table[MICROPHONE_CHARACTERISTIC]; 907 fn(attr); 908 } else if (strcmp(tag_name, "input_snd_device") == 0) { 909 if (section != SND_DEVICES) { 910 ALOGE("input_snd_device tag only supported with SND_DEVICES section"); 911 return; 912 } 913 section = INPUT_SND_DEVICE; 914 } else if (strcmp(tag_name, "input_snd_device_mic_mapping") == 0) { 915 if (section != INPUT_SND_DEVICE) { 916 ALOGE("input_snd_device_mic_mapping tag only supported with INPUT_SND_DEVICE section"); 917 return; 918 } 919 section = INPUT_SND_DEVICE_TO_MIC_MAPPING; 920 } else if (strcmp(tag_name, "snd_dev") == 0) { 921 if (section != INPUT_SND_DEVICE_TO_MIC_MAPPING) { 922 ALOGE("snd_dev tag only supported with INPUT_SND_DEVICE_TO_MIC_MAPPING section"); 923 return; 924 } 925 section_process_fn fn = section_table[SND_DEV]; 926 fn(attr); 927 } else if (strcmp(tag_name, "mic_info") == 0) { 928 if (section != INPUT_SND_DEVICE_TO_MIC_MAPPING) { 929 ALOGE("mic_info tag only supported with INPUT_SND_DEVICE_TO_MIC_MAPPING section"); 930 return; 931 } 932 if (in_snd_device == SND_DEVICE_NONE) { 933 ALOGE("%s: Error in previous tags, do not process mic info", __func__); 934 return; 935 } 936 section_process_fn fn = section_table[MIC_INFO]; 937 fn(attr); 938 } else if (strcmp(tag_name, "external_specific_dev") == 0) { 939 section = EXTERNAL_DEVICE_SPECIFIC; 940 } else if (strcmp(tag_name, "ext_device") == 0) { 941 section_process_fn fn = section_table[section]; 942 fn(attr); 943 } 944 else if (strncmp(tag_name, "aec", strlen("aec")) == 0) { 945 if (section != MODULE) { 946 ALOGE("aec tag only supported with MODULE section"); 947 return; 948 } 949 section = AEC; 950 } 951 else if (strncmp(tag_name, "ns", strlen("ns")) == 0) { 952 if (section != MODULE) { 953 ALOGE("ns tag only supported with MODULE section"); 954 return; 955 } 956 section = NS; 957 } 958 } else { 959 if(strcmp(tag_name, "config_params") == 0) { 960 section = CONFIG_PARAMS; 961 } else if (strcmp(tag_name, "param") == 0) { 962 if (section != CONFIG_PARAMS) { 963 ALOGE("param tag only supported with CONFIG_PARAMS section"); 964 return; 965 } 966 967 section_process_fn fn = section_table[section]; 968 fn(attr); 969 } 970 } 971 972 return; 973 } 974 975 static void end_tag(void *userdata __unused, const XML_Char *tag_name) 976 { 977 if (strcmp(tag_name, "acdb_ids") == 0) { 978 section = ROOT; 979 } else if (strncmp(tag_name, "module_ids", strlen("module_ids")) == 0) { 980 section = ROOT; 981 } else if (strncmp(tag_name, "aec", strlen("aec")) == 0) { 982 section = MODULE; 983 } else if (strncmp(tag_name, "ns", strlen("ns")) == 0) { 984 section = MODULE; 985 } else if (strcmp(tag_name, "pcm_ids") == 0) { 986 section = ROOT; 987 } else if (strcmp(tag_name, "backend_names") == 0) { 988 section = ROOT; 989 } else if (strcmp(tag_name, "config_params") == 0) { 990 section = ROOT; 991 } else if (strcmp(tag_name, "operator_specific") == 0) { 992 section = ROOT; 993 } else if (strcmp(tag_name, "gain_db_to_level_mapping") == 0) { 994 section = ROOT; 995 } else if (strcmp(tag_name, "app_types") == 0) { 996 section = ROOT; 997 } else if (strcmp(tag_name, "microphone_characteristics") == 0) { 998 section = ROOT; 999 } else if (strcmp(tag_name, "snd_devices") == 0) { 1000 section = ROOT; 1001 } else if (strcmp(tag_name, "external_specific_dev") == 0) { 1002 section = ROOT; 1003 } else if (strcmp(tag_name, "input_snd_device") == 0) { 1004 section = SND_DEVICES; 1005 } else if (strcmp(tag_name, "input_snd_device_mic_mapping") == 0) { 1006 section = INPUT_SND_DEVICE; 1007 } else if (strcmp(tag_name, "acdb_metainfo_key") == 0) { 1008 section = ROOT; 1009 } 1010 } 1011 1012 int platform_info_init(const char *filename, void *platform, 1013 bool do_full_parse, set_parameters_fn fn) 1014 { 1015 XML_Parser parser; 1016 FILE *file; 1017 int ret = 0; 1018 int bytes_read; 1019 void *buf; 1020 static const uint32_t kBufSize = 1024; 1021 char platform_info_file_name[MIXER_PATH_MAX_LENGTH]= {0}; 1022 1023 if (filename == NULL) { 1024 strlcpy(platform_info_file_name, PLATFORM_INFO_XML_PATH, MIXER_PATH_MAX_LENGTH); 1025 } else { 1026 strlcpy(platform_info_file_name, filename, MIXER_PATH_MAX_LENGTH); 1027 } 1028 1029 ALOGV("%s: platform info file name is %s", __func__, platform_info_file_name); 1030 1031 file = fopen(platform_info_file_name, "r"); 1032 1033 if (!file) { 1034 ALOGD("%s: Failed to open %s, using defaults.", 1035 __func__, platform_info_file_name); 1036 ret = -ENODEV; 1037 goto done; 1038 } 1039 1040 parser = XML_ParserCreate(NULL); 1041 if (!parser) { 1042 ALOGE("%s: Failed to create XML parser!", __func__); 1043 ret = -ENODEV; 1044 goto err_close_file; 1045 } 1046 1047 pthread_mutex_lock(&my_data.lock); 1048 section = ROOT; 1049 my_data.do_full_parse = do_full_parse; 1050 my_data.platform = platform; 1051 my_data.kvpairs = str_parms_create(); 1052 my_data.set_parameters = fn; 1053 1054 XML_SetElementHandler(parser, start_tag, end_tag); 1055 1056 while (1) { 1057 buf = XML_GetBuffer(parser, kBufSize); 1058 if (buf == NULL) { 1059 ALOGE("%s: XML_GetBuffer failed", __func__); 1060 ret = -ENOMEM; 1061 goto err_free_parser; 1062 } 1063 1064 bytes_read = fread(buf, 1, kBufSize, file); 1065 if (bytes_read < 0) { 1066 ALOGE("%s: fread failed, bytes read = %d", __func__, bytes_read); 1067 ret = bytes_read; 1068 goto err_free_parser; 1069 } 1070 1071 if (XML_ParseBuffer(parser, bytes_read, 1072 bytes_read == 0) == XML_STATUS_ERROR) { 1073 ALOGE("%s: XML_ParseBuffer failed, for %s", 1074 __func__, platform_info_file_name); 1075 ret = -EINVAL; 1076 goto err_free_parser; 1077 } 1078 1079 if (bytes_read == 0) 1080 break; 1081 } 1082 1083 err_free_parser: 1084 if (my_data.kvpairs != NULL) { 1085 str_parms_destroy(my_data.kvpairs); 1086 my_data.kvpairs = NULL; 1087 } 1088 pthread_mutex_unlock(&my_data.lock); 1089 XML_ParserFree(parser); 1090 err_close_file: 1091 fclose(file); 1092 done: 1093 return ret; 1094 } 1095