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 /*
42 "ctl_values" couples the buffer pointer with a variable "byte_size" to store
43 both types of ctl setting as below in respective ways.
44
45 | fixed-length | tlv-typed byte ctl [note 1]
46 | byte/int/enum ctl |
47 -------------------+-------------------------+--------------------------------
48 alloc buffer size | num_values * size(type) | num_values * 1 [note 2]
49 + +
50 stored value size | always as the full size | can be any size from 1 up to
51 | of allocated buffer | num_values
52 + +
53 "byte_size" value | equal to buffer size, | equal to stored value size,
54 | fixed in runtime | variable according to setting
55
56 additional notes:
57 [1] tlv-typed read/write is not a byte-specific feature but by now it only
58 supports for byte ctls via Tinyalsa API
59 [2] num_values is obtained from mixer_ctl_get_num_values()
60 */
61 struct ctl_values {
62 /* anonymous union */
63 union {
64 int *enumerated;
65 long *integer;
66 void *ptr;
67 unsigned char *bytes;
68 };
69 unsigned int byte_size;
70 };
71
72 struct mixer_state {
73 struct mixer_ctl *ctl;
74 unsigned int num_values;
75 struct ctl_values old_value;
76 struct ctl_values new_value;
77 struct ctl_values reset_value;
78 unsigned int active_count;
79 };
80
81 struct mixer_setting {
82 unsigned int ctl_index;
83 unsigned int num_values;
84 unsigned int type;
85 struct ctl_values value;
86 };
87
88 struct mixer_value {
89 unsigned int ctl_index;
90 int index;
91 long value;
92 /*
93 memory pointed by this is allocated in start_tag during parsing ctl of
94 MIXER_CTL_TYPE_BYTE or MIXER_CTL_TYPE_INT, and is released after the
95 parsed values are updated to either setting value within a path,
96 or top level initial setting value
97 */
98 long *values;
99 unsigned int num_values_in_array;
100 };
101
102 struct mixer_path {
103 char *name;
104 unsigned int size;
105 unsigned int length;
106 struct mixer_setting *setting;
107 };
108
109 struct audio_route {
110 struct mixer *mixer;
111 unsigned int num_mixer_ctls;
112 struct mixer_state *mixer_state;
113
114 unsigned int mixer_path_size;
115 unsigned int num_mixer_paths;
116 struct mixer_path *mixer_path;
117 };
118
119 struct config_parse_state {
120 struct audio_route *ar;
121 struct mixer_path *path;
122 int level;
123 bool enum_mixer_numeric_fallback;
124 };
125
126 static size_t sizeof_ctl_type(enum mixer_ctl_type type);
127
ctl_is_tlv_byte_type(struct mixer_ctl * ctl)128 static bool ctl_is_tlv_byte_type(struct mixer_ctl *ctl)
129 {
130 return mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE && mixer_ctl_is_access_tlv_rw(ctl);
131 }
132
133 /* ctl_values helper functions */
134
ctl_values_alloc(struct ctl_values * value,unsigned int num_values,enum mixer_ctl_type type)135 static int ctl_values_alloc(struct ctl_values *value, unsigned int num_values,
136 enum mixer_ctl_type type)
137 {
138 void *ptr;
139 size_t value_sz = sizeof_ctl_type(type);
140
141 ptr = calloc(num_values, value_sz);
142 if (!ptr)
143 return -1;
144
145 value->ptr = ptr;
146 value->byte_size = num_values * value_sz;
147 return 0;
148 }
149
ctl_values_copy(struct ctl_values * dst,const struct ctl_values * src)150 static void ctl_values_copy(struct ctl_values *dst, const struct ctl_values *src)
151 {
152 /*
153 this should only be used for copying among "ctl_values"-es of a "mixer_state", all of them
154 will be allocated the same size of buffers according to "num_values" obtained from mixer ctl.
155 */
156 memcpy(dst->ptr, src->ptr, src->byte_size);
157 dst->byte_size = src->byte_size;
158 }
159
160 /* path functions */
161
is_supported_ctl_type(enum mixer_ctl_type type)162 static bool is_supported_ctl_type(enum mixer_ctl_type type)
163 {
164 switch (type) {
165 case MIXER_CTL_TYPE_BOOL:
166 case MIXER_CTL_TYPE_INT:
167 case MIXER_CTL_TYPE_ENUM:
168 case MIXER_CTL_TYPE_BYTE:
169 return true;
170 default:
171 return false;
172 }
173 }
174
175 /* as they match in alsa */
sizeof_ctl_type(enum mixer_ctl_type type)176 static size_t sizeof_ctl_type(enum mixer_ctl_type type) {
177 switch (type) {
178 case MIXER_CTL_TYPE_BOOL:
179 case MIXER_CTL_TYPE_INT:
180 return sizeof(long);
181 case MIXER_CTL_TYPE_ENUM:
182 return sizeof(int);
183 case MIXER_CTL_TYPE_BYTE:
184 return sizeof(unsigned char);
185 case MIXER_CTL_TYPE_INT64:
186 case MIXER_CTL_TYPE_IEC958:
187 case MIXER_CTL_TYPE_UNKNOWN:
188 default:
189 LOG_ALWAYS_FATAL("Unsupported mixer ctl type: %d, check type before calling", (int)type);
190 return 0;
191 }
192 }
193
index_to_ctl(struct audio_route * ar,unsigned int ctl_index)194 static inline struct mixer_ctl *index_to_ctl(struct audio_route *ar,
195 unsigned int ctl_index)
196 {
197 return ar->mixer_state[ctl_index].ctl;
198 }
199
200 #if 0
201 static void path_print(struct audio_route *ar, struct mixer_path *path)
202 {
203 unsigned int i;
204 unsigned int j;
205
206 ALOGE("Path: %s, length: %d", path->name, path->length);
207 for (i = 0; i < path->length; i++) {
208 struct mixer_ctl *ctl = index_to_ctl(ar, path->setting[i].ctl_index);
209
210 ALOGE(" id=%d: ctl=%s", i, mixer_ctl_get_name(ctl));
211 if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) {
212 for (j = 0; j < path->setting[i].num_values; j++)
213 ALOGE(" id=%d value=0x%02x", j, path->setting[i].value.bytes[j]);
214 } else if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_ENUM) {
215 for (j = 0; j < path->setting[i].num_values; j++)
216 ALOGE(" id=%d value=%d", j, path->setting[i].value.enumerated[j]);
217 } else {
218 for (j = 0; j < path->setting[i].num_values; j++)
219 ALOGE(" id=%d value=%ld", j, path->setting[i].value.integer[j]);
220 }
221 }
222 }
223 #endif
224
path_free(struct audio_route * ar)225 static void path_free(struct audio_route *ar)
226 {
227 unsigned int i;
228
229 for (i = 0; i < ar->num_mixer_paths; i++) {
230 free(ar->mixer_path[i].name);
231 if (ar->mixer_path[i].setting) {
232 size_t j;
233 for (j = 0; j < ar->mixer_path[i].length; j++) {
234 free(ar->mixer_path[i].setting[j].value.ptr);
235 }
236 free(ar->mixer_path[i].setting);
237 ar->mixer_path[i].size = 0;
238 ar->mixer_path[i].length = 0;
239 ar->mixer_path[i].setting = NULL;
240 }
241 }
242 free(ar->mixer_path);
243 ar->mixer_path = NULL;
244 ar->mixer_path_size = 0;
245 ar->num_mixer_paths = 0;
246 }
247
path_get_by_name(struct audio_route * ar,const char * name)248 static struct mixer_path *path_get_by_name(struct audio_route *ar,
249 const char *name)
250 {
251 unsigned int i;
252
253 for (i = 0; i < ar->num_mixer_paths; i++)
254 if (strcmp(ar->mixer_path[i].name, name) == 0)
255 return &ar->mixer_path[i];
256
257 return NULL;
258 }
259
path_create(struct audio_route * ar,const char * name)260 static struct mixer_path *path_create(struct audio_route *ar, const char *name)
261 {
262 struct mixer_path *new_mixer_path = NULL;
263
264 if (path_get_by_name(ar, name)) {
265 ALOGW("Path name '%s' already exists", name);
266 return NULL;
267 }
268
269 /* check if we need to allocate more space for mixer paths */
270 if (ar->mixer_path_size <= ar->num_mixer_paths) {
271 if (ar->mixer_path_size == 0)
272 ar->mixer_path_size = INITIAL_MIXER_PATH_SIZE;
273 else
274 ar->mixer_path_size *= 2;
275
276 new_mixer_path = realloc(ar->mixer_path, ar->mixer_path_size *
277 sizeof(struct mixer_path));
278 if (new_mixer_path == NULL) {
279 ALOGE("Unable to allocate more paths");
280 return NULL;
281 } else {
282 ar->mixer_path = new_mixer_path;
283 }
284 }
285
286 /* initialise the new mixer path */
287 ar->mixer_path[ar->num_mixer_paths].name = strdup(name);
288 ar->mixer_path[ar->num_mixer_paths].size = 0;
289 ar->mixer_path[ar->num_mixer_paths].length = 0;
290 ar->mixer_path[ar->num_mixer_paths].setting = NULL;
291
292 /* return the mixer path just added, then increment number of them */
293 return &ar->mixer_path[ar->num_mixer_paths++];
294 }
295
find_ctl_index_in_path(struct mixer_path * path,unsigned int ctl_index)296 static int find_ctl_index_in_path(struct mixer_path *path,
297 unsigned int ctl_index)
298 {
299 unsigned int i;
300
301 for (i = 0; i < path->length; i++)
302 if (path->setting[i].ctl_index == ctl_index)
303 return i;
304
305 return -1;
306 }
307
alloc_path_setting(struct mixer_path * path)308 static int alloc_path_setting(struct mixer_path *path)
309 {
310 struct mixer_setting *new_path_setting;
311 int path_index;
312
313 /* check if we need to allocate more space for path settings */
314 if (path->size <= path->length) {
315 if (path->size == 0)
316 path->size = INITIAL_MIXER_PATH_SIZE;
317 else
318 path->size *= 2;
319
320 new_path_setting = realloc(path->setting,
321 path->size * sizeof(struct mixer_setting));
322 if (new_path_setting == NULL) {
323 ALOGE("Unable to allocate more path settings");
324 return -1;
325 } else {
326 path->setting = new_path_setting;
327 }
328 }
329
330 path_index = path->length;
331 path->length++;
332
333 return path_index;
334 }
335
path_add_setting(struct audio_route * ar,struct mixer_path * path,struct mixer_setting * setting)336 static int path_add_setting(struct audio_route *ar, struct mixer_path *path,
337 struct mixer_setting *setting)
338 {
339 int path_index;
340 int rc;
341
342 if (find_ctl_index_in_path(path, setting->ctl_index) != -1) {
343 struct mixer_ctl *ctl = index_to_ctl(ar, setting->ctl_index);
344
345 ALOGW("Control '%s' already exists in path '%s' - Ignore one in the new sub path",
346 mixer_ctl_get_name(ctl), path->name);
347 return -2;
348 }
349
350 if (!is_supported_ctl_type(setting->type)) {
351 ALOGE("unsupported type %d", (int)setting->type);
352 return -1;
353 }
354
355 path_index = alloc_path_setting(path);
356 if (path_index < 0)
357 return -1;
358
359 path->setting[path_index].ctl_index = setting->ctl_index;
360 path->setting[path_index].type = setting->type;
361 path->setting[path_index].num_values = setting->num_values;
362
363 rc = ctl_values_alloc(&path->setting[path_index].value, setting->num_values, setting->type);
364 if (rc < 0) {
365 ALOGE("failed to allocate mem for path setting");
366 return rc;
367 }
368 /* copy all values */
369 ctl_values_copy(&path->setting[path_index].value, &setting->value);
370
371 return 0;
372 }
373
path_add_value(struct audio_route * ar,struct mixer_path * path,struct mixer_value * mixer_value)374 static int path_add_value(struct audio_route *ar, struct mixer_path *path,
375 struct mixer_value *mixer_value)
376 {
377 unsigned int i;
378 int path_index;
379 unsigned int num_values;
380 struct mixer_ctl *ctl;
381 int rc;
382
383 /* Check that mixer value index is within range */
384 ctl = index_to_ctl(ar, mixer_value->ctl_index);
385 num_values = mixer_ctl_get_num_values(ctl);
386 if (mixer_value->index >= (int)num_values) {
387 ALOGE("mixer index %d is out of range for '%s'", mixer_value->index,
388 mixer_ctl_get_name(ctl));
389 return -1;
390 }
391
392 path_index = find_ctl_index_in_path(path, mixer_value->ctl_index);
393 if (path_index < 0) {
394 /* New path */
395
396 enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
397 if (!is_supported_ctl_type(type)) {
398 ALOGE("unsupported type %d", (int)type);
399 return -1;
400 }
401 path_index = alloc_path_setting(path);
402 if (path_index < 0)
403 return -1;
404
405 /* initialise the new path setting */
406 path->setting[path_index].ctl_index = mixer_value->ctl_index;
407 path->setting[path_index].num_values = num_values;
408 path->setting[path_index].type = type;
409
410 rc = ctl_values_alloc(&path->setting[path_index].value, num_values, type);
411 if (rc < 0) {
412 ALOGE("failed to allocate mem for path setting");
413 return rc;
414 }
415 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
416 path->setting[path_index].value.bytes[0] = mixer_value->value;
417 else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
418 path->setting[path_index].value.enumerated[0] = mixer_value->value;
419 else
420 path->setting[path_index].value.integer[0] = mixer_value->value;
421 }
422
423 if (mixer_value->index == -1) {
424 /* set all values the same except for CTL_TYPE_BYTE and CTL_TYPE_INT */
425 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE) {
426 /* update the number of values (bytes) from input "mixer_value" */
427 for (i = 0; i < mixer_value->num_values_in_array; i++)
428 path->setting[path_index].value.bytes[i] = mixer_value->values[i];
429 path->setting[path_index].value.byte_size = mixer_value->num_values_in_array;
430 } else if (path->setting[path_index].type == MIXER_CTL_TYPE_INT) {
431 for (i = 0; i < num_values; i++)
432 path->setting[path_index].value.integer[i] = mixer_value->values[i];
433 } else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM) {
434 for (i = 0; i < num_values; i++)
435 path->setting[path_index].value.enumerated[i] = mixer_value->value;
436 } else {
437 for (i = 0; i < num_values; i++)
438 path->setting[path_index].value.integer[i] = mixer_value->value;
439 }
440 } else {
441 /* set only one value */
442 if (path->setting[path_index].type == MIXER_CTL_TYPE_BYTE)
443 path->setting[path_index].value.bytes[mixer_value->index] = mixer_value->value;
444 else if (path->setting[path_index].type == MIXER_CTL_TYPE_ENUM)
445 path->setting[path_index].value.enumerated[mixer_value->index] = mixer_value->value;
446 else
447 path->setting[path_index].value.integer[mixer_value->index] = mixer_value->value;
448 }
449
450 return 0;
451 }
452
path_add_path(struct audio_route * ar,struct mixer_path * path,struct mixer_path * sub_path)453 static int path_add_path(struct audio_route *ar, struct mixer_path *path,
454 struct mixer_path *sub_path)
455 {
456 unsigned int i;
457
458 for (i = 0; i < sub_path->length; i++) {
459 int retVal = path_add_setting(ar, path, &sub_path->setting[i]);
460 if (retVal < 0) {
461 if (retVal == -2)
462 continue;
463 else
464 return -1;
465 }
466 }
467 return 0;
468 }
469
path_apply(struct audio_route * ar,struct mixer_path * path)470 static int path_apply(struct audio_route *ar, struct mixer_path *path)
471 {
472 unsigned int i;
473 unsigned int ctl_index;
474 struct mixer_ctl *ctl;
475 enum mixer_ctl_type type;
476
477 ALOGD("Apply path: %s", path->name != NULL ? path->name : "none");
478 for (i = 0; i < path->length; i++) {
479 ctl_index = path->setting[i].ctl_index;
480 ctl = index_to_ctl(ar, ctl_index);
481 type = mixer_ctl_get_type(ctl);
482 if (!is_supported_ctl_type(type))
483 continue;
484 ctl_values_copy(&ar->mixer_state[ctl_index].new_value, &path->setting[i].value);
485 }
486
487 return 0;
488 }
489
path_reset(struct audio_route * ar,struct mixer_path * path)490 static int path_reset(struct audio_route *ar, struct mixer_path *path)
491 {
492 unsigned int i;
493 unsigned int ctl_index;
494 struct mixer_ctl *ctl;
495 enum mixer_ctl_type type;
496
497 ALOGV("Reset path: %s", path->name != NULL ? path->name : "none");
498 for (i = 0; i < path->length; i++) {
499 ctl_index = path->setting[i].ctl_index;
500 ctl = index_to_ctl(ar, ctl_index);
501 type = mixer_ctl_get_type(ctl);
502 if (!is_supported_ctl_type(type))
503 continue;
504 /* reset the value(s) */
505 ctl_values_copy(&ar->mixer_state[ctl_index].new_value,
506 &ar->mixer_state[ctl_index].reset_value);
507 }
508
509 return 0;
510 }
511
safe_strtol(const char * str,long * val)512 static bool safe_strtol(const char *str, long *val)
513 {
514 char *end;
515 long v;
516 if (str == NULL || strlen(str) == 0)
517 return false;
518 errno = 0;
519 v = strtol(str, &end, 0);
520 if (errno || *end)
521 return false;
522 *val = v;
523 return true;
524 }
525
526 /* mixer helper function */
mixer_enum_string_to_value(struct mixer_ctl * ctl,const char * string,bool allow_numeric_fallback)527 static int mixer_enum_string_to_value(struct mixer_ctl *ctl, const char *string,
528 bool allow_numeric_fallback)
529 {
530 unsigned int i;
531 unsigned int num_values = mixer_ctl_get_num_enums(ctl);
532
533 if (string == NULL) {
534 ALOGE("NULL enum value string passed to mixer_enum_string_to_value() for ctl %s",
535 mixer_ctl_get_name(ctl));
536 return 0;
537 }
538
539 /* Search the enum strings for a particular one */
540 for (i = 0; i < num_values; i++) {
541 if (strcmp(mixer_ctl_get_enum_string(ctl, i), string) == 0)
542 break;
543 }
544 if (i == num_values) {
545 /* No enum string match. Check the flag before numeric parsing. */
546 if (allow_numeric_fallback) {
547 long value = 0;
548 if (safe_strtol(string, &value) && value >= 0 && value < num_values) {
549 return value;
550 }
551 }
552 ALOGW("unknown enum value string %s for ctl %s",
553 string, mixer_ctl_get_name(ctl));
554 return 0;
555 }
556 return i;
557 }
558
mixer_get_bytes_from_file(long ** value_array,const char * filepath,unsigned int max_bytes)559 static int mixer_get_bytes_from_file(long **value_array, const char *filepath,
560 unsigned int max_bytes)
561 {
562 unsigned char *buf = NULL;
563 long *values = NULL;
564 int bytes_read = -1;
565 unsigned int i;
566
567 FILE *file = fopen(filepath, "rb");
568 if (!file) {
569 ALOGE("Failed to open %s: %s", filepath, strerror(errno));
570 return -1;
571 }
572
573 buf = calloc(max_bytes, 1);
574 if (!buf) {
575 ALOGE("failed to allocate mem for file read buffer");
576 goto exit;
577 }
578
579 bytes_read = fread(buf, 1, max_bytes, file);
580 if (bytes_read < 0) {
581 ALOGE("failed to read data from file, rc: %d", bytes_read);
582 goto exit;
583 }
584
585 values = calloc(bytes_read, sizeof(long));
586 if (!values) {
587 ALOGE("failed to allocate mem for values array");
588 bytes_read = -1;
589 goto exit;
590 }
591
592 for (i = 0; i < bytes_read; i++) {
593 values[i] = (long)buf[i];
594 }
595 *value_array = values;
596
597 exit:
598 free(buf);
599 fclose(file);
600 return bytes_read;
601 }
602
start_tag(void * data,const XML_Char * tag_name,const XML_Char ** attr)603 static void start_tag(void *data, const XML_Char *tag_name,
604 const XML_Char **attr)
605 {
606 const XML_Char *attr_name = NULL;
607 const XML_Char *attr_id = NULL;
608 const XML_Char *attr_value = NULL;
609 const XML_Char *attr_enum_mixer_numeric_fallback = NULL;
610 const XML_Char *attr_bin = NULL;
611 struct config_parse_state *state = data;
612 struct audio_route *ar = state->ar;
613 unsigned int i;
614 unsigned int ctl_index;
615 struct mixer_ctl *ctl;
616 long value;
617 unsigned int id;
618 struct mixer_value mixer_value;
619 enum mixer_ctl_type type;
620 long* value_array = NULL;
621 unsigned int num_values_in_array = 0;
622
623 /* Get name, id and value attributes (these may be empty) */
624 for (i = 0; attr[i]; i += 2) {
625 if (strcmp(attr[i], "name") == 0)
626 attr_name = attr[i + 1];
627 else if (strcmp(attr[i], "id") == 0)
628 attr_id = attr[i + 1];
629 else if (strcmp(attr[i], "value") == 0)
630 attr_value = attr[i + 1];
631 else if (strcmp(attr[i], "enum_mixer_numeric_fallback") == 0)
632 attr_enum_mixer_numeric_fallback = attr[i + 1];
633 else if (strcmp(attr[i], "bin") == 0)
634 attr_bin = attr[i + 1];
635 }
636
637 /* Look at tags */
638 if (strcmp(tag_name, "mixer") == 0) {
639 state->enum_mixer_numeric_fallback =
640 attr_enum_mixer_numeric_fallback != NULL &&
641 strcmp(attr_enum_mixer_numeric_fallback, "true") == 0 ;
642 } else if (strcmp(tag_name, "path") == 0) {
643 if (attr_name == NULL) {
644 ALOGE("Unnamed path!");
645 } else {
646 if (state->level == 1) {
647 /* top level path: create and stash the path */
648 state->path = path_create(ar, (char *)attr_name);
649 if (state->path == NULL)
650 ALOGW("path creation failed, please check if the path exists");
651 } else {
652 /* nested path */
653 struct mixer_path *sub_path = path_get_by_name(ar, attr_name);
654 if (!sub_path) {
655 ALOGW("unable to find sub path '%s'", attr_name);
656 } else if (state->path != NULL) {
657 path_add_path(ar, state->path, sub_path);
658 }
659 }
660 }
661 } else if (strcmp(tag_name, "ctl") == 0) {
662 /* Obtain the mixer ctl and value */
663 ctl = mixer_get_ctl_by_name(ar->mixer, attr_name);
664 if (ctl == NULL) {
665 ALOGW("Control '%s' doesn't exist - skipping", attr_name);
666 goto done;
667 }
668
669 switch (mixer_ctl_get_type(ctl)) {
670 case MIXER_CTL_TYPE_BOOL:
671 if (attr_value == NULL) {
672 ALOGE("No value specified for ctl %s", attr_name);
673 goto done;
674 }
675 value = strtol((char *)attr_value, NULL, 0);
676 break;
677 case MIXER_CTL_TYPE_INT:
678 case MIXER_CTL_TYPE_BYTE: {
679 char *attr_sub_value, *test_r;
680 unsigned int num_values = mixer_ctl_get_num_values(ctl);
681
682 if (attr_bin && mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE) {
683 /* get byte values from binfile */
684 int bytes_read = mixer_get_bytes_from_file(&value_array, attr_bin, num_values);
685 if (bytes_read <= 0) {
686 ALOGE("failed to get bytes from file '%s'", attr_bin);
687 goto done;
688 }
689 if (bytes_read < num_values && mixer_ctl_is_access_tlv_rw(ctl) == 0) {
690 ALOGE("expect %d values but only %d specified for ctl %s",
691 num_values, bytes_read, attr_name);
692 goto done;
693 }
694 num_values_in_array = bytes_read;
695 break;
696 }
697
698 if (attr_value == NULL) {
699 ALOGE("No value specified for ctl %s", attr_name);
700 goto done;
701 }
702 value_array = calloc(num_values, sizeof(long));
703 if (!value_array) {
704 ALOGE("failed to allocate mem for ctl %s", attr_name);
705 goto done;
706 }
707 for (i = 0; i < num_values; i++) {
708 attr_sub_value = strtok_r((char *)attr_value, " ", &test_r);
709 if (attr_sub_value == NULL) {
710 /* the length of setting for tlv-typed byte control
711 can be any size up to num_value; break the loop so
712 the current count of values will be recorded */
713 if (ctl_is_tlv_byte_type(ctl))
714 break;
715
716 ALOGE("expect %d values but only %d specified for ctl %s",
717 num_values, i, attr_name);
718 goto done;
719 }
720 if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_INT)
721 value_array[i] = strtol((char *)attr_sub_value, NULL, 0);
722 else
723 value_array[i] =
724 (unsigned char) strtol((char *)attr_sub_value, NULL, 16);
725
726 /* count the number of values written in array */
727 num_values_in_array++;
728
729 if (attr_id)
730 break;
731
732 attr_value = NULL;
733 }
734 } break;
735 case MIXER_CTL_TYPE_ENUM:
736 if (attr_value == NULL) {
737 ALOGE("No value specified for ctl %s", attr_name);
738 goto done;
739 }
740 value = mixer_enum_string_to_value(ctl, (char *)attr_value,
741 state->enum_mixer_numeric_fallback);
742 break;
743 default:
744 value = 0;
745 break;
746 }
747
748 /* locate the mixer ctl in the list */
749 for (ctl_index = 0; ctl_index < ar->num_mixer_ctls; ctl_index++) {
750 if (ar->mixer_state[ctl_index].ctl == ctl)
751 break;
752 }
753
754 if (state->level == 1) {
755 /* top level ctl (initial setting) */
756
757 type = mixer_ctl_get_type(ctl);
758 if (is_supported_ctl_type(type)) {
759 /* apply the new value */
760 if (attr_id) {
761 /* set only one value */
762 id = atoi((char *)attr_id);
763 if (id < ar->mixer_state[ctl_index].num_values)
764 if (type == MIXER_CTL_TYPE_BYTE)
765 ar->mixer_state[ctl_index].new_value.bytes[id] = value_array[0];
766 else if (type == MIXER_CTL_TYPE_INT)
767 ar->mixer_state[ctl_index].new_value.integer[id] = value_array[0];
768 else if (type == MIXER_CTL_TYPE_ENUM)
769 ar->mixer_state[ctl_index].new_value.enumerated[id] = value;
770 else
771 ar->mixer_state[ctl_index].new_value.integer[id] = value;
772 else
773 ALOGW("value id out of range for mixer ctl '%s'",
774 mixer_ctl_get_name(ctl));
775 } else if (ctl_is_tlv_byte_type(ctl)) {
776 /* for tlv-typed ctl, only set the number of values (bytes) carried by array,
777 and update the number of bytes */
778 for (i = 0; i < num_values_in_array; i++)
779 ar->mixer_state[ctl_index].new_value.bytes[i] = value_array[i];
780 ar->mixer_state[ctl_index].new_value.byte_size = num_values_in_array;
781 } else {
782 /* set all values the same except for CTL_TYPE_BYTE and CTL_TYPE_INT */
783 for (i = 0; i < ar->mixer_state[ctl_index].num_values; i++)
784 if (type == MIXER_CTL_TYPE_BYTE)
785 ar->mixer_state[ctl_index].new_value.bytes[i] = value_array[i];
786 else if (type == MIXER_CTL_TYPE_INT)
787 ar->mixer_state[ctl_index].new_value.integer[i] = value_array[i];
788 else if (type == MIXER_CTL_TYPE_ENUM)
789 ar->mixer_state[ctl_index].new_value.enumerated[i] = value;
790 else
791 ar->mixer_state[ctl_index].new_value.integer[i] = value;
792 }
793 }
794 } else {
795 /* nested ctl (within a path) */
796 mixer_value.ctl_index = ctl_index;
797 if (mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_BYTE ||
798 mixer_ctl_get_type(ctl) == MIXER_CTL_TYPE_INT) {
799 mixer_value.values = value_array;
800 mixer_value.value = value_array[0];
801 mixer_value.num_values_in_array = num_values_in_array;
802 } else {
803 mixer_value.value = value;
804 }
805 if (attr_id)
806 mixer_value.index = atoi((char *)attr_id);
807 else
808 mixer_value.index = -1;
809 if (state->path != NULL)
810 path_add_value(ar, state->path, &mixer_value);
811 }
812 }
813
814 done:
815 free(value_array);
816 state->level++;
817 }
818
end_tag(void * data,const XML_Char * tag_name)819 static void end_tag(void *data, const XML_Char *tag_name)
820 {
821 struct config_parse_state *state = data;
822 (void)tag_name;
823
824 state->level--;
825 }
826
alloc_mixer_state(struct audio_route * ar)827 static int alloc_mixer_state(struct audio_route *ar)
828 {
829 unsigned int i;
830 unsigned int num_values;
831 struct mixer_ctl *ctl;
832 enum mixer_ctl_type type;
833
834 ar->num_mixer_ctls = mixer_get_num_ctls(ar->mixer);
835 ar->mixer_state = calloc(ar->num_mixer_ctls, sizeof(struct mixer_state));
836 if (!ar->mixer_state)
837 return -1;
838
839 for (i = 0; i < ar->num_mixer_ctls; i++) {
840 ctl = mixer_get_ctl(ar->mixer, i);
841 num_values = mixer_ctl_get_num_values(ctl);
842
843 ar->mixer_state[i].ctl = ctl;
844 ar->mixer_state[i].num_values = num_values;
845 ar->mixer_state[i].active_count = 0;
846
847 /* Skip unsupported types that are not supported yet in XML */
848 type = mixer_ctl_get_type(ctl);
849
850 if (!is_supported_ctl_type(type))
851 continue;
852
853 /*
854 for tlv-typed ctl, "mixer_ctl_get_num_values()" returns the max length of a
855 setting data. The buffer size allocated per mixer setting should align the
856 max length to be capable of carrying any length of data.
857 */
858 ctl_values_alloc(&ar->mixer_state[i].old_value, num_values, type);
859 ctl_values_alloc(&ar->mixer_state[i].new_value, num_values, type);
860 ctl_values_alloc(&ar->mixer_state[i].reset_value, num_values, type);
861
862 if (type == MIXER_CTL_TYPE_ENUM)
863 ar->mixer_state[i].old_value.enumerated[0] = mixer_ctl_get_value(ctl, 0);
864 else
865 mixer_ctl_get_array(ctl, ar->mixer_state[i].old_value.ptr, num_values);
866
867 ctl_values_copy(&ar->mixer_state[i].new_value, &ar->mixer_state[i].old_value);
868 }
869
870 return 0;
871 }
872
free_mixer_state(struct audio_route * ar)873 static void free_mixer_state(struct audio_route *ar)
874 {
875 unsigned int i;
876 enum mixer_ctl_type type;
877
878 for (i = 0; i < ar->num_mixer_ctls; i++) {
879 type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
880 if (!is_supported_ctl_type(type))
881 continue;
882
883 free(ar->mixer_state[i].old_value.ptr);
884 free(ar->mixer_state[i].new_value.ptr);
885 free(ar->mixer_state[i].reset_value.ptr);
886 }
887
888 free(ar->mixer_state);
889 ar->mixer_state = NULL;
890 }
891
mixer_set_value_if_changed(struct mixer_state * ms)892 static void mixer_set_value_if_changed(struct mixer_state *ms)
893 {
894 unsigned int i;
895 struct mixer_ctl *ctl = ms->ctl;
896 enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
897
898 if (type == MIXER_CTL_TYPE_BYTE) {
899 unsigned int num_bytes;
900 /*
901 for tlv-typed ctl, "mixer_ctl_set_array()" should specify the length of data to
902 be set, thus the data can be wrapped into tlv format correctly by Tinyalsa.
903 */
904 num_bytes = ctl_is_tlv_byte_type(ctl) ? ms->new_value.byte_size : ms->num_values;
905 for (i = 0; i < num_bytes; i++) {
906 if (ms->old_value.bytes[i] != ms->new_value.bytes[i]) {
907 mixer_ctl_set_array(ctl, ms->new_value.ptr, num_bytes);
908 ctl_values_copy(&ms->old_value, &ms->new_value);
909 return;
910 }
911 }
912 } else if (type == MIXER_CTL_TYPE_ENUM) {
913 for (i = 0; i < ms->num_values; i++) {
914 if (ms->old_value.enumerated[i] != ms->new_value.enumerated[i]) {
915 mixer_ctl_set_value(ctl, 0, ms->new_value.enumerated[0]);
916 ctl_values_copy(&ms->old_value, &ms->new_value);
917 return;
918 }
919 }
920 } else {
921 for (i = 0; i < ms->num_values; i++) {
922 if (ms->old_value.integer[i] != ms->new_value.integer[i]) {
923 mixer_ctl_set_array(ctl, ms->new_value.ptr, ms->num_values);
924 ctl_values_copy(&ms->old_value, &ms->new_value);
925 return;
926 }
927 }
928 }
929 }
930
931 /* Update the mixer with any changed values */
audio_route_update_mixer(struct audio_route * ar)932 int audio_route_update_mixer(struct audio_route *ar)
933 {
934 unsigned int i;
935 struct mixer_ctl *ctl;
936
937 for (i = 0; i < ar->num_mixer_ctls; i++) {
938 enum mixer_ctl_type type;
939
940 ctl = ar->mixer_state[i].ctl;
941
942 /* Skip unsupported types */
943 type = mixer_ctl_get_type(ctl);
944 if (!is_supported_ctl_type(type))
945 continue;
946
947 /* if the value has changed, update the mixer */
948 mixer_set_value_if_changed(&ar->mixer_state[i]);
949 }
950
951 return 0;
952 }
953
954 /* saves the current state of the mixer, for resetting all controls */
save_mixer_state(struct audio_route * ar)955 static void save_mixer_state(struct audio_route *ar)
956 {
957 unsigned int i;
958 enum mixer_ctl_type type;
959
960 for (i = 0; i < ar->num_mixer_ctls; i++) {
961 type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
962 if (!is_supported_ctl_type(type))
963 continue;
964
965 ctl_values_copy(&ar->mixer_state[i].reset_value, &ar->mixer_state[i].new_value);
966 }
967 }
968
969 /* Reset the audio routes back to the initial state */
audio_route_reset(struct audio_route * ar)970 void audio_route_reset(struct audio_route *ar)
971 {
972 unsigned int i;
973 enum mixer_ctl_type type;
974
975 /* load all of the saved values */
976 for (i = 0; i < ar->num_mixer_ctls; i++) {
977 type = mixer_ctl_get_type(ar->mixer_state[i].ctl);
978 if (!is_supported_ctl_type(type))
979 continue;
980
981 ctl_values_copy(&ar->mixer_state[i].new_value, &ar->mixer_state[i].reset_value);
982 }
983 }
984
985 /* Apply an audio route path by name */
audio_route_apply_path(struct audio_route * ar,const char * name)986 int audio_route_apply_path(struct audio_route *ar, const char *name)
987 {
988 struct mixer_path *path;
989
990 if (!ar) {
991 ALOGE("invalid audio_route");
992 return -1;
993 }
994
995 path = path_get_by_name(ar, name);
996 if (!path) {
997 ALOGE("unable to find path '%s'", name);
998 return -1;
999 }
1000
1001 path_apply(ar, path);
1002
1003 return 0;
1004 }
1005
1006 /* Reset an audio route path by name */
audio_route_reset_path(struct audio_route * ar,const char * name)1007 int audio_route_reset_path(struct audio_route *ar, const char *name)
1008 {
1009 struct mixer_path *path;
1010
1011 if (!ar) {
1012 ALOGE("invalid audio_route");
1013 return -1;
1014 }
1015
1016 path = path_get_by_name(ar, name);
1017 if (!path) {
1018 ALOGE("unable to find path '%s'", name);
1019 return -1;
1020 }
1021
1022 path_reset(ar, path);
1023
1024 return 0;
1025 }
1026
1027 /*
1028 * Operates on the specified path .. controls will be updated in the
1029 * order listed in the XML file
1030 */
audio_route_update_path(struct audio_route * ar,const char * name,int direction)1031 static int audio_route_update_path(struct audio_route *ar, const char *name, int direction)
1032 {
1033 struct mixer_path *path;
1034 unsigned int j;
1035 bool reverse = direction != DIRECTION_FORWARD;
1036 bool force_reset = direction == DIRECTION_REVERSE_RESET;
1037
1038 if (!ar) {
1039 ALOGE("invalid audio_route");
1040 return -1;
1041 }
1042
1043 path = path_get_by_name(ar, name);
1044 if (!path) {
1045 ALOGE("unable to find path '%s'", name);
1046 return -1;
1047 }
1048
1049 for (size_t i = 0; i < path->length; ++i) {
1050 unsigned int ctl_index;
1051 enum mixer_ctl_type type;
1052
1053 ctl_index = path->setting[reverse ? path->length - 1 - i : i].ctl_index;
1054
1055 struct mixer_state * ms = &ar->mixer_state[ctl_index];
1056
1057 type = mixer_ctl_get_type(ms->ctl);
1058 if (!is_supported_ctl_type(type)) {
1059 continue;
1060 }
1061
1062 if (reverse && ms->active_count > 0) {
1063 if (force_reset) {
1064 ms->active_count = 0;
1065 } else if (--ms->active_count > 0) {
1066 ALOGD("%s: skip to reset mixer control '%s' in path '%s' "
1067 "because it is still needed by other paths", __func__,
1068 mixer_ctl_get_name(ms->ctl), name);
1069 ctl_values_copy(&ms->new_value, &ms->old_value);
1070 continue;
1071 }
1072 } else if (!reverse) {
1073 ms->active_count++;
1074 }
1075
1076 /* if any value has changed, update the mixer */
1077 mixer_set_value_if_changed(ms);
1078 }
1079 return 0;
1080 }
1081
audio_route_apply_and_update_path(struct audio_route * ar,const char * name)1082 int audio_route_apply_and_update_path(struct audio_route *ar, const char *name)
1083 {
1084 if (audio_route_apply_path(ar, name) < 0) {
1085 return -1;
1086 }
1087 return audio_route_update_path(ar, name, DIRECTION_FORWARD);
1088 }
1089
audio_route_reset_and_update_path(struct audio_route * ar,const char * name)1090 int audio_route_reset_and_update_path(struct audio_route *ar, const char *name)
1091 {
1092 if (audio_route_reset_path(ar, name) < 0) {
1093 return -1;
1094 }
1095 return audio_route_update_path(ar, name, DIRECTION_REVERSE);
1096 }
1097
audio_route_force_reset_and_update_path(struct audio_route * ar,const char * name)1098 int audio_route_force_reset_and_update_path(struct audio_route *ar, const char *name)
1099 {
1100 if (audio_route_reset_path(ar, name) < 0) {
1101 return -1;
1102 }
1103
1104 return audio_route_update_path(ar, name, DIRECTION_REVERSE_RESET);
1105 }
1106
audio_route_supports_path(struct audio_route * ar,const char * name)1107 int audio_route_supports_path(struct audio_route *ar, const char *name)
1108 {
1109 if (!path_get_by_name(ar, name)) {
1110 return -1;
1111 }
1112
1113 return 0;
1114 }
1115
audio_route_init(unsigned int card,const char * xml_path)1116 struct audio_route *audio_route_init(unsigned int card, const char *xml_path)
1117 {
1118 struct config_parse_state state;
1119 XML_Parser parser;
1120 FILE *file;
1121 int bytes_read;
1122 void *buf;
1123 struct audio_route *ar;
1124
1125 ar = calloc(1, sizeof(struct audio_route));
1126 if (!ar)
1127 goto err_calloc;
1128
1129 ar->mixer = mixer_open(card);
1130 if (!ar->mixer) {
1131 ALOGE("Unable to open the mixer, aborting.");
1132 goto err_mixer_open;
1133 }
1134
1135 ar->mixer_path = NULL;
1136 ar->mixer_path_size = 0;
1137 ar->num_mixer_paths = 0;
1138
1139 /* allocate space for and read current mixer settings */
1140 if (alloc_mixer_state(ar) < 0)
1141 goto err_mixer_state;
1142
1143 /* use the default XML path if none is provided */
1144 if (xml_path == NULL)
1145 xml_path = MIXER_XML_PATH;
1146
1147 file = fopen(xml_path, "r");
1148
1149 if (!file) {
1150 ALOGE("Failed to open %s: %s", xml_path, strerror(errno));
1151 goto err_fopen;
1152 }
1153
1154 parser = XML_ParserCreate(NULL);
1155 if (!parser) {
1156 ALOGE("Failed to create XML parser");
1157 goto err_parser_create;
1158 }
1159
1160 memset(&state, 0, sizeof(state));
1161 state.ar = ar;
1162 XML_SetUserData(parser, &state);
1163 XML_SetElementHandler(parser, start_tag, end_tag);
1164
1165 for (;;) {
1166 buf = XML_GetBuffer(parser, BUF_SIZE);
1167 if (buf == NULL)
1168 goto err_parse;
1169
1170 bytes_read = fread(buf, 1, BUF_SIZE, file);
1171 if (bytes_read < 0)
1172 goto err_parse;
1173
1174 if (XML_ParseBuffer(parser, bytes_read,
1175 bytes_read == 0) == XML_STATUS_ERROR) {
1176 ALOGE("Error in mixer xml (%s)", MIXER_XML_PATH);
1177 goto err_parse;
1178 }
1179
1180 if (bytes_read == 0)
1181 break;
1182 }
1183
1184 /* apply the initial mixer values, and save them so we can reset the
1185 mixer to the original values */
1186 audio_route_update_mixer(ar);
1187 save_mixer_state(ar);
1188
1189 XML_ParserFree(parser);
1190 fclose(file);
1191 return ar;
1192
1193 err_parse:
1194 path_free(ar);
1195 XML_ParserFree(parser);
1196 err_parser_create:
1197 fclose(file);
1198 err_fopen:
1199 free_mixer_state(ar);
1200 err_mixer_state:
1201 mixer_close(ar->mixer);
1202 err_mixer_open:
1203 free(ar);
1204 ar = NULL;
1205 err_calloc:
1206 return NULL;
1207 }
1208
audio_route_free(struct audio_route * ar)1209 void audio_route_free(struct audio_route *ar)
1210 {
1211 free_mixer_state(ar);
1212 mixer_close(ar->mixer);
1213 path_free(ar);
1214 free(ar);
1215 }
1216