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