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