1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * Inspired by TinyHW, written by Mark Brown at Wolfson Micro 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #define LOG_TAG "audio_route" 19 /*#define LOG_NDEBUG 0*/ 20 21 #include <errno.h> 22 #include <expat.h> 23 #include <stdbool.h> 24 #include <stdio.h> 25 #include <string.h> 26 27 #include <cutils/log.h> 28 29 #include <tinyalsa/asoundlib.h> 30 31 #define BUF_SIZE 1024 32 #define MIXER_XML_PATH "/system/etc/mixer_paths.xml" 33 #define INITIAL_MIXER_PATH_SIZE 8 34 35 struct mixer_state { 36 struct mixer_ctl *ctl; 37 unsigned int num_values; 38 int *old_value; 39 int *new_value; 40 int *reset_value; 41 }; 42 43 struct mixer_setting { 44 unsigned int ctl_index; 45 unsigned int num_values; 46 int *value; 47 }; 48 49 struct mixer_value { 50 unsigned int ctl_index; 51 int index; 52 int value; 53 }; 54 55 struct mixer_path { 56 char *name; 57 unsigned int size; 58 unsigned int length; 59 struct mixer_setting *setting; 60 }; 61 62 struct audio_route { 63 struct mixer *mixer; 64 unsigned int num_mixer_ctls; 65 struct mixer_state *mixer_state; 66 67 unsigned int mixer_path_size; 68 unsigned int num_mixer_paths; 69 struct mixer_path *mixer_path; 70 }; 71 72 struct config_parse_state { 73 struct audio_route *ar; 74 struct mixer_path *path; 75 int level; 76 }; 77 78 /* path functions */ 79 80 bool is_supported_ctl_type(enum mixer_ctl_type type) 81 { 82 switch (type) { 83 case MIXER_CTL_TYPE_BOOL: 84 case MIXER_CTL_TYPE_INT: 85 case MIXER_CTL_TYPE_ENUM: 86 return true; 87 default: 88 return false; 89 } 90 } 91 92 static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar, 93 unsigned int ctl_index) 94 { 95 return ar->mixer_state[ctl_index].ctl; 96 } 97 98 static void path_print(struct audio_route *ar, struct mixer_path *path) 99 { 100 unsigned int i; 101 unsigned int j; 102 103 ALOGE("Path: %s, length: %d", path->name, path->length); 104 for (i = 0; i < path->length; i++) { 105 struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index); 106 107 ALOGE(" id=%d: ctl=%s", i, mixer_ctl_get_name(ctl)); 108 for (j = 0; j < path->setting[i].num_values; j++) 109 ALOGE(" id=%d value=%d", j, path->setting[i].value[j]); 110 } 111 } 112 113 static void path_free(struct audio_route *ar) 114 { 115 unsigned int i; 116 117 for (i = 0; i < ar->num_mixer_paths; i++) { 118 if (ar->mixer_path[i].name) 119 free(ar->mixer_path[i].name); 120 if (ar->mixer_path[i].setting) { 121 if (ar->mixer_path[i].setting->value) 122 free(ar->mixer_path[i].setting->value); 123 free(ar->mixer_path[i].setting); 124 } 125 } 126 free(ar->mixer_path); 127 } 128 129 static struct mixer_path *path_get_by_name(struct audio_route *ar, 130 const char *name) 131 { 132 unsigned int i; 133 134 for (i = 0; i < ar->num_mixer_paths; i++) 135 if (strcmp(ar->mixer_path[i].name, name) == 0) 136 return &ar->mixer_path[i]; 137 138 return NULL; 139 } 140 141 static struct mixer_path *path_create(struct audio_route *ar, const char *name) 142 { 143 struct mixer_path *new_mixer_path = NULL; 144 145 if (path_get_by_name(ar, name)) { 146 ALOGE("Path name '%s' already exists", name); 147 return NULL; 148 } 149 150 /* check if we need to allocate more space for mixer paths */ 151 if (ar->mixer_path_size <= ar->num_mixer_paths) { 152 if (ar->mixer_path_size == 0) 153 ar->mixer_path_size = INITIAL_MIXER_PATH_SIZE; 154 else 155 ar->mixer_path_size *= 2; 156 157 new_mixer_path = realloc(ar->mixer_path, ar->mixer_path_size * 158 sizeof(struct mixer_path)); 159 if (new_mixer_path == NULL) { 160 ALOGE("Unable to allocate more paths"); 161 return NULL; 162 } else { 163 ar->mixer_path = new_mixer_path; 164 } 165 } 166 167 /* initialise the new mixer path */ 168 ar->mixer_path[ar->num_mixer_paths].name = strdup(name); 169 ar->mixer_path[ar->num_mixer_paths].size = 0; 170 ar->mixer_path[ar->num_mixer_paths].length = 0; 171 ar->mixer_path[ar->num_mixer_paths].setting = NULL; 172 173 /* return the mixer path just added, then increment number of them */ 174 return &ar->mixer_path[ar->num_mixer_paths++]; 175 } 176 177 static int find_ctl_index_in_path(struct mixer_path *path, 178 unsigned int ctl_index) 179 { 180 unsigned int i; 181 182 for (i = 0; i < path->length; i++) 183 if (path->setting[i].ctl_index == ctl_index) 184 return i; 185 186 return -1; 187 } 188 189 static int alloc_path_setting(struct mixer_path *path) 190 { 191 struct mixer_setting *new_path_setting; 192 int path_index; 193 194 /* check if we need to allocate more space for path settings */ 195 if (path->size <= path->length) { 196 if (path->size == 0) 197 path->size = INITIAL_MIXER_PATH_SIZE; 198 else 199 path->size *= 2; 200 201 new_path_setting = realloc(path->setting, 202 path->size * sizeof(struct mixer_setting)); 203 if (new_path_setting == NULL) { 204 ALOGE("Unable to allocate more path settings"); 205 return -1; 206 } else { 207 path->setting = new_path_setting; 208 } 209 } 210 211 path_index = path->length; 212 path->length++; 213 214 return path_index; 215 } 216 217 static int path_add_setting(struct audio_route *ar, struct mixer_path *path, 218 struct mixer_setting *setting) 219 { 220 int path_index; 221 222 if (find_ctl_index_in_path(path, setting->ctl_index) != -1) { 223 struct mixer_ctl *ctl = index_to_ctl(ar, setting->ctl_index); 224 225 ALOGE("Control '%s' already exists in path '%s'", 226 mixer_ctl_get_name(ctl), path->name); 227 return -1; 228 } 229 230 path_index = alloc_path_setting(path); 231 if (path_index < 0) 232 return -1; 233 234 path->setting[path_index].ctl_index = setting->ctl_index; 235 path->setting[path_index].num_values = setting->num_values; 236 path->setting[path_index].value = malloc(setting->num_values * sizeof(int)); 237 /* copy all values */ 238 memcpy(path->setting[path_index].value, setting->value, 239 setting->num_values * sizeof(int)); 240 241 return 0; 242 } 243 244 static int path_add_value(struct audio_route *ar, struct mixer_path *path, 245 struct mixer_value *mixer_value) 246 { 247 unsigned int i; 248 int path_index; 249 unsigned int num_values; 250 struct mixer_ctl *ctl; 251 252 /* Check that mixer value index is within range */ 253 ctl = index_to_ctl(ar, mixer_value->ctl_index); 254 num_values = mixer_ctl_get_num_values(ctl); 255 if (mixer_value->index >= (int)num_values) { 256 ALOGE("mixer index %d is out of range for '%s'", mixer_value->index, 257 mixer_ctl_get_name(ctl)); 258 return -1; 259 } 260 261 path_index = find_ctl_index_in_path(path, mixer_value->ctl_index); 262 if (path_index < 0) { 263 /* New path */ 264 265 path_index = alloc_path_setting(path); 266 if (path_index < 0) 267 return -1; 268 269 /* initialise the new path setting */ 270 path->setting[path_index].ctl_index = mixer_value->ctl_index; 271 path->setting[path_index].num_values = num_values; 272 path->setting[path_index].value = malloc(num_values * sizeof(int)); 273 path->setting[path_index].value[0] = mixer_value->value; 274 } 275 276 if (mixer_value->index == -1) { 277 /* set all values the same */ 278 for (i = 0; i < num_values; i++) 279 path->setting[path_index].value[i] = mixer_value->value; 280 } else { 281 /* set only one value */ 282 path->setting[path_index].value[mixer_value->index] = mixer_value->value; 283 } 284 285 return 0; 286 } 287 288 static int path_add_path(struct audio_route *ar, struct mixer_path *path, 289 struct mixer_path *sub_path) 290 { 291 unsigned int i; 292 293 for (i = 0; i < sub_path->length; i++) 294 if (path_add_setting(ar, path, &sub_path->setting[i]) < 0) 295 return -1; 296 297 return 0; 298 } 299 300 static int path_apply(struct audio_route *ar, struct mixer_path *path) 301 { 302 unsigned int i; 303 unsigned int ctl_index; 304 struct mixer_ctl *ctl; 305 enum mixer_ctl_type type; 306 307 for (i = 0; i < path->length; i++) { 308 ctl_index = path->setting[i].ctl_index; 309 ctl = index_to_ctl(ar, ctl_index); 310 type = mixer_ctl_get_type(ctl); 311 if (!is_supported_ctl_type(type)) 312 continue; 313 314 /* apply the new value(s) */ 315 memcpy(ar->mixer_state[ctl_index].new_value, path->setting[i].value, 316 path->setting[i].num_values * sizeof(int)); 317 } 318 319 return 0; 320 } 321 322 static int path_reset(struct audio_route *ar, struct mixer_path *path) 323 { 324 unsigned int i; 325 unsigned int j; 326 unsigned int ctl_index; 327 struct mixer_ctl *ctl; 328 enum mixer_ctl_type type; 329 330 for (i = 0; i < path->length; i++) { 331 ctl_index = path->setting[i].ctl_index; 332 ctl = index_to_ctl(ar, ctl_index); 333 type = mixer_ctl_get_type(ctl); 334 if (!is_supported_ctl_type(type)) 335 continue; 336 337 /* reset the value(s) */ 338 memcpy(ar->mixer_state[ctl_index].new_value, 339 ar->mixer_state[ctl_index].reset_value, 340 ar->mixer_state[ctl_index].num_values * sizeof(int)); 341 } 342 343 return 0; 344 } 345 346 /* mixer helper function */ 347 static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string) 348 { 349 unsigned int i; 350 351 /* Search the enum strings for a particular one */ 352 for (i = 0; i < mixer_ctl_get_num_enums(ctl); i++) { 353 if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0) 354 break; 355 } 356 357 return i; 358 } 359 360 static void start_tag(void *data, const XML_Char *tag_name, 361 const XML_Char **attr) 362 { 363 const XML_Char *attr_name = NULL; 364 const XML_Char *attr_id = NULL; 365 const XML_Char *attr_value = NULL; 366 struct config_parse_state *state = data; 367 struct audio_route *ar = state->ar; 368 unsigned int i; 369 unsigned int ctl_index; 370 struct mixer_ctl *ctl; 371 int value; 372 unsigned int id; 373 struct mixer_value mixer_value; 374 enum mixer_ctl_type type; 375 376 /* Get name, id and value attributes (these may be empty) */ 377 for (i = 0; attr[i]; i += 2) { 378 if (strcmp(attr[i], "name") == 0) 379 attr_name = attr[i + 1]; 380 if (strcmp(attr[i], "id") == 0) 381 attr_id = attr[i + 1]; 382 else if (strcmp(attr[i], "value") == 0) 383 attr_value = attr[i + 1]; 384 } 385 386 /* Look at tags */ 387 if (strcmp(tag_name, "path") == 0) { 388 if (attr_name == NULL) { 389 ALOGE("Unnamed path!"); 390 } else { 391 if (state->level == 1) { 392 /* top level path: create and stash the path */ 393 state->path = path_create(ar, (char *)attr_name); 394 } else { 395 /* nested path */ 396 struct mixer_path *sub_path = path_get_by_name(ar, attr_name); 397 path_add_path(ar, state->path, sub_path); 398 } 399 } 400 } 401 402 else if (strcmp(tag_name, "ctl") == 0) { 403 /* Obtain the mixer ctl and value */ 404 ctl = mixer_get_ctl_by_name(ar->mixer, attr_name); 405 if (ctl == NULL) { 406 ALOGE("Control '%s' doesn't exist - skipping", attr_name); 407 goto done; 408 } 409 410 switch (mixer_ctl_get_type(ctl)) { 411 case MIXER_CTL_TYPE_BOOL: 412 case MIXER_CTL_TYPE_INT: 413 value = atoi((char *)attr_value); 414 break; 415 case MIXER_CTL_TYPE_ENUM: 416 value = mixer_enum_string_to_value(ctl, (char *)attr_value); 417 break; 418 default: 419 value = 0; 420 break; 421 } 422 423 /* locate the mixer ctl in the list */ 424 for (ctl_index = 0; ctl_index < ar->num_mixer_ctls; ctl_index++) { 425 if (ar->mixer_state[ctl_index].ctl == ctl) 426 break; 427 } 428 429 if (state->level == 1) { 430 /* top level ctl (initial setting) */ 431 432 type = mixer_ctl_get_type(ctl); 433 if (is_supported_ctl_type(type)) { 434 /* apply the new value */ 435 if (attr_id) { 436 /* set only one value */ 437 id = atoi((char *)attr_id); 438 if (id < ar->mixer_state[ctl_index].num_values) 439 ar->mixer_state[ctl_index].new_value[id] = value; 440 else 441 ALOGE("value id out of range for mixer ctl '%s'", 442 mixer_ctl_get_name(ctl)); 443 } else { 444 /* set all values the same */ 445 for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++) 446 ar->mixer_state[ctl_index].new_value[i] = value; 447 } 448 } 449 } else { 450 /* nested ctl (within a path) */ 451 mixer_value.ctl_index = ctl_index; 452 mixer_value.value = value; 453 if (attr_id) 454 mixer_value.index = atoi((char *)attr_id); 455 else 456 mixer_value.index = -1; 457 path_add_value(ar, state->path, &mixer_value); 458 } 459 } 460 461 done: 462 state->level++; 463 } 464 465 static void end_tag(void *data, const XML_Char *tag_name) 466 { 467 struct config_parse_state *state = data; 468 (void)tag_name; 469 470 state->level--; 471 } 472 473 static int alloc_mixer_state(struct audio_route *ar) 474 { 475 unsigned int i; 476 unsigned int j; 477 unsigned int num_values; 478 struct mixer_ctl *ctl; 479 enum mixer_ctl_type type; 480 481 ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer); 482 ar->mixer_state = malloc(ar->num_mixer_ctls * sizeof(struct mixer_state)); 483 if (!ar->mixer_state) 484 return -1; 485 486 for (i = 0; i < ar->num_mixer_ctls; i++) { 487 ctl = mixer_get_ctl(ar->mixer, i); 488 num_values = mixer_ctl_get_num_values(ctl); 489 490 ar->mixer_state[i].ctl = ctl; 491 ar->mixer_state[i].num_values = num_values; 492 493 /* Skip unsupported types that are not supported yet in XML */ 494 type = mixer_ctl_get_type(ctl); 495 496 if (!is_supported_ctl_type(type)) 497 continue; 498 499 ar->mixer_state[i].old_value = malloc(num_values * sizeof(int)); 500 ar->mixer_state[i].new_value = malloc(num_values * sizeof(int)); 501 ar->mixer_state[i].reset_value = malloc(num_values * sizeof(int)); 502 503 if (type == MIXER_CTL_TYPE_ENUM) 504 ar->mixer_state[i].old_value[0] = mixer_ctl_get_value(ctl, 0); 505 else 506 mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value, num_values); 507 memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].old_value, 508 num_values * sizeof(int)); 509 } 510 511 return 0; 512 } 513 514 static void free_mixer_state(struct audio_route *ar) 515 { 516 unsigned int i; 517 enum mixer_ctl_type type; 518 519 for (i = 0; i < ar->num_mixer_ctls; i++) { 520 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 521 if (!is_supported_ctl_type(type)) 522 continue; 523 524 free(ar->mixer_state[i].old_value); 525 free(ar->mixer_state[i].new_value); 526 free(ar->mixer_state[i].reset_value); 527 } 528 529 free(ar->mixer_state); 530 ar->mixer_state = NULL; 531 } 532 533 /* Update the mixer with any changed values */ 534 int audio_route_update_mixer(struct audio_route *ar) 535 { 536 unsigned int i; 537 unsigned int j; 538 struct mixer_ctl *ctl; 539 540 for (i = 0; i < ar->num_mixer_ctls; i++) { 541 unsigned int num_values = ar->mixer_state[i].num_values; 542 enum mixer_ctl_type type; 543 544 ctl = ar->mixer_state[i].ctl; 545 546 /* Skip unsupported types */ 547 type = mixer_ctl_get_type(ctl); 548 if (!is_supported_ctl_type(type)) 549 continue; 550 551 /* if the value has changed, update the mixer */ 552 bool changed = false; 553 for (j = 0; j < num_values; j++) { 554 if (ar->mixer_state[i].old_value[j] != ar->mixer_state[i].new_value[j]) { 555 changed = true; 556 break; 557 } 558 } 559 if (changed) { 560 if (type == MIXER_CTL_TYPE_ENUM) 561 mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value[0]); 562 else 563 mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value, num_values); 564 memcpy(ar->mixer_state[i].old_value, ar->mixer_state[i].new_value, 565 num_values * sizeof(int)); 566 } 567 } 568 569 return 0; 570 } 571 572 /* saves the current state of the mixer, for resetting all controls */ 573 static void save_mixer_state(struct audio_route *ar) 574 { 575 unsigned int i; 576 enum mixer_ctl_type type; 577 578 for (i = 0; i < ar->num_mixer_ctls; i++) { 579 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 580 if (!is_supported_ctl_type(type)) 581 continue; 582 583 memcpy(ar->mixer_state[i].reset_value, ar->mixer_state[i].new_value, 584 ar->mixer_state[i].num_values * sizeof(int)); 585 } 586 } 587 588 /* Reset the audio routes back to the initial state */ 589 void audio_route_reset(struct audio_route *ar) 590 { 591 unsigned int i; 592 enum mixer_ctl_type type; 593 594 /* load all of the saved values */ 595 for (i = 0; i < ar->num_mixer_ctls; i++) { 596 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 597 if (!is_supported_ctl_type(type)) 598 continue; 599 600 memcpy(ar->mixer_state[i].new_value, ar->mixer_state[i].reset_value, 601 ar->mixer_state[i].num_values * sizeof(int)); 602 } 603 } 604 605 /* Apply an audio route path by name */ 606 int audio_route_apply_path(struct audio_route *ar, const char *name) 607 { 608 struct mixer_path *path; 609 610 if (!ar) { 611 ALOGE("invalid audio_route"); 612 return -1; 613 } 614 615 path = path_get_by_name(ar, name); 616 if (!path) { 617 ALOGE("unable to find path '%s'", name); 618 return -1; 619 } 620 621 path_apply(ar, path); 622 623 return 0; 624 } 625 626 /* Reset an audio route path by name */ 627 int audio_route_reset_path(struct audio_route *ar, const char *name) 628 { 629 struct mixer_path *path; 630 631 if (!ar) { 632 ALOGE("invalid audio_route"); 633 return -1; 634 } 635 636 path = path_get_by_name(ar, name); 637 if (!path) { 638 ALOGE("unable to find path '%s'", name); 639 return -1; 640 } 641 642 path_reset(ar, path); 643 644 return 0; 645 } 646 647 struct audio_route *audio_route_init(unsigned int card, const char *xml_path) 648 { 649 struct config_parse_state state; 650 XML_Parser parser; 651 FILE *file; 652 int bytes_read; 653 void *buf; 654 int i; 655 struct audio_route *ar; 656 657 ar = calloc(1, sizeof(struct audio_route)); 658 if (!ar) 659 goto err_calloc; 660 661 ar->mixer = mixer_open(card); 662 if (!ar->mixer) { 663 ALOGE("Unable to open the mixer, aborting."); 664 goto err_mixer_open; 665 } 666 667 ar->mixer_path = NULL; 668 ar->mixer_path_size = 0; 669 ar->num_mixer_paths = 0; 670 671 /* allocate space for and read current mixer settings */ 672 if (alloc_mixer_state(ar) < 0) 673 goto err_mixer_state; 674 675 /* use the default XML path if none is provided */ 676 if (xml_path == NULL) 677 xml_path = MIXER_XML_PATH; 678 679 file = fopen(xml_path, "r"); 680 681 if (!file) { 682 ALOGE("Failed to open %s", xml_path); 683 goto err_fopen; 684 } 685 686 parser = XML_ParserCreate(NULL); 687 if (!parser) { 688 ALOGE("Failed to create XML parser"); 689 goto err_parser_create; 690 } 691 692 memset(&state, 0, sizeof(state)); 693 state.ar = ar; 694 XML_SetUserData(parser, &state); 695 XML_SetElementHandler(parser, start_tag, end_tag); 696 697 for (;;) { 698 buf = XML_GetBuffer(parser, BUF_SIZE); 699 if (buf == NULL) 700 goto err_parse; 701 702 bytes_read = fread(buf, 1, BUF_SIZE, file); 703 if (bytes_read < 0) 704 goto err_parse; 705 706 if (XML_ParseBuffer(parser, bytes_read, 707 bytes_read == 0) == XML_STATUS_ERROR) { 708 ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH); 709 goto err_parse; 710 } 711 712 if (bytes_read == 0) 713 break; 714 } 715 716 /* apply the initial mixer values, and save them so we can reset the 717 mixer to the original values */ 718 audio_route_update_mixer(ar); 719 save_mixer_state(ar); 720 721 XML_ParserFree(parser); 722 fclose(file); 723 return ar; 724 725 err_parse: 726 XML_ParserFree(parser); 727 err_parser_create: 728 fclose(file); 729 err_fopen: 730 free_mixer_state(ar); 731 err_mixer_state: 732 mixer_close(ar->mixer); 733 err_mixer_open: 734 free(ar); 735 ar = NULL; 736 err_calloc: 737 return NULL; 738 } 739 740 void audio_route_free(struct audio_route *ar) 741 { 742 free_mixer_state(ar); 743 mixer_close(ar->mixer); 744 free(ar); 745 } 746