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 <log/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 enum update_direction { 36 DIRECTION_FORWARD, 37 DIRECTION_REVERSE, 38 DIRECTION_REVERSE_RESET 39 }; 40 41 union ctl_values { 42 int *enumerated; 43 long *integer; 44 void *ptr; 45 unsigned char *bytes; 46 }; 47 48 struct mixer_state { 49 struct mixer_ctl *ctl; 50 unsigned int num_values; 51 union ctl_values old_value; 52 union ctl_values new_value; 53 union ctl_values reset_value; 54 unsigned int active_count; 55 }; 56 57 struct mixer_setting { 58 unsigned int ctl_index; 59 unsigned int num_values; 60 unsigned int type; 61 union ctl_values value; 62 }; 63 64 struct mixer_value { 65 unsigned int ctl_index; 66 int index; 67 long value; 68 }; 69 70 struct mixer_path { 71 char *name; 72 unsigned int size; 73 unsigned int length; 74 struct mixer_setting *setting; 75 }; 76 77 struct audio_route { 78 struct mixer *mixer; 79 unsigned int num_mixer_ctls; 80 struct mixer_state *mixer_state; 81 82 unsigned int mixer_path_size; 83 unsigned int num_mixer_paths; 84 struct mixer_path *mixer_path; 85 }; 86 87 struct config_parse_state { 88 struct audio_route *ar; 89 struct mixer_path *path; 90 int level; 91 }; 92 93 /* path functions */ 94 95 static bool is_supported_ctl_type(enum mixer_ctl_type type) 96 { 97 switch (type) { 98 case MIXER_CTL_TYPE_BOOL: 99 case MIXER_CTL_TYPE_INT: 100 case MIXER_CTL_TYPE_ENUM: 101 case MIXER_CTL_TYPE_BYTE: 102 return true; 103 default: 104 return false; 105 } 106 } 107 108 /* as they match in alsa */ 109 static size_t sizeof_ctl_type(enum mixer_ctl_type type) { 110 switch (type) { 111 case MIXER_CTL_TYPE_BOOL: 112 case MIXER_CTL_TYPE_INT: 113 return sizeof(long); 114 case MIXER_CTL_TYPE_ENUM: 115 return sizeof(int); 116 case MIXER_CTL_TYPE_BYTE: 117 return sizeof(unsigned char); 118 case MIXER_CTL_TYPE_INT64: 119 case MIXER_CTL_TYPE_IEC958: 120 case MIXER_CTL_TYPE_UNKNOWN: 121 default: 122 LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type); 123 return 0; 124 } 125 } 126 127 static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar, 128 unsigned int ctl_index) 129 { 130 return ar->mixer_state[ctl_index].ctl; 131 } 132 133 #if 0 134 static void path_print(struct audio_route *ar, struct mixer_path *path) 135 { 136 unsigned int i; 137 unsigned int j; 138 139 ALOGE("Path: %s, length: %d", path->name, path->length); 140 for (i = 0; i < path->length; i++) { 141 struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index); 142 143 ALOGE(" id=%d: ctl=%s", i, mixer_ctl_get_name(ctl)); 144 if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) { 145 for (j = 0; j < path->setting[i].num_values; j++) 146 ALOGE(" id=%d value=0x%02x", j, path->setting[i].value.bytes[j]); 147 } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) { 148 for (j = 0; j < path->setting[i].num_values; j++) 149 ALOGE(" id=%d value=%d", j, path->setting[i].value.enumerated[j]); 150 } else { 151 for (j = 0; j < path->setting[i].num_values; j++) 152 ALOGE(" id=%d value=%ld", j, path->setting[i].value.integer[j]); 153 } 154 } 155 } 156 #endif 157 158 static void path_free(struct audio_route *ar) 159 { 160 unsigned int i; 161 162 for (i = 0; i < ar->num_mixer_paths; i++) { 163 free(ar->mixer_path[i].name); 164 if (ar->mixer_path[i].setting) { 165 size_t j; 166 for (j = 0; j < ar->mixer_path[i].length; j++) { 167 free(ar->mixer_path[i].setting[j].value.ptr); 168 } 169 free(ar->mixer_path[i].setting); 170 ar->mixer_path[i].size = 0; 171 ar->mixer_path[i].length = 0; 172 ar->mixer_path[i].setting = NULL; 173 } 174 } 175 free(ar->mixer_path); 176 ar->mixer_path = NULL; 177 ar->mixer_path_size = 0; 178 ar->num_mixer_paths = 0; 179 } 180 181 static struct mixer_path *path_get_by_name(struct audio_route *ar, 182 const char *name) 183 { 184 unsigned int i; 185 186 for (i = 0; i < ar->num_mixer_paths; i++) 187 if (strcmp(ar->mixer_path[i].name, name) == 0) 188 return &ar->mixer_path[i]; 189 190 return NULL; 191 } 192 193 static struct mixer_path *path_create(struct audio_route *ar, const char *name) 194 { 195 struct mixer_path *new_mixer_path = NULL; 196 197 if (path_get_by_name(ar, name)) { 198 ALOGE("Path name '%s' already exists", name); 199 return NULL; 200 } 201 202 /* check if we need to allocate more space for mixer paths */ 203 if (ar->mixer_path_size <= ar->num_mixer_paths) { 204 if (ar->mixer_path_size == 0) 205 ar->mixer_path_size = INITIAL_MIXER_PATH_SIZE; 206 else 207 ar->mixer_path_size *= 2; 208 209 new_mixer_path = realloc(ar->mixer_path, ar->mixer_path_size * 210 sizeof(struct mixer_path)); 211 if (new_mixer_path == NULL) { 212 ALOGE("Unable to allocate more paths"); 213 return NULL; 214 } else { 215 ar->mixer_path = new_mixer_path; 216 } 217 } 218 219 /* initialise the new mixer path */ 220 ar->mixer_path[ar->num_mixer_paths].name = strdup(name); 221 ar->mixer_path[ar->num_mixer_paths].size = 0; 222 ar->mixer_path[ar->num_mixer_paths].length = 0; 223 ar->mixer_path[ar->num_mixer_paths].setting = NULL; 224 225 /* return the mixer path just added, then increment number of them */ 226 return &ar->mixer_path[ar->num_mixer_paths++]; 227 } 228 229 static int find_ctl_index_in_path(struct mixer_path *path, 230 unsigned int ctl_index) 231 { 232 unsigned int i; 233 234 for (i = 0; i < path->length; i++) 235 if (path->setting[i].ctl_index == ctl_index) 236 return i; 237 238 return -1; 239 } 240 241 static int alloc_path_setting(struct mixer_path *path) 242 { 243 struct mixer_setting *new_path_setting; 244 int path_index; 245 246 /* check if we need to allocate more space for path settings */ 247 if (path->size <= path->length) { 248 if (path->size == 0) 249 path->size = INITIAL_MIXER_PATH_SIZE; 250 else 251 path->size *= 2; 252 253 new_path_setting = realloc(path->setting, 254 path->size * sizeof(struct mixer_setting)); 255 if (new_path_setting == NULL) { 256 ALOGE("Unable to allocate more path settings"); 257 return -1; 258 } else { 259 path->setting = new_path_setting; 260 } 261 } 262 263 path_index = path->length; 264 path->length++; 265 266 return path_index; 267 } 268 269 static int path_add_setting(struct audio_route *ar, struct mixer_path *path, 270 struct mixer_setting *setting) 271 { 272 int path_index; 273 274 if (find_ctl_index_in_path(path, setting->ctl_index) != -1) { 275 struct mixer_ctl *ctl = index_to_ctl(ar, setting->ctl_index); 276 277 ALOGE("Control '%s' already exists in path '%s'", 278 mixer_ctl_get_name(ctl), path->name); 279 return -1; 280 } 281 282 if (!is_supported_ctl_type(setting->type)) { 283 ALOGE("unsupported type %d", (int)setting->type); 284 return -1; 285 } 286 287 path_index = alloc_path_setting(path); 288 if (path_index < 0) 289 return -1; 290 291 path->setting[path_index].ctl_index = setting->ctl_index; 292 path->setting[path_index].type = setting->type; 293 path->setting[path_index].num_values = setting->num_values; 294 295 size_t value_sz = sizeof_ctl_type(setting->type); 296 297 path->setting[path_index].value.ptr = calloc(setting->num_values, value_sz); 298 /* copy all values */ 299 memcpy(path->setting[path_index].value.ptr, setting->value.ptr, 300 setting->num_values * value_sz); 301 302 return 0; 303 } 304 305 static int path_add_value(struct audio_route *ar, struct mixer_path *path, 306 struct mixer_value *mixer_value) 307 { 308 unsigned int i; 309 int path_index; 310 unsigned int num_values; 311 struct mixer_ctl *ctl; 312 313 /* Check that mixer value index is within range */ 314 ctl = index_to_ctl(ar, mixer_value->ctl_index); 315 num_values = mixer_ctl_get_num_values(ctl); 316 if (mixer_value->index >= (int)num_values) { 317 ALOGE("mixer index %d is out of range for '%s'", mixer_value->index, 318 mixer_ctl_get_name(ctl)); 319 return -1; 320 } 321 322 path_index = find_ctl_index_in_path(path, mixer_value->ctl_index); 323 if (path_index < 0) { 324 /* New path */ 325 326 enum mixer_ctl_type type = mixer_ctl_get_type(ctl); 327 if (!is_supported_ctl_type(type)) { 328 ALOGE("unsupported type %d", (int)type); 329 return -1; 330 } 331 path_index = alloc_path_setting(path); 332 if (path_index < 0) 333 return -1; 334 335 /* initialise the new path setting */ 336 path->setting[path_index].ctl_index = mixer_value->ctl_index; 337 path->setting[path_index].num_values = num_values; 338 path->setting[path_index].type = type; 339 340 size_t value_sz = sizeof_ctl_type(type); 341 path->setting[path_index].value.ptr = calloc(num_values, value_sz); 342 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) 343 path->setting[path_index].value.bytes[0] = mixer_value->value; 344 else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) 345 path->setting[path_index].value.enumerated[0] = mixer_value->value; 346 else 347 path->setting[path_index].value.integer[0] = mixer_value->value; 348 } 349 350 if (mixer_value->index == -1) { 351 /* set all values the same */ 352 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) { 353 for (i = 0; i < num_values; i++) 354 path->setting[path_index].value.bytes[i] = mixer_value->value; 355 } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) { 356 for (i = 0; i < num_values; i++) 357 path->setting[path_index].value.enumerated[i] = mixer_value->value; 358 } else { 359 for (i = 0; i < num_values; i++) 360 path->setting[path_index].value.integer[i] = mixer_value->value; 361 } 362 } else { 363 /* set only one value */ 364 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) 365 path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value; 366 else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) 367 path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value; 368 else 369 path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value; 370 } 371 372 return 0; 373 } 374 375 static int path_add_path(struct audio_route *ar, struct mixer_path *path, 376 struct mixer_path *sub_path) 377 { 378 unsigned int i; 379 380 for (i = 0; i < sub_path->length; i++) 381 if (path_add_setting(ar, path, &sub_path->setting[i]) < 0) 382 return -1; 383 384 return 0; 385 } 386 387 static int path_apply(struct audio_route *ar, struct mixer_path *path) 388 { 389 unsigned int i; 390 unsigned int ctl_index; 391 struct mixer_ctl *ctl; 392 enum mixer_ctl_type type; 393 394 ALOGD("Apply path: %s", path->name != NULL ? path->name : "none"); 395 for (i = 0; i < path->length; i++) { 396 ctl_index = path->setting[i].ctl_index; 397 ctl = index_to_ctl(ar, ctl_index); 398 type = mixer_ctl_get_type(ctl); 399 if (!is_supported_ctl_type(type)) 400 continue; 401 size_t value_sz = sizeof_ctl_type(type); 402 memcpy(ar->mixer_state[ctl_index].new_value.ptr, path->setting[i].value.ptr, 403 path->setting[i].num_values * value_sz); 404 } 405 406 return 0; 407 } 408 409 static int path_reset(struct audio_route *ar, struct mixer_path *path) 410 { 411 unsigned int i; 412 unsigned int ctl_index; 413 struct mixer_ctl *ctl; 414 enum mixer_ctl_type type; 415 416 ALOGV("Reset path: %s", path->name != NULL ? path->name : "none"); 417 for (i = 0; i < path->length; i++) { 418 ctl_index = path->setting[i].ctl_index; 419 ctl = index_to_ctl(ar, ctl_index); 420 type = mixer_ctl_get_type(ctl); 421 if (!is_supported_ctl_type(type)) 422 continue; 423 size_t value_sz = sizeof_ctl_type(type); 424 /* reset the value(s) */ 425 memcpy(ar->mixer_state[ctl_index].new_value.ptr, 426 ar->mixer_state[ctl_index].reset_value.ptr, 427 ar->mixer_state[ctl_index].num_values * value_sz); 428 } 429 430 return 0; 431 } 432 433 /* mixer helper function */ 434 static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string) 435 { 436 unsigned int i; 437 unsigned int num_values = mixer_ctl_get_num_enums(ctl); 438 439 if (string == NULL) { 440 ALOGE("NULL enum value string passed to mixer_enum_string_to_value() for ctl %s", 441 mixer_ctl_get_name(ctl)); 442 return 0; 443 } 444 445 /* Search the enum strings for a particular one */ 446 for (i = 0; i < num_values; i++) { 447 if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0) 448 break; 449 } 450 if (i == num_values) { 451 ALOGE("unknown enum value string %s for ctl %s", 452 string, mixer_ctl_get_name(ctl)); 453 return 0; 454 } 455 return i; 456 } 457 458 static void start_tag(void *data, const XML_Char *tag_name, 459 const XML_Char **attr) 460 { 461 const XML_Char *attr_name = NULL; 462 const XML_Char *attr_id = NULL; 463 const XML_Char *attr_value = NULL; 464 struct config_parse_state *state = data; 465 struct audio_route *ar = state->ar; 466 unsigned int i; 467 unsigned int ctl_index; 468 struct mixer_ctl *ctl; 469 long value; 470 unsigned int id; 471 struct mixer_value mixer_value; 472 enum mixer_ctl_type type; 473 474 /* Get name, id and value attributes (these may be empty) */ 475 for (i = 0; attr[i]; i += 2) { 476 if (strcmp(attr[i], "name") == 0) 477 attr_name = attr[i + 1]; 478 if (strcmp(attr[i], "id") == 0) 479 attr_id = attr[i + 1]; 480 else if (strcmp(attr[i], "value") == 0) 481 attr_value = attr[i + 1]; 482 } 483 484 /* Look at tags */ 485 if (strcmp(tag_name, "path") == 0) { 486 if (attr_name == NULL) { 487 ALOGE("Unnamed path!"); 488 } else { 489 if (state->level == 1) { 490 /* top level path: create and stash the path */ 491 state->path = path_create(ar, (char *)attr_name); 492 if (state->path == NULL) 493 ALOGE("path created failed, please check the path if existed"); 494 } else { 495 /* nested path */ 496 struct mixer_path *sub_path = path_get_by_name(ar, attr_name); 497 if (!sub_path) { 498 ALOGE("unable to find sub path '%s'", attr_name); 499 } else if (state->path != NULL) { 500 path_add_path(ar, state->path, sub_path); 501 } 502 } 503 } 504 } 505 506 else if (strcmp(tag_name, "ctl") == 0) { 507 /* Obtain the mixer ctl and value */ 508 ctl = mixer_get_ctl_by_name(ar->mixer, attr_name); 509 if (ctl == NULL) { 510 ALOGE("Control '%s' doesn't exist - skipping", attr_name); 511 goto done; 512 } 513 514 switch (mixer_ctl_get_type(ctl)) { 515 case MIXER_CTL_TYPE_BOOL: 516 case MIXER_CTL_TYPE_INT: 517 value = strtol((char *)attr_value, NULL, 0); 518 break; 519 case MIXER_CTL_TYPE_BYTE: 520 value = (unsigned char) strtol((char *)attr_value, NULL, 16); 521 break; 522 case MIXER_CTL_TYPE_ENUM: 523 value = mixer_enum_string_to_value(ctl, (char *)attr_value); 524 break; 525 default: 526 value = 0; 527 break; 528 } 529 530 /* locate the mixer ctl in the list */ 531 for (ctl_index = 0; ctl_index < ar->num_mixer_ctls; ctl_index++) { 532 if (ar->mixer_state[ctl_index].ctl == ctl) 533 break; 534 } 535 536 if (state->level == 1) { 537 /* top level ctl (initial setting) */ 538 539 type = mixer_ctl_get_type(ctl); 540 if (is_supported_ctl_type(type)) { 541 /* apply the new value */ 542 if (attr_id) { 543 /* set only one value */ 544 id = atoi((char *)attr_id); 545 if (id < ar->mixer_state[ctl_index].num_values) 546 if (type == MIXER_CTL_TYPE_BYTE) 547 ar->mixer_state[ctl_index].new_value.bytes[id] = value; 548 else if (type == MIXER_CTL_TYPE_ENUM) 549 ar->mixer_state[ctl_index].new_value.enumerated[id] = value; 550 else 551 ar->mixer_state[ctl_index].new_value.integer[id] = value; 552 else 553 ALOGE("value id out of range for mixer ctl '%s'", 554 mixer_ctl_get_name(ctl)); 555 } else { 556 /* set all values the same */ 557 for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++) 558 if (type == MIXER_CTL_TYPE_BYTE) 559 ar->mixer_state[ctl_index].new_value.bytes[i] = value; 560 else if (type == MIXER_CTL_TYPE_ENUM) 561 ar->mixer_state[ctl_index].new_value.enumerated[i] = value; 562 else 563 ar->mixer_state[ctl_index].new_value.integer[i] = value; 564 } 565 } 566 } else { 567 /* nested ctl (within a path) */ 568 mixer_value.ctl_index = ctl_index; 569 mixer_value.value = value; 570 if (attr_id) 571 mixer_value.index = atoi((char *)attr_id); 572 else 573 mixer_value.index = -1; 574 if (state->path != NULL) 575 path_add_value(ar, state->path, &mixer_value); 576 } 577 } 578 579 done: 580 state->level++; 581 } 582 583 static void end_tag(void *data, const XML_Char *tag_name) 584 { 585 struct config_parse_state *state = data; 586 (void)tag_name; 587 588 state->level--; 589 } 590 591 static int alloc_mixer_state(struct audio_route *ar) 592 { 593 unsigned int i; 594 unsigned int num_values; 595 struct mixer_ctl *ctl; 596 enum mixer_ctl_type type; 597 598 ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer); 599 ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state)); 600 if (!ar->mixer_state) 601 return -1; 602 603 for (i = 0; i < ar->num_mixer_ctls; i++) { 604 ctl = mixer_get_ctl(ar->mixer, i); 605 num_values = mixer_ctl_get_num_values(ctl); 606 607 ar->mixer_state[i].ctl = ctl; 608 ar->mixer_state[i].num_values = num_values; 609 ar->mixer_state[i].active_count = 0; 610 611 /* Skip unsupported types that are not supported yet in XML */ 612 type = mixer_ctl_get_type(ctl); 613 614 if (!is_supported_ctl_type(type)) 615 continue; 616 617 size_t value_sz = sizeof_ctl_type(type); 618 ar->mixer_state[i].old_value.ptr = calloc(num_values, value_sz); 619 ar->mixer_state[i].new_value.ptr = calloc(num_values, value_sz); 620 ar->mixer_state[i].reset_value.ptr = calloc(num_values, value_sz); 621 622 if (type == MIXER_CTL_TYPE_ENUM) 623 ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0); 624 else 625 mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values); 626 627 memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].old_value.ptr, 628 num_values * value_sz); 629 } 630 631 return 0; 632 } 633 634 static void free_mixer_state(struct audio_route *ar) 635 { 636 unsigned int i; 637 enum mixer_ctl_type type; 638 639 for (i = 0; i < ar->num_mixer_ctls; i++) { 640 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 641 if (!is_supported_ctl_type(type)) 642 continue; 643 644 free(ar->mixer_state[i].old_value.ptr); 645 free(ar->mixer_state[i].new_value.ptr); 646 free(ar->mixer_state[i].reset_value.ptr); 647 } 648 649 free(ar->mixer_state); 650 ar->mixer_state = NULL; 651 } 652 653 /* Update the mixer with any changed values */ 654 int audio_route_update_mixer(struct audio_route *ar) 655 { 656 unsigned int i; 657 unsigned int j; 658 struct mixer_ctl *ctl; 659 660 for (i = 0; i < ar->num_mixer_ctls; i++) { 661 unsigned int num_values = ar->mixer_state[i].num_values; 662 enum mixer_ctl_type type; 663 664 ctl = ar->mixer_state[i].ctl; 665 666 /* Skip unsupported types */ 667 type = mixer_ctl_get_type(ctl); 668 if (!is_supported_ctl_type(type)) 669 continue; 670 671 /* if the value has changed, update the mixer */ 672 bool changed = false; 673 if (type == MIXER_CTL_TYPE_BYTE) { 674 for (j = 0; j < num_values; j++) { 675 if (ar->mixer_state[i].old_value.bytes[j] != ar->mixer_state[i].new_value.bytes[j]) { 676 changed = true; 677 break; 678 } 679 } 680 } else if (type == MIXER_CTL_TYPE_ENUM) { 681 for (j = 0; j < num_values; j++) { 682 if (ar->mixer_state[i].old_value.enumerated[j] 683 != ar->mixer_state[i].new_value.enumerated[j]) { 684 changed = true; 685 break; 686 } 687 } 688 } else { 689 for (j = 0; j < num_values; j++) { 690 if (ar->mixer_state[i].old_value.integer[j] != ar->mixer_state[i].new_value.integer[j]) { 691 changed = true; 692 break; 693 } 694 } 695 } 696 if (changed) { 697 if (type == MIXER_CTL_TYPE_ENUM) 698 mixer_ctl_set_value(ctl, 0, ar->mixer_state[i].new_value.enumerated[0]); 699 else 700 mixer_ctl_set_array(ctl, ar->mixer_state[i].new_value.ptr, num_values); 701 702 size_t value_sz = sizeof_ctl_type(type); 703 memcpy(ar->mixer_state[i].old_value.ptr, ar->mixer_state[i].new_value.ptr, 704 num_values * value_sz); 705 } 706 } 707 708 return 0; 709 } 710 711 /* saves the current state of the mixer, for resetting all controls */ 712 static void save_mixer_state(struct audio_route *ar) 713 { 714 unsigned int i; 715 enum mixer_ctl_type type; 716 717 for (i = 0; i < ar->num_mixer_ctls; i++) { 718 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 719 if (!is_supported_ctl_type(type)) 720 continue; 721 722 size_t value_sz = sizeof_ctl_type(type); 723 memcpy(ar->mixer_state[i].reset_value.ptr, ar->mixer_state[i].new_value.ptr, 724 ar->mixer_state[i].num_values * value_sz); 725 } 726 } 727 728 /* Reset the audio routes back to the initial state */ 729 void audio_route_reset(struct audio_route *ar) 730 { 731 unsigned int i; 732 enum mixer_ctl_type type; 733 734 /* load all of the saved values */ 735 for (i = 0; i < ar->num_mixer_ctls; i++) { 736 type = mixer_ctl_get_type(ar->mixer_state[i].ctl); 737 if (!is_supported_ctl_type(type)) 738 continue; 739 740 size_t value_sz = sizeof_ctl_type(type); 741 memcpy(ar->mixer_state[i].new_value.ptr, ar->mixer_state[i].reset_value.ptr, 742 ar->mixer_state[i].num_values * value_sz); 743 } 744 } 745 746 /* Apply an audio route path by name */ 747 int audio_route_apply_path(struct audio_route *ar, const char *name) 748 { 749 struct mixer_path *path; 750 751 if (!ar) { 752 ALOGE("invalid audio_route"); 753 return -1; 754 } 755 756 path = path_get_by_name(ar, name); 757 if (!path) { 758 ALOGE("unable to find path '%s'", name); 759 return -1; 760 } 761 762 path_apply(ar, path); 763 764 return 0; 765 } 766 767 /* Reset an audio route path by name */ 768 int audio_route_reset_path(struct audio_route *ar, const char *name) 769 { 770 struct mixer_path *path; 771 772 if (!ar) { 773 ALOGE("invalid audio_route"); 774 return -1; 775 } 776 777 path = path_get_by_name(ar, name); 778 if (!path) { 779 ALOGE("unable to find path '%s'", name); 780 return -1; 781 } 782 783 path_reset(ar, path); 784 785 return 0; 786 } 787 788 /* 789 * Operates on the specified path .. controls will be updated in the 790 * order listed in the XML file 791 */ 792 static int audio_route_update_path(struct audio_route *ar, const char *name, int direction) 793 { 794 struct mixer_path *path; 795 unsigned int j; 796 bool reverse = direction != DIRECTION_FORWARD; 797 bool force_reset = direction == DIRECTION_REVERSE_RESET; 798 799 if (!ar) { 800 ALOGE("invalid audio_route"); 801 return -1; 802 } 803 804 path = path_get_by_name(ar, name); 805 if (!path) { 806 ALOGE("unable to find path '%s'", name); 807 return -1; 808 } 809 810 for (size_t i = 0; i < path->length; ++i) { 811 unsigned int ctl_index; 812 enum mixer_ctl_type type; 813 814 ctl_index = path->setting[reverse ? path->length - 1 - i : i].ctl_index; 815 816 struct mixer_state * ms = &ar->mixer_state[ctl_index]; 817 818 type = mixer_ctl_get_type(ms->ctl); 819 if (!is_supported_ctl_type(type)) { 820 continue; 821 } 822 823 if (reverse && ms->active_count > 0) { 824 if (force_reset) 825 ms->active_count = 0; 826 else 827 ms->active_count--; 828 } else if (!reverse) { 829 ms->active_count++; 830 } 831 832 size_t value_sz = sizeof_ctl_type(type); 833 /* if any value has changed, update the mixer */ 834 for (j = 0; j < ms->num_values; j++) { 835 if (type == MIXER_CTL_TYPE_BYTE) { 836 if (ms->old_value.bytes[j] != ms->new_value.bytes[j]) { 837 if (reverse && ms->active_count > 0) { 838 ALOGD("%s: skip to reset mixer control '%s' in path '%s' " 839 "because it is still needed by other paths", __func__, 840 mixer_ctl_get_name(ms->ctl), name); 841 memcpy(ms->new_value.bytes, ms->old_value.bytes, 842 ms->num_values * value_sz); 843 break; 844 } 845 mixer_ctl_set_array(ms->ctl, ms->new_value.bytes, ms->num_values); 846 memcpy(ms->old_value.bytes, ms->new_value.bytes, ms->num_values * value_sz); 847 break; 848 } 849 } else if (type == MIXER_CTL_TYPE_ENUM) { 850 if (ms->old_value.enumerated[j] != ms->new_value.enumerated[j]) { 851 if (reverse && ms->active_count > 0) { 852 ALOGD("%s: skip to reset mixer control '%s' in path '%s' " 853 "because it is still needed by other paths", __func__, 854 mixer_ctl_get_name(ms->ctl), name); 855 memcpy(ms->new_value.enumerated, ms->old_value.enumerated, 856 ms->num_values * value_sz); 857 break; 858 } 859 mixer_ctl_set_value(ms->ctl, 0, ms->new_value.enumerated[0]); 860 memcpy(ms->old_value.enumerated, ms->new_value.enumerated, 861 ms->num_values * value_sz); 862 break; 863 } 864 } else if (ms->old_value.integer[j] != ms->new_value.integer[j]) { 865 if (reverse && ms->active_count > 0) { 866 ALOGD("%s: skip to reset mixer control '%s' in path '%s' " 867 "because it is still needed by other paths", __func__, 868 mixer_ctl_get_name(ms->ctl), name); 869 memcpy(ms->new_value.integer, ms->old_value.integer, 870 ms->num_values * value_sz); 871 break; 872 } 873 mixer_ctl_set_array(ms->ctl, ms->new_value.integer, ms->num_values); 874 memcpy(ms->old_value.integer, ms->new_value.integer, ms->num_values * value_sz); 875 break; 876 } 877 } 878 } 879 return 0; 880 } 881 882 int audio_route_apply_and_update_path(struct audio_route *ar, const char *name) 883 { 884 if (audio_route_apply_path(ar, name) < 0) { 885 return -1; 886 } 887 return audio_route_update_path(ar, name, DIRECTION_FORWARD); 888 } 889 890 int audio_route_reset_and_update_path(struct audio_route *ar, const char *name) 891 { 892 if (audio_route_reset_path(ar, name) < 0) { 893 return -1; 894 } 895 return audio_route_update_path(ar, name, DIRECTION_REVERSE); 896 } 897 898 int audio_route_force_reset_and_update_path(struct audio_route *ar, const char *name) 899 { 900 if (audio_route_reset_path(ar, name) < 0) { 901 return -1; 902 } 903 904 return audio_route_update_path(ar, name, DIRECTION_REVERSE_RESET); 905 } 906 907 struct audio_route *audio_route_init(unsigned int card, const char *xml_path) 908 { 909 struct config_parse_state state; 910 XML_Parser parser; 911 FILE *file; 912 int bytes_read; 913 void *buf; 914 struct audio_route *ar; 915 916 ar = calloc(1, sizeof(struct audio_route)); 917 if (!ar) 918 goto err_calloc; 919 920 ar->mixer = mixer_open(card); 921 if (!ar->mixer) { 922 ALOGE("Unable to open the mixer, aborting."); 923 goto err_mixer_open; 924 } 925 926 ar->mixer_path = NULL; 927 ar->mixer_path_size = 0; 928 ar->num_mixer_paths = 0; 929 930 /* allocate space for and read current mixer settings */ 931 if (alloc_mixer_state(ar) < 0) 932 goto err_mixer_state; 933 934 /* use the default XML path if none is provided */ 935 if (xml_path == NULL) 936 xml_path = MIXER_XML_PATH; 937 938 file = fopen(xml_path, "r"); 939 940 if (!file) { 941 ALOGE("Failed to open %s: %s", xml_path, strerror(errno)); 942 goto err_fopen; 943 } 944 945 parser = XML_ParserCreate(NULL); 946 if (!parser) { 947 ALOGE("Failed to create XML parser"); 948 goto err_parser_create; 949 } 950 951 memset(&state, 0, sizeof(state)); 952 state.ar = ar; 953 XML_SetUserData(parser, &state); 954 XML_SetElementHandler(parser, start_tag, end_tag); 955 956 for (;;) { 957 buf = XML_GetBuffer(parser, BUF_SIZE); 958 if (buf == NULL) 959 goto err_parse; 960 961 bytes_read = fread(buf, 1, BUF_SIZE, file); 962 if (bytes_read < 0) 963 goto err_parse; 964 965 if (XML_ParseBuffer(parser, bytes_read, 966 bytes_read == 0) == XML_STATUS_ERROR) { 967 ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH); 968 goto err_parse; 969 } 970 971 if (bytes_read == 0) 972 break; 973 } 974 975 /* apply the initial mixer values, and save them so we can reset the 976 mixer to the original values */ 977 audio_route_update_mixer(ar); 978 save_mixer_state(ar); 979 980 XML_ParserFree(parser); 981 fclose(file); 982 return ar; 983 984 err_parse: 985 path_free(ar); 986 XML_ParserFree(parser); 987 err_parser_create: 988 fclose(file); 989 err_fopen: 990 free_mixer_state(ar); 991 err_mixer_state: 992 mixer_close(ar->mixer); 993 err_mixer_open: 994 free(ar); 995 ar = NULL; 996 err_calloc: 997 return NULL; 998 } 999 1000 void audio_route_free(struct audio_route *ar) 1001 { 1002 free_mixer_state(ar); 1003 mixer_close(ar->mixer); 1004 path_free(ar); 1005 free(ar); 1006 } 1007