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