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