Home | History | Annotate | Download | only in libalsa-intf
      1 /*
      2  * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *   * Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  *   * Redistributions in binary form must reproduce the above
     10  *     copyright notice, this list of conditions and the following
     11  *     disclaimer in the documentation and/or other materials provided
     12  *     with the distribution.
     13  *   * Neither the name of Code Aurora Forum, Inc. nor the names of its
     14  *     contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 #define LOG_TAG "alsa_ucm"
     30 //#define LOG_NDDEBUG 0
     31 
     32 #ifdef ANDROID
     33 /* definitions for Android logging */
     34 #include <utils/Log.h>
     35 #include <cutils/properties.h>
     36 #else /* ANDROID */
     37 #include <math.h>
     38 #define strlcat g_strlcat
     39 #define strlcpy g_strlcpy
     40 #define ALOGI(...)      fprintf(stdout, __VA_ARGS__)
     41 #define ALOGE(...)      fprintf(stderr, __VA_ARGS__)
     42 #define ALOGV(...)      fprintf(stderr, __VA_ARGS__)
     43 #define ALOGD(...)      fprintf(stderr, __VA_ARGS__)
     44 #endif /* ANDROID */
     45 
     46 #include <stdio.h>
     47 #include <stdlib.h>
     48 #include <fcntl.h>
     49 #include <stdarg.h>
     50 #include <string.h>
     51 #include <errno.h>
     52 #include <unistd.h>
     53 #include <pthread.h>
     54 #include <ctype.h>
     55 #include <sys/stat.h>
     56 #include <sys/ioctl.h>
     57 #include <sys/mman.h>
     58 #include <sys/time.h>
     59 #include <sys/poll.h>
     60 #include <stdint.h>
     61 #include <dlfcn.h>
     62 
     63 #include <linux/ioctl.h>
     64 #include "msm8960_use_cases.h"
     65 #if defined(QC_PROP)
     66     static void (*acdb_send_audio_cal)(int,int);
     67     static void (*acdb_send_voice_cal)(int,int);
     68 #endif
     69 #define PARSE_DEBUG 0
     70 
     71 /**
     72  * Create an identifier
     73  * fmt - sprintf like format,
     74  * ... - Optional arguments
     75  * returns - string allocated or NULL on error
     76  */
     77 char *snd_use_case_identifier(const char *fmt, ...)
     78 {
     79     ALOGE("API not implemented for now, to be updated if required");
     80     return NULL;
     81 }
     82 
     83 /**
     84  * Free a list
     85  * list - list to free
     86  * items -  Count of strings
     87  * Return Zero on success, otherwise a negative error code
     88  */
     89 int snd_use_case_free_list(const char *list[], int items)
     90 {
     91     /* list points to UCM internal static tables,
     92      * hence there is no need to do a free call
     93      * just set the list to NULL and return */
     94     list = NULL;
     95     return 0;
     96 }
     97 
     98 /**
     99  * Obtain a list of entries
    100  * uc_mgr - UCM structure pointer or  NULL for card list
    101  * identifier - NULL for card list
    102  * list - Returns allocated list
    103  * returns Number of list entries on success, otherwise a negative error code
    104  */
    105 int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
    106                           const char *identifier,
    107                           const char **list[])
    108 {
    109     use_case_verb_t *verb_list;
    110     int verb_index, list_size, index = 0;
    111 
    112     if (identifier == NULL) {
    113         *list = card_list;
    114         return ((int)MAX_NUM_CARDS);
    115     }
    116 
    117     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
    118     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) ||
    119         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL)) {
    120         ALOGE("snd_use_case_get_list(): failed, invalid arguments");
    121         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    122         return -EINVAL;
    123     }
    124 
    125     if (!strncmp(identifier, "_verbs", 6)) {
    126         while(strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
    127             SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))) {
    128             ALOGV("Index:%d Verb:%s", index,
    129                  uc_mgr->card_ctxt_ptr->verb_list[index]);
    130             index++;
    131         }
    132         *list = (char ***)uc_mgr->card_ctxt_ptr->verb_list;
    133         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    134         return index;
    135     } else  if (!strncmp(identifier, "_devices", 8)) {
    136         if (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    137             SND_USE_CASE_VERB_INACTIVE, strlen(SND_USE_CASE_VERB_INACTIVE))) {
    138             ALOGE("Use case verb name not set, invalid current verb");
    139             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    140             return -EINVAL;
    141         }
    142         verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    143         while(strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    144             verb_list[index].use_case_name,
    145             (strlen(verb_list[index].use_case_name)+1))) {
    146             index++;
    147         }
    148         verb_index = index;
    149         index = 0;
    150         while(strncmp(verb_list[verb_index].device_list[index],
    151             SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))) {
    152             ALOGV("Index:%d Device:%s", index,
    153                  verb_list[verb_index].device_list[index]);
    154             index++;
    155         }
    156         *list = verb_list[verb_index].device_list;
    157         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    158         return index;
    159     } else  if (!strncmp(identifier, "_modifiers", 10)) {
    160         if (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    161                     SND_USE_CASE_VERB_INACTIVE, MAX_STR_LEN)) {
    162             ALOGE("Use case verb name not set, invalid current verb");
    163             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    164             return -EINVAL;
    165         }
    166         verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    167         while(strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    168             verb_list[index].use_case_name,
    169             (strlen(verb_list[index].use_case_name)+1))) {
    170             index++;
    171         }
    172         verb_index = index;
    173         index = 0;
    174         while(strncmp(verb_list[verb_index].modifier_list[index],
    175                     SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))) {
    176             ALOGV("Index:%d Modifier:%s", index,
    177                  verb_list[verb_index].modifier_list[index]);
    178             index++;
    179         }
    180         *list = verb_list[verb_index].modifier_list;
    181         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    182         return index;
    183     } else  if (!strncmp(identifier, "_enadevs", 8)) {
    184         if (uc_mgr->device_list_count) {
    185             for (index = 0; index < uc_mgr->device_list_count; index++) {
    186                 free(uc_mgr->current_device_list[index]);
    187                 uc_mgr->current_device_list[index] = NULL;
    188             }
    189             free(uc_mgr->current_device_list);
    190             uc_mgr->current_device_list = NULL;
    191             uc_mgr->device_list_count = 0;
    192         }
    193         list_size =
    194             snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
    195         uc_mgr->device_list_count = list_size;
    196     if (list_size > 0) {
    197             uc_mgr->current_device_list =
    198                 (char **)malloc(sizeof(char *)*list_size);
    199             if (uc_mgr->current_device_list == NULL) {
    200                 *list = NULL;
    201                 pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    202                 return -ENOMEM;
    203             }
    204             for (index = 0; index < list_size; index++) {
    205                 uc_mgr->current_device_list[index] =
    206                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
    207                 index);
    208             }
    209         }
    210         *list = (const char **)uc_mgr->current_device_list;
    211         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    212         return (list_size);
    213     } else  if (!strncmp(identifier, "_enamods", 8)) {
    214         if (uc_mgr->modifier_list_count) {
    215             for (index = 0; index < uc_mgr->modifier_list_count; index++) {
    216                 free(uc_mgr->current_modifier_list[index]);
    217                 uc_mgr->current_modifier_list[index] = NULL;
    218             }
    219             free(uc_mgr->current_modifier_list);
    220             uc_mgr->current_modifier_list = NULL;
    221             uc_mgr->modifier_list_count = 0;
    222         }
    223         list_size =
    224             snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
    225         uc_mgr->modifier_list_count = list_size;
    226     if (list_size > 0) {
    227             uc_mgr->current_modifier_list =
    228                 (char **)malloc(sizeof(char *) * list_size);
    229             if (uc_mgr->current_modifier_list == NULL) {
    230                 *list = NULL;
    231                 pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    232                 return -ENOMEM;
    233             }
    234             for (index = 0; index < list_size; index++) {
    235                 uc_mgr->current_modifier_list[index] =
    236                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->mod_list_head,
    237                 index);
    238             }
    239         }
    240         *list = (const char **)uc_mgr->current_modifier_list;
    241         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    242         return (list_size);
    243     } else {
    244         ALOGE("Invalid identifier: %s", identifier);
    245         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    246         return -EINVAL;
    247     }
    248 }
    249 
    250 
    251 /**
    252  * Get current value of the identifier
    253  * identifier - NULL for current card
    254  *        _verb
    255  *        <Name>/<_device/_modifier>
    256  *    Name -    PlaybackPCM
    257  *        CapturePCM
    258  *        PlaybackCTL
    259  *        CaptureCTL
    260  * value - Value pointer
    261  * returns Zero if success, otherwise a negative error code
    262  */
    263 int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
    264                      const char *identifier,
    265                      const char **value)
    266 {
    267     card_mctrl_t *ctrl_list;
    268     use_case_verb_t *verb_list;
    269     char ident[MAX_STR_LEN], *ident1, *ident2, *temp_ptr;
    270     int index, verb_index = 0, ret = 0;
    271 
    272     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
    273     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) ||
    274         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL)) {
    275         ALOGE("snd_use_case_get(): failed, invalid arguments");
    276         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    277         return -EINVAL;
    278     }
    279 
    280     if (identifier == NULL) {
    281         if (uc_mgr->card_ctxt_ptr->card_name != NULL) {
    282             *value = strdup(uc_mgr->card_ctxt_ptr->card_name);
    283         } else {
    284             *value = NULL;
    285         }
    286         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    287         return 0;
    288     }
    289 
    290     if (!strncmp(identifier, "_verb", 5)) {
    291         if (uc_mgr->card_ctxt_ptr->current_verb != NULL) {
    292             *value = strdup(uc_mgr->card_ctxt_ptr->current_verb);
    293         } else {
    294             *value = NULL;
    295         }
    296         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    297         return 0;
    298     }
    299 
    300     strlcpy(ident, identifier, sizeof(ident));
    301     if(!(ident1 = strtok_r(ident, "/", &temp_ptr))) {
    302         ALOGE("No valid identifier found: %s", ident);
    303         ret = -EINVAL;
    304     } else {
    305         if ((!strncmp(ident1, "PlaybackPCM", 11)) ||
    306             (!strncmp(ident1, "CapturePCM", 10))) {
    307             ident2 = strtok_r(NULL, "/", &temp_ptr);
    308             index = 0;
    309             if (ident2 != NULL) {
    310                 verb_index = uc_mgr->card_ctxt_ptr->current_verb_index;
    311                 verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    312                 if((get_usecase_type(uc_mgr, ident2)) == CTRL_LIST_VERB) {
    313                     ctrl_list = verb_list[verb_index].verb_ctrls;
    314                 } else {
    315                     ctrl_list = verb_list[verb_index].mod_ctrls;
    316                 }
    317                 if((verb_index < 0) ||
    318                     (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    319                     SND_UCM_END_OF_LIST, 3)) || (ctrl_list == NULL)) {
    320                     ALOGE("Invalid current verb value: %s - %d",
    321                          uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    322                     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    323                     return -EINVAL;
    324                 }
    325                 while(strncmp(ctrl_list[index].case_name, ident2,
    326                     (strlen(ident2)+1))) {
    327                     if (!strncmp(ctrl_list[index].case_name,
    328                         SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))){
    329                         *value = NULL;
    330                         ret = -EINVAL;
    331                         break;
    332                     } else {
    333                         index++;
    334                     }
    335                 }
    336             } else {
    337                 ret = -EINVAL;
    338             }
    339             if (ret < 0) {
    340                 ALOGE("No valid device/modifier found with given identifier: %s",
    341                      ident2);
    342             } else {
    343                 if(!strncmp(ident1, "PlaybackPCM", 11)) {
    344                     if (ctrl_list[index].playback_dev_name) {
    345                         *value = strdup(ctrl_list[index].playback_dev_name);
    346                     } else {
    347                         *value = NULL;
    348                         ret = -ENODEV;
    349                     }
    350                 } else if(!strncmp(ident1, "CapturePCM", 10)) {
    351                     if (ctrl_list[index].capture_dev_name) {
    352                         *value = strdup(ctrl_list[index].capture_dev_name);
    353                     } else {
    354                         *value = NULL;
    355                         ret = -ENODEV;
    356                     }
    357                 } else {
    358                     ALOGE("No valid device name exists for given identifier: %s",
    359                          ident2);
    360                     *value = NULL;
    361                     ret = -ENODEV;
    362                 }
    363             }
    364         } else if ((!strncmp(ident1, "PlaybackCTL", 11)) ||
    365                    (!strncmp(ident1, "CaptureCTL", 10))) {
    366             if(uc_mgr->card_ctxt_ptr->control_device != NULL) {
    367                 *value = strdup(uc_mgr->card_ctxt_ptr->control_device);
    368             } else {
    369                 ALOGE("No valid control device found");
    370                 *value = NULL;
    371                 ret = -ENODEV;
    372             }
    373         } else if (!strncmp(ident1, "ACDBID", 11)) {
    374             ident2 = strtok_r(NULL, "/", &temp_ptr);
    375             index = 0; verb_index = 0;
    376             verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    377             if((verb_index < 0) ||
    378                (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    379                 SND_UCM_END_OF_LIST, 3)) ||
    380                 (verb_list[verb_index].verb_ctrls == NULL)) {
    381                 ALOGE("Invalid current verb value: %s - %d",
    382                      uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    383                 pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    384                 return -EINVAL;
    385             }
    386             ctrl_list = verb_list[verb_index].device_ctrls;
    387             if (ident2 != NULL) {
    388                 while(strncmp(ctrl_list[index].case_name, ident2,
    389                     MAX_LEN(ctrl_list[index].case_name,ident2))) {
    390                     if (!strncmp(ctrl_list[index].case_name, SND_UCM_END_OF_LIST,
    391                         strlen(SND_UCM_END_OF_LIST))){
    392                         ret = -EINVAL;
    393                         break;
    394                     } else {
    395                         index++;
    396                     }
    397                 }
    398             }
    399             if (ret < 0) {
    400                 ALOGE("No valid device/modifier found with given identifier: %s",
    401                       ident2);
    402             } else {
    403                 if (verb_list[verb_index].device_ctrls[index].acdb_id) {
    404                     ret = verb_list[verb_index].device_ctrls[index].acdb_id;
    405                 } else {
    406                     ret = -ENODEV;
    407                 }
    408             }
    409         } else if (!strncmp(ident1, "EffectsMixerCTL", 11)) {
    410             ident2 = strtok_r(NULL, "/", &temp_ptr);
    411             index = 0; verb_index = 0;
    412             verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    413             if((verb_index < 0) ||
    414                (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    415                 SND_UCM_END_OF_LIST, 3)) ||
    416                 (verb_list[verb_index].verb_ctrls == NULL)) {
    417                 ALOGE("Invalid current verb value: %s - %d",
    418                      uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    419                 pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    420                 return -EINVAL;
    421             }
    422             ctrl_list = verb_list[verb_index].device_ctrls;
    423             if (ident2 != NULL) {
    424                 while(strncmp(ctrl_list[index].case_name, ident2, strlen(ident2)+1)) {
    425                     if (!strncmp(ctrl_list[index].case_name, SND_UCM_END_OF_LIST,
    426                         strlen(SND_UCM_END_OF_LIST))){
    427                         ret = -EINVAL;
    428                         break;
    429                     } else {
    430                         index++;
    431                     }
    432                 }
    433             }
    434             if (ret < 0) {
    435                 ALOGE("No valid device/modifier found with given identifier: %s",
    436                       ident2);
    437             } else {
    438                 if (verb_list[verb_index].device_ctrls[index].effects_mixer_ctl) {
    439                     *value = strdup(verb_list[verb_index].device_ctrls[index].effects_mixer_ctl);
    440                 } else {
    441                     *value = NULL;
    442                     ret = -ENODEV;
    443                 }
    444             }
    445         } else {
    446             ALOGE("Unsupported identifier value: %s", ident1);
    447             *value = NULL;
    448             ret = -EINVAL;
    449         }
    450     }
    451     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    452     return ret;
    453 }
    454 
    455 /**
    456  * Get current status
    457  * uc_mgr - UCM structure
    458  * identifier - _devstatus/<device>,
    459         _modstatus/<modifier>
    460  * value - result
    461  * returns 0 on success, otherwise a negative error code
    462  */
    463 int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
    464               const char *identifier,
    465               long *value)
    466 {
    467     char ident[MAX_STR_LEN], *ident1, *ident2, *ident_value, *temp_ptr;
    468     int index, list_size, ret = -EINVAL;
    469 
    470     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
    471     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) ||
    472         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL)) {
    473         ALOGE("snd_use_case_geti(): failed, invalid arguments");
    474         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    475         return -EINVAL;
    476     }
    477 
    478     *value = 0;
    479     strlcpy(ident, identifier, sizeof(ident));
    480     if(!(ident1 = strtok_r(ident, "/", &temp_ptr))) {
    481         ALOGE("No valid identifier found: %s", ident);
    482         ret = -EINVAL;
    483     } else {
    484         if (!strncmp(ident1, "_devstatus", 10)) {
    485             ident2 = strtok_r(NULL, "/", &temp_ptr);
    486             if (ident2 != NULL) {
    487                 list_size =
    488                 snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
    489                 for (index = 0; index < list_size; index++) {
    490                 if ((ident_value =
    491                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
    492                 index))) {
    493                         if (!strncmp(ident2, ident_value,
    494                             (strlen(ident_value)+1))) {
    495                             *value = 1;
    496                             free(ident_value);
    497                             ident_value = NULL;
    498                             break;
    499                         } else {
    500                             free(ident_value);
    501                             ident_value = NULL;
    502                         }
    503                     }
    504                 }
    505                 ret = 0;
    506             }
    507         } else if (!strncmp(ident1, "_modstatus", 10)) {
    508             ident2 = strtok_r(NULL, "/", &temp_ptr);
    509             if (ident2 != NULL) {
    510                 list_size =
    511                 snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
    512                 for (index = 0; index < list_size; index++) {
    513                 if((ident_value =
    514                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->mod_list_head,
    515                 index))) {
    516                         if (!strncmp(ident2, ident_value,
    517                             (strlen(ident_value)+1))) {
    518                             *value = 1;
    519                             free(ident_value);
    520                             ident_value = NULL;
    521                             break;
    522                         } else {
    523                             free(ident_value);
    524                             ident_value = NULL;
    525                         }
    526                     }
    527                 }
    528                 ret = 0;
    529             }
    530         } else {
    531             ALOGE("Unknown identifier: %s", ident1);
    532         }
    533     }
    534     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
    535     return ret;
    536 }
    537 
    538 static int check_devices_for_voice_call(snd_use_case_mgr_t *uc_mgr,
    539 const char *use_case)
    540 {
    541     struct snd_ucm_ident_node *dev_node = NULL;
    542     int index = 0, list_size = 0, rx_dev_status = 0, tx_dev_status = 0;
    543 
    544     if ((!strncmp(use_case, SND_USE_CASE_VERB_VOICECALL,
    545         strlen(SND_USE_CASE_VERB_VOICECALL))) ||
    546         (!strncmp(use_case, SND_USE_CASE_VERB_IP_VOICECALL,
    547         strlen(SND_USE_CASE_VERB_IP_VOICECALL))) ||
    548         (!strncmp(use_case, SND_USE_CASE_MOD_PLAY_VOICE,
    549         strlen(SND_USE_CASE_MOD_PLAY_VOICE))) ||
    550         (!strncmp(use_case, SND_USE_CASE_MOD_PLAY_VOIP,
    551         strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) {
    552         ALOGV("check_devices_for_voice_call(): voice cap detected\n");
    553         list_size =
    554         snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
    555         for (index = 0; index < list_size; index++) {
    556             if ((dev_node =
    557                 snd_ucm_get_device_node(uc_mgr->card_ctxt_ptr->dev_list_head,
    558                 index))) {
    559                 if (dev_node->capability == CAP_RX && dev_node->active == 1) {
    560                     rx_dev_status = 1;
    561                 } else if (dev_node->capability == CAP_TX && dev_node->active == 1) {
    562                     tx_dev_status = 1;
    563                 }
    564             }
    565         }
    566         if (rx_dev_status == 1 && tx_dev_status == 1) {
    567             ALOGV("check_devices_for_voice_call(): Rx and Tx devices enabled\n");
    568             return 0;
    569         } else {
    570             ALOGV("check_devices_for_voice_call(): Rx/Tx dev not enabled: \
    571                   %d,%d\n", rx_dev_status, tx_dev_status);
    572             return 1;
    573         }
    574     }
    575     return 0;
    576 }
    577 
    578 static int snd_use_case_apply_voice_acdb(snd_use_case_mgr_t *uc_mgr,
    579 int use_case_index)
    580 {
    581     card_mctrl_t *ctrl_list;
    582     int list_size, index, verb_index, ret = 0, voice_acdb = 0, rx_id, tx_id;
    583     char *ident_value = NULL;
    584 
    585     /* Check if voice call use case/modifier exists */
    586     if ((!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    587         SND_USE_CASE_VERB_VOICECALL, strlen(SND_USE_CASE_VERB_VOICECALL))) ||
    588         (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    589         SND_USE_CASE_VERB_IP_VOICECALL,
    590         strlen(SND_USE_CASE_VERB_IP_VOICECALL)))) {
    591         voice_acdb = 1;
    592     }
    593     if (voice_acdb != 1) {
    594         list_size =
    595         snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
    596         for (index = 0; index < list_size; index++) {
    597             if ((ident_value =
    598                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->mod_list_head,
    599                 index))) {
    600                 if ((!strncmp(ident_value, SND_USE_CASE_MOD_PLAY_VOICE,
    601                     strlen(SND_USE_CASE_MOD_PLAY_VOICE))) ||
    602                     (!strncmp(ident_value, SND_USE_CASE_MOD_PLAY_VOIP,
    603                     strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) {
    604                     voice_acdb = 1;
    605                     free(ident_value);
    606                     ident_value = NULL;
    607                     break;
    608                 }
    609                 free(ident_value);
    610                 ident_value = NULL;
    611             }
    612         }
    613     }
    614 
    615     verb_index = uc_mgr->card_ctxt_ptr->current_verb_index;
    616     if((verb_index < 0) ||
    617         (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
    618         SND_UCM_END_OF_LIST, 3))) {
    619         ALOGE("Invalid current verb value: %s - %d",
    620             uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    621         return -EINVAL;
    622     }
    623     if (voice_acdb == 1) {
    624         ctrl_list =
    625         uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
    626         list_size =
    627         snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
    628         for (index = 0; index < list_size; index++) {
    629             if ((ident_value =
    630                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
    631                 index))) {
    632                 if (strncmp(ident_value, ctrl_list[use_case_index].case_name,
    633                     (strlen(ctrl_list[use_case_index].case_name)+1))) {
    634                     break;
    635                 }
    636                 free(ident_value);
    637                 ident_value = NULL;
    638             }
    639         }
    640         index = 0;
    641         if (ident_value != NULL) {
    642             while(strncmp(ctrl_list[index].case_name, ident_value,
    643                   (strlen(ident_value)+1))) {
    644                 if (!strncmp(ctrl_list[index].case_name, SND_UCM_END_OF_LIST,
    645                     strlen(SND_UCM_END_OF_LIST))) {
    646                     ret = -EINVAL;
    647                     break;
    648                 }
    649                 index++;
    650             }
    651             if (ret < 0) {
    652                 ALOGE("No valid device found: %s",ident_value);
    653             } else {
    654                 if (ctrl_list[use_case_index].capability == CAP_RX) {
    655                     rx_id = ctrl_list[use_case_index].acdb_id;
    656                     tx_id = ctrl_list[index].acdb_id;
    657                 } else {
    658                     rx_id = ctrl_list[index].acdb_id;
    659                     tx_id = ctrl_list[use_case_index].acdb_id;
    660                 }
    661                 if(((rx_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID)||(rx_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID))
    662                     && tx_id == DEVICE_HANDSET_TX_ACDB_ID) {
    663                     tx_id = DEVICE_SPEAKER_TX_ACDB_ID;
    664                 } else if (((rx_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID )||(rx_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID))
    665                     && tx_id == DEVICE_HANDSET_TX_FV5_ACDB_ID) {
    666                     tx_id = DEVICE_SPEAKER_TX_FV5_ACDB_ID;
    667                 }
    668 
    669                 if ((rx_id != uc_mgr->current_rx_device) ||
    670                     (tx_id != uc_mgr->current_tx_device)) {
    671                     uc_mgr->current_rx_device = rx_id;
    672                     uc_mgr->current_tx_device = tx_id;
    673                     ALOGD("Voice acdb: rx id %d tx id %d",
    674                           uc_mgr->current_rx_device,
    675                           uc_mgr->current_tx_device);
    676                     if (uc_mgr->acdb_handle && !uc_mgr->isFusion3Platform) {
    677                         acdb_send_voice_cal = dlsym(uc_mgr->acdb_handle,"acdb_loader_send_voice_cal");
    678                         if (acdb_send_voice_cal == NULL) {
    679                             ALOGE("ucm: dlsym: Error:%s Loading acdb_loader_send_voice_cal", dlerror());
    680                         }else {
    681                             acdb_send_voice_cal(uc_mgr->current_rx_device,
    682                                        uc_mgr->current_tx_device);
    683                         }
    684                    }
    685                 } else {
    686                     ALOGV("Voice acdb: Required acdb already pushed \
    687                          rx id %d tx id %d", uc_mgr->current_rx_device,
    688                          uc_mgr->current_tx_device);
    689                 }
    690             }
    691             free(ident_value);
    692             ident_value = NULL;
    693         }
    694     } else {
    695         ALOGV("No voice use case found");
    696         uc_mgr->current_rx_device = -1; uc_mgr->current_tx_device = -1;
    697         ret = -ENODEV;
    698     }
    699     return ret;
    700 }
    701 
    702 int get_use_case_index(snd_use_case_mgr_t *uc_mgr, const char *use_case,
    703 int ctrl_list_type)
    704 {
    705     use_case_verb_t *verb_list;
    706     card_mctrl_t *ctrl_list;
    707     int ret = 0, index = 0, verb_index;
    708 
    709     verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
    710     verb_index = uc_mgr->card_ctxt_ptr->current_verb_index;
    711     if (ctrl_list_type == CTRL_LIST_VERB) {
    712         ctrl_list =
    713             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].verb_ctrls;
    714     } else if (ctrl_list_type == CTRL_LIST_DEVICE) {
    715         ctrl_list =
    716             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
    717     } else if (ctrl_list_type == CTRL_LIST_MODIFIER) {
    718         ctrl_list =
    719             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].mod_ctrls;
    720     } else {
    721         ctrl_list = NULL;
    722     }
    723     if((verb_index < 0) ||
    724       (!strncmp(uc_mgr->card_ctxt_ptr->current_verb, SND_UCM_END_OF_LIST, 3)) ||
    725       (ctrl_list == NULL) || (ctrl_list[index].case_name == NULL)) {
    726         ALOGE("Invalid current verb value: %s - %d",
    727                 uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    728         return -EINVAL;
    729     }
    730     while(strncmp(ctrl_list[index].case_name, use_case, (strlen(use_case)+1))) {
    731         if (!strncmp(ctrl_list[index].case_name, SND_UCM_END_OF_LIST,
    732             strlen(SND_UCM_END_OF_LIST))) {
    733             ret = -EINVAL;
    734             break;
    735         }
    736         index++;
    737         if (ctrl_list[index].case_name == NULL) {
    738             ALOGE("Invalid case_name at index %d", index);
    739             ret = -EINVAL;
    740             break;
    741         }
    742     }
    743     if (ret < 0) {
    744         return ret;
    745     } else {
    746         return index;
    747     }
    748 }
    749 
    750 /* Apply the required mixer controls for specific use case
    751  * uc_mgr - UCM structure pointer
    752  * use_case - use case name
    753  * return 0 on sucess, otherwise a negative error code
    754  */
    755 int snd_use_case_apply_mixer_controls(snd_use_case_mgr_t *uc_mgr,
    756 const char *use_case, int enable, int ctrl_list_type, int uc_index)
    757 {
    758     card_mctrl_t *ctrl_list;
    759     mixer_control_t *mixer_list;
    760     struct mixer_ctl *ctl;
    761     int i, ret = 0, index = 0, verb_index, mixer_count;
    762 
    763     verb_index = uc_mgr->card_ctxt_ptr->current_verb_index;
    764     if (ctrl_list_type == CTRL_LIST_VERB) {
    765         ctrl_list =
    766             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].verb_ctrls;
    767     } else if (ctrl_list_type == CTRL_LIST_DEVICE) {
    768         ctrl_list =
    769             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
    770     } else if (ctrl_list_type == CTRL_LIST_MODIFIER) {
    771         ctrl_list =
    772             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].mod_ctrls;
    773     } else {
    774         ctrl_list = NULL;
    775     }
    776     if((verb_index < 0) ||
    777       (!strncmp(uc_mgr->card_ctxt_ptr->current_verb, SND_UCM_END_OF_LIST, 3)) ||
    778       (ctrl_list == NULL)) {
    779         ALOGE("Invalid current verb value: %s - %d",
    780             uc_mgr->card_ctxt_ptr->current_verb, verb_index);
    781         return -EINVAL;
    782     }
    783     if (uc_index < 0) {
    784         ALOGE("No valid use case found with the use case: %s", use_case);
    785         ret = -ENODEV;
    786     } else {
    787         if (!uc_mgr->card_ctxt_ptr->mixer_handle) {
    788             ALOGE("Control device not initialized");
    789             ret = -ENODEV;
    790         } else {
    791             if (enable &&
    792                 (check_devices_for_voice_call(uc_mgr, use_case) != NULL))
    793                 return ret;
    794             ALOGD("Set mixer controls for %s enable %d", use_case, enable);
    795             if (ctrl_list[uc_index].acdb_id && ctrl_list[uc_index].capability) {
    796                 if (enable) {
    797                     if (snd_use_case_apply_voice_acdb(uc_mgr, uc_index)) {
    798                         ALOGV("acdb_id %d cap %d enable %d",
    799                             ctrl_list[uc_index].acdb_id,
    800                             ctrl_list[uc_index].capability, enable);
    801                         if (uc_mgr->acdb_handle) {
    802                             acdb_send_audio_cal = dlsym(uc_mgr->acdb_handle,"acdb_loader_send_audio_cal");
    803                             if (acdb_send_audio_cal == NULL) {
    804                                 ALOGE("ucm:dlsym:Error:%s Loading acdb_loader_send_audio_cal", dlerror());
    805                             } else {
    806                                 acdb_send_audio_cal(ctrl_list[uc_index].acdb_id,
    807                                                      ctrl_list[uc_index].capability);
    808                             }
    809                         }
    810                     }
    811                 }
    812             }
    813             if (enable) {
    814                 mixer_list = ctrl_list[uc_index].ena_mixer_list;
    815                 mixer_count = ctrl_list[uc_index].ena_mixer_count;
    816             } else {
    817                 mixer_list = ctrl_list[uc_index].dis_mixer_list;
    818                 mixer_count = ctrl_list[uc_index].dis_mixer_count;
    819             }
    820             for(index = 0; index < mixer_count; index++) {
    821                 if (mixer_list == NULL) {
    822                     ALOGE("No valid controls exist for this case: %s", use_case);
    823                     break;
    824                 }
    825                 ctl = mixer_get_control(uc_mgr->card_ctxt_ptr->mixer_handle,
    826                           mixer_list[index].control_name, 0);
    827                 if (ctl) {
    828                     if (mixer_list[index].type == TYPE_INT) {
    829                         ALOGV("Setting mixer control: %s, value: %d",
    830                              mixer_list[index].control_name,
    831                              mixer_list[index].value);
    832                         ret = mixer_ctl_set(ctl, mixer_list[index].value);
    833                     } else if (mixer_list[index].type == TYPE_MULTI_VAL) {
    834                         ALOGD("Setting multi value: %s",
    835                             mixer_list[index].control_name);
    836                         ret = mixer_ctl_set_value(ctl, mixer_list[index].value,
    837                                 mixer_list[index].mulval);
    838                         if (ret < 0)
    839                             ALOGE("Failed to set multi value control %s\n",
    840                                 mixer_list[index].control_name);
    841                     } else {
    842                         ALOGV("Setting mixer control: %s, value: %s",
    843                             mixer_list[index].control_name,
    844                             mixer_list[index].string);
    845                         ret = mixer_ctl_select(ctl, mixer_list[index].string);
    846                     }
    847                     if ((ret != 0) && enable) {
    848                        /* Disable all the mixer controls which are
    849                         * already enabled before failure */
    850                        mixer_list = ctrl_list[uc_index].dis_mixer_list;
    851                        mixer_count = ctrl_list[uc_index].dis_mixer_count;
    852                        for(i = 0; i < mixer_count; i++) {
    853                            ctl = mixer_get_control(
    854                                      uc_mgr->card_ctxt_ptr->mixer_handle,
    855                                      mixer_list[i].control_name, 0);
    856                            if (ctl) {
    857                                if (mixer_list[i].type == TYPE_INT) {
    858                                    ret = mixer_ctl_set(ctl,
    859                                              mixer_list[i].value);
    860                                } else {
    861                                    ret = mixer_ctl_select(ctl,
    862                                              mixer_list[i].string);
    863                                }
    864                            }
    865                        }
    866                        ALOGE("Failed to enable the mixer controls for %s",
    867                             use_case);
    868                        break;
    869                     }
    870                 }
    871             }
    872         }
    873     }
    874     return ret;
    875 }
    876 
    877 int getUseCaseType(const char *useCase)
    878 {
    879     ALOGV("getUseCaseType: use case is %s\n", useCase);
    880     if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
    881            MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
    882         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
    883            MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
    884         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
    885            MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
    886         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
    887             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
    888         !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
    889             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
    890         !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
    891             MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
    892         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
    893             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
    894         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
    895             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
    896         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
    897             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
    898         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
    899             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
    900         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
    901             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
    902         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
    903             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
    904         return CAP_RX;
    905     } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
    906             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
    907         !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
    908             MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
    909         !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
    910             MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
    911         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
    912             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
    913         !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
    914             MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
    915         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
    916             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
    917         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
    918             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
    919         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
    920             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
    921         return CAP_TX;
    922     } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
    923             MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
    924         !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
    925             MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
    926         !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
    927             MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
    928         !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
    929             MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
    930         !strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
    931             MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
    932         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
    933             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
    934         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
    935             MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
    936         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
    937             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
    938         !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
    939             MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
    940         !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
    941             MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
    942         !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
    943             MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
    944         return CAP_VOICE;
    945     } else {
    946         ALOGE("unknown use case %s, returning voice capablity", useCase);
    947         return CAP_VOICE;
    948     }
    949 }
    950 
    951 /* Set/Reset mixer controls of specific use case for all current devices
    952  * uc_mgr - UCM structure pointer
    953  * ident  - use case name (verb or modifier)
    954  * enable - 1 for enable and 0 for disable
    955  * return 0 on sucess, otherwise a negative error code
    956  */
    957 static int set_controls_of_usecase_for_all_devices(snd_use_case_mgr_t *uc_mgr,
    958 const char *ident, int enable, int ctrl_list_type)
    959 {
    960     card_mctrl_t *dev_list, *uc_list;
    961     char *current_device, use_case[MAX_UC_LEN];
    962     int list_size, index, uc_index, ret = 0, intdev_flag = 0;
    963     int verb_index, capability = 0, ident_cap = 0, dev_cap =0;
    964 
    965     ALOGV("set_use_case_ident_for_all_devices(): %s", ident);
    966     if ((verb_index = uc_mgr->card_ctxt_ptr->current_verb_index) < 0)
    967         verb_index = 0;
    968     dev_list =
    969         uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
    970     if (ctrl_list_type == CTRL_LIST_VERB) {
    971         uc_list =
    972             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].verb_ctrls;
    973     } else if (ctrl_list_type == CTRL_LIST_MODIFIER) {
    974         uc_list =
    975             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].mod_ctrls;
    976     } else {
    977         uc_list = NULL;
    978     }
    979     ident_cap = getUseCaseType(ident);
    980     list_size = snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
    981     for (index = 0; index < list_size; index++) {
    982         current_device =
    983         snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head, index);
    984         if (current_device != NULL) {
    985             uc_index = get_use_case_index(uc_mgr, current_device,
    986                        CTRL_LIST_DEVICE);
    987             dev_cap = dev_list[uc_index].capability;
    988             if (!capability) {
    989                 capability = dev_list[uc_index].capability;
    990             } else if (capability != dev_list[uc_index].capability) {
    991                 capability = CAP_VOICE;
    992             }
    993             if (ident_cap == CAP_VOICE  || ident_cap == dev_cap) {
    994                 if (enable) {
    995                     if (!snd_ucm_get_status_at_index(
    996                         uc_mgr->card_ctxt_ptr->dev_list_head, current_device)) {
    997                         if (uc_index >= 0) {
    998                             ALOGV("Applying mixer controls for device: %s",
    999                                   current_device);
   1000                             ret = snd_use_case_apply_mixer_controls(uc_mgr,
   1001                                   current_device, enable, CTRL_LIST_DEVICE, uc_index);
   1002                             if (!ret)
   1003                                 snd_ucm_set_status_at_index(
   1004                                   uc_mgr->card_ctxt_ptr->dev_list_head,
   1005                                   current_device, enable, dev_cap);
   1006                         }
   1007                      } else if (ident_cap == CAP_VOICE) {
   1008                         snd_use_case_apply_voice_acdb(uc_mgr, uc_index);
   1009                      }
   1010                  }
   1011                  strlcpy(use_case, ident, sizeof(use_case));
   1012                  strlcat(use_case, current_device, sizeof(use_case));
   1013                  ALOGV("Applying mixer controls for use case: %s", use_case);
   1014                  if ((uc_index =
   1015                       get_use_case_index(uc_mgr, use_case, ctrl_list_type)) < 0) {
   1016                       ALOGV("No valid use case found: %s", use_case);
   1017                       intdev_flag++;
   1018                  } else {
   1019                       if (capability == CAP_VOICE || ident_cap == CAP_VOICE ||
   1020                           capability == ident_cap) {
   1021                           ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case,
   1022                                 enable, ctrl_list_type, uc_index);
   1023                       }
   1024                  }
   1025                  use_case[0] = 0;
   1026                  free(current_device);
   1027              }
   1028         }
   1029     }
   1030     if (intdev_flag) {
   1031         if ((uc_index = get_use_case_index(uc_mgr, ident, ctrl_list_type)) < 0) {
   1032             ALOGE("use case %s not valid without device combination", ident);
   1033         } else {
   1034             if (capability == CAP_VOICE || capability == ident_cap ||
   1035                 ident_cap == CAP_VOICE) {
   1036                 snd_use_case_apply_mixer_controls(uc_mgr, ident, enable,
   1037                 ctrl_list_type, uc_index);
   1038             }
   1039         }
   1040     }
   1041     return ret;
   1042 }
   1043 
   1044 /* Set/Reset mixer controls of specific use case for a specific device
   1045  * uc_mgr - UCM structure pointer
   1046  * ident  - use case name (verb or modifier)
   1047  * device - device for which use case needs to be set/reset
   1048  * enable - 1 for enable and 0 for disable
   1049  * return 0 on sucess, otherwise a negative error code
   1050  */
   1051 static int set_controls_of_usecase_for_device(snd_use_case_mgr_t *uc_mgr,
   1052 const char *ident, const char *device, int enable, int ctrl_list_type)
   1053 {
   1054     card_mctrl_t *dev_list;
   1055     char use_case[MAX_UC_LEN];
   1056     int list_size, index, dev_index, uc_index, ret = 0;
   1057     int verb_index, capability = 0;
   1058 
   1059     ALOGV("set_use_case_ident_for_device(): use case %s device %s", ident,
   1060         device);
   1061     if ((verb_index = uc_mgr->card_ctxt_ptr->current_verb_index) < 0)
   1062         verb_index = 0;
   1063     dev_list =
   1064         uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
   1065     if (device != NULL) {
   1066         if (enable) {
   1067             dev_index = get_use_case_index(uc_mgr, device, CTRL_LIST_DEVICE);
   1068             capability = dev_list[dev_index].capability;
   1069             if (!snd_ucm_get_status_at_index(
   1070                 uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1071                 ret = snd_use_case_apply_mixer_controls(uc_mgr, device,
   1072                          enable, CTRL_LIST_DEVICE, dev_index);
   1073                 if (!ret)
   1074                     snd_ucm_set_status_at_index(
   1075                     uc_mgr->card_ctxt_ptr->dev_list_head, device, enable,
   1076                     capability);
   1077             }
   1078         }
   1079         strlcpy(use_case, ident, sizeof(use_case));
   1080         strlcat(use_case, device, sizeof(use_case));
   1081     ALOGV("Applying mixer controls for use case: %s", use_case);
   1082         if ((uc_index = get_use_case_index(uc_mgr, use_case, ctrl_list_type)) < 0) {
   1083             ALOGV("No valid use case found: %s", use_case );
   1084             uc_index = get_use_case_index(uc_mgr, ident, ctrl_list_type);
   1085             if (snd_use_case_apply_mixer_controls(uc_mgr, ident, enable,
   1086                 ctrl_list_type, uc_index) < 0) {
   1087                  ALOGV("use case %s not valid without device combination also",
   1088                      ident);
   1089             }
   1090         } else {
   1091             ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case, enable,
   1092                       ctrl_list_type, uc_index);
   1093         }
   1094     } else {
   1095         uc_index = get_use_case_index(uc_mgr, ident, ctrl_list_type);
   1096         if (snd_use_case_apply_mixer_controls(uc_mgr, ident, enable,
   1097             ctrl_list_type, uc_index) < 0) {
   1098              ALOGV("use case %s not valid without device combination also",
   1099                  ident);
   1100         }
   1101     }
   1102     return ret;
   1103 }
   1104 
   1105 /* Set/Reset mixer controls of specific device for all use cases
   1106  * uc_mgr - UCM structure pointer
   1107  * device - device name
   1108  * enable - 1 for enable and 0 for disable
   1109  * return 0 on sucess, otherwise a negative error code
   1110  */
   1111 static int set_controls_of_device_for_all_usecases(snd_use_case_mgr_t *uc_mgr,
   1112 const char *device, int enable)
   1113 {
   1114     card_mctrl_t *dev_list, *uc_list;
   1115     char *ident_value, use_case[MAX_UC_LEN];
   1116     int verb_index, uc_index, dev_index, capability = 0;
   1117     int list_size, index = 0, ret = -ENODEV, flag = 0, intdev_flag = 0;
   1118 
   1119     ALOGV("set_controls_of_device_for_all_usecases: %s", device);
   1120     if ((verb_index = uc_mgr->card_ctxt_ptr->current_verb_index) < 0)
   1121         verb_index = 0;
   1122     dev_list =
   1123          uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
   1124     dev_index = get_use_case_index(uc_mgr, device, CTRL_LIST_DEVICE);
   1125     if (dev_index >= 0)
   1126         capability = dev_list[dev_index].capability;
   1127     if (strncmp(uc_mgr->card_ctxt_ptr->current_verb, SND_USE_CASE_VERB_INACTIVE,
   1128         strlen(SND_USE_CASE_VERB_INACTIVE))) {
   1129         uc_list =
   1130             uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].verb_ctrls;
   1131         if (capability == CAP_VOICE ||
   1132             capability == getUseCaseType(uc_mgr->card_ctxt_ptr->current_verb) ||
   1133             getUseCaseType(uc_mgr->card_ctxt_ptr->current_verb) == CAP_VOICE) {
   1134             strlcpy(use_case, uc_mgr->card_ctxt_ptr->current_verb,
   1135                 sizeof(use_case));
   1136             strlcat(use_case, device, sizeof(use_case));
   1137             if ((uc_index =
   1138                 get_use_case_index(uc_mgr, use_case, CTRL_LIST_VERB)) < 0) {
   1139                 ALOGV("No valid use case found: %s", use_case);
   1140                 intdev_flag = 1;
   1141             } else {
   1142                 if (enable) {
   1143                     if (!snd_ucm_get_status_at_index(
   1144                         uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1145                         ret = snd_use_case_apply_mixer_controls(uc_mgr, device,
   1146                                   enable, CTRL_LIST_DEVICE, dev_index);
   1147                         if (!ret)
   1148                             snd_ucm_set_status_at_index(
   1149                             uc_mgr->card_ctxt_ptr->dev_list_head, device,
   1150                             enable, capability);
   1151                             flag = 1;
   1152                     }
   1153                 }
   1154                 ALOGV("set %d for use case value: %s", enable, use_case);
   1155                 ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case,
   1156                           enable, CTRL_LIST_VERB, uc_index);
   1157                 if (ret != 0)
   1158                      ALOGE("No valid controls exists for usecase %s and device \
   1159                           %s, enable: %d", use_case, device, enable);
   1160             }
   1161         }
   1162         if (intdev_flag) {
   1163             if (enable && !flag) {
   1164                 if (!snd_ucm_get_status_at_index(
   1165                     uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1166                     ret = snd_use_case_apply_mixer_controls(uc_mgr,
   1167                               device, enable, CTRL_LIST_DEVICE, dev_index);
   1168                     if (!ret)
   1169                         snd_ucm_set_status_at_index(
   1170                         uc_mgr->card_ctxt_ptr->dev_list_head, device, enable,
   1171                         capability);
   1172                     flag = 1;
   1173                 }
   1174             }
   1175             use_case[0] = 0;
   1176             strlcpy(use_case, uc_mgr->card_ctxt_ptr->current_verb,
   1177                 sizeof(use_case));
   1178             uc_index = get_use_case_index(uc_mgr, use_case, CTRL_LIST_VERB);
   1179             if (capability == CAP_VOICE ||
   1180                 capability ==
   1181                 getUseCaseType(uc_mgr->card_ctxt_ptr->current_verb) ||
   1182                 getUseCaseType(uc_mgr->card_ctxt_ptr->current_verb) ==
   1183                 CAP_VOICE) {
   1184                 ALOGV("set %d for use case value: %s", enable, use_case);
   1185                 ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case,
   1186                           enable, CTRL_LIST_VERB, uc_index);
   1187                 if (ret != 0)
   1188                       ALOGE("No valid controls exists for usecase %s and \
   1189                            device %s, enable: %d", use_case, device, enable);
   1190             }
   1191             intdev_flag = 0;
   1192         }
   1193         use_case[0] = 0;
   1194     }
   1195     snd_ucm_print_list(uc_mgr->card_ctxt_ptr->mod_list_head);
   1196     uc_list =
   1197         uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].mod_ctrls;
   1198     list_size = snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
   1199     for (index = 0; index < list_size; index++) {
   1200         if ((ident_value =
   1201             snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->mod_list_head,
   1202             index))) {
   1203             if (capability == CAP_VOICE ||
   1204                 getUseCaseType(ident_value) == CAP_VOICE ||
   1205                 capability == getUseCaseType(ident_value)) {
   1206                 strlcpy(use_case, ident_value, sizeof(use_case));
   1207                 strlcat(use_case, device, sizeof(use_case));
   1208                 if ((uc_index = get_use_case_index(uc_mgr, use_case,
   1209                     CTRL_LIST_MODIFIER)) < 0) {
   1210                     ALOGV("No valid use case found: %s", use_case);
   1211                     intdev_flag = 1;
   1212                 } else {
   1213                     if (enable && !flag) {
   1214                         if (!snd_ucm_get_status_at_index(
   1215                             uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1216                             ret = snd_use_case_apply_mixer_controls(uc_mgr,
   1217                                       device, enable, CTRL_LIST_DEVICE,
   1218                                       dev_index);
   1219                             if (!ret)
   1220                                 snd_ucm_set_status_at_index(
   1221                                     uc_mgr->card_ctxt_ptr->dev_list_head,
   1222                                     device, enable, capability);
   1223                             flag = 1;
   1224                         }
   1225                     }
   1226                     ALOGV("set %d for use case value: %s", enable, use_case);
   1227                     ret = snd_use_case_apply_mixer_controls(uc_mgr,
   1228                           use_case, enable, CTRL_LIST_MODIFIER, uc_index);
   1229                     if (ret != 0)
   1230                         ALOGE("No valid controls exists for usecase %s and \
   1231                             device %s, enable: %d", use_case, device, enable);
   1232                 }
   1233             }
   1234             if (intdev_flag) {
   1235                 if (enable && !flag) {
   1236                     if (!snd_ucm_get_status_at_index(
   1237                          uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1238                         ret = snd_use_case_apply_mixer_controls(uc_mgr,
   1239                                   device, enable, CTRL_LIST_DEVICE, dev_index);
   1240                         if (!ret)
   1241                             snd_ucm_set_status_at_index(
   1242                             uc_mgr->card_ctxt_ptr->dev_list_head, device,
   1243                             enable, capability);
   1244                         flag = 1;
   1245                     }
   1246                 }
   1247                 use_case[0] = 0;
   1248                 strlcpy(use_case, ident_value, sizeof(use_case));
   1249                 uc_index =
   1250                     get_use_case_index(uc_mgr, ident_value, CTRL_LIST_MODIFIER);
   1251                 if (capability == CAP_VOICE ||
   1252                     capability == getUseCaseType(ident_value) ||
   1253                     getUseCaseType(ident_value) == CAP_VOICE) {
   1254                     ALOGV("set %d for use case value: %s", enable, use_case);
   1255                     ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case,
   1256                           enable, CTRL_LIST_MODIFIER, uc_index);
   1257                     if (ret != 0)
   1258                          ALOGE("No valid controls exists for usecase %s and \
   1259                               device %s, enable: %d", use_case, device, enable);
   1260                 }
   1261                 intdev_flag = 0;
   1262             }
   1263             use_case[0] = 0;
   1264             free(ident_value);
   1265         }
   1266     }
   1267     if (!enable) {
   1268         ret = snd_use_case_apply_mixer_controls(uc_mgr, device, enable,
   1269                   CTRL_LIST_DEVICE, dev_index);
   1270         if (!ret)
   1271             snd_ucm_set_status_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1272                 device, enable, capability);
   1273     }
   1274     return ret;
   1275 }
   1276 
   1277 /* Returns usecase type i.e. either verb or modifier
   1278  * uc_mgr - UCM structure pointer
   1279  * usecase - usecase name either verb or modifier
   1280  * return CTRL_LIST_VERB or CTRL_LIST_MODIFIER for verb/modifier respectively
   1281  */
   1282 static int get_usecase_type(snd_use_case_mgr_t *uc_mgr, const char *usecase)
   1283 {
   1284     int ret = -EINVAL, index = 0;
   1285 
   1286     while (strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1287         SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))) {
   1288         if (!strncmp(uc_mgr->card_ctxt_ptr->verb_list[index], usecase,
   1289             (strlen(usecase)+1))) {
   1290             ret = 0;
   1291             break;
   1292         }
   1293         index++;
   1294     }
   1295     if (ret == 0)
   1296         return CTRL_LIST_VERB;
   1297     else
   1298         return CTRL_LIST_MODIFIER;
   1299 }
   1300 
   1301 /* Set/Reset mixer controls of specific device and specific use cases
   1302  * uc_mgr - UCM structure pointer
   1303  * device - device name
   1304  * usecase - use case for which device needs to be enabled
   1305  * enable - 1 for enable and 0 for disable
   1306  * return 0 on sucess, otherwise a negative error code
   1307  */
   1308 static int set_controls_of_device_for_usecase(snd_use_case_mgr_t *uc_mgr,
   1309     const char *device, const char *usecase, int enable)
   1310 {
   1311     card_mctrl_t *dev_list;
   1312     char use_case[MAX_UC_LEN];
   1313     int ret = -ENODEV, uc_index, dev_index;
   1314     int verb_index, capability = 0;
   1315 
   1316     ALOGV("set_device_for_ident(): %s %s", device, usecase);
   1317     if ((verb_index = uc_mgr->card_ctxt_ptr->current_verb_index) < 0)
   1318         verb_index = 0;
   1319     dev_list =
   1320          uc_mgr->card_ctxt_ptr->use_case_verb_list[verb_index].device_ctrls;
   1321     dev_index = get_use_case_index(uc_mgr, device, CTRL_LIST_DEVICE);
   1322     capability = dev_list[dev_index].capability;
   1323     if (usecase != NULL) {
   1324         strlcpy(use_case, usecase, sizeof(use_case));
   1325         strlcat(use_case, device, sizeof(use_case));
   1326         if ((uc_index = get_use_case_index(uc_mgr, use_case,
   1327             get_usecase_type(uc_mgr, usecase))) < 0) {
   1328             ALOGV("No valid use case found: %s", use_case);
   1329         } else {
   1330             if (enable) {
   1331                 if (!snd_ucm_get_status_at_index(
   1332                     uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1333                     ret = snd_use_case_apply_mixer_controls(uc_mgr, device,
   1334                           enable, CTRL_LIST_DEVICE, dev_index);
   1335                     if (!ret)
   1336                         snd_ucm_set_status_at_index
   1337                         (uc_mgr->card_ctxt_ptr->dev_list_head, device, enable,
   1338                         capability);
   1339                 }
   1340             }
   1341             ALOGV("set %d for use case value: %s", enable, use_case);
   1342             ret = snd_use_case_apply_mixer_controls(uc_mgr, use_case, enable,
   1343                       get_usecase_type(uc_mgr, usecase), uc_index);
   1344             if (ret != 0)
   1345                 ALOGE("No valid controls exists for usecase %s and device %s, \
   1346                      enable: %d", use_case, device, enable);
   1347         }
   1348         use_case[0] = 0;
   1349     } else {
   1350         if (enable) {
   1351             if (!snd_ucm_get_status_at_index(
   1352                  uc_mgr->card_ctxt_ptr->dev_list_head, device)) {
   1353                 ret = snd_use_case_apply_mixer_controls(uc_mgr, device, enable,
   1354                           CTRL_LIST_DEVICE, dev_index);
   1355                 if (!ret)
   1356                     snd_ucm_set_status_at_index(
   1357                         uc_mgr->card_ctxt_ptr->dev_list_head, device, enable,
   1358                         capability);
   1359             }
   1360         }
   1361     }
   1362     if (!enable) {
   1363         ret = snd_use_case_apply_mixer_controls(uc_mgr, device, enable,
   1364                   CTRL_LIST_DEVICE, dev_index);
   1365         if (!ret)
   1366             snd_ucm_set_status_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1367                 device, enable, capability);
   1368     }
   1369     return ret;
   1370 }
   1371 
   1372 /**
   1373  * Set new value for an identifier
   1374  * uc_mgr - UCM structure
   1375  * identifier - _verb, _enadev, _disdev, _enamod, _dismod
   1376  *        _swdev, _swmod
   1377  * value - Value to be set
   1378  * returns 0 on success, otherwise a negative error code
   1379  */
   1380 int snd_use_case_set(snd_use_case_mgr_t *uc_mgr,
   1381                      const char *identifier,
   1382                      const char *value)
   1383 {
   1384     use_case_verb_t *verb_list;
   1385     char ident[MAX_STR_LEN], *ident1, *ident2, *temp_ptr;
   1386     int verb_index, list_size, index = 0, ret = -EINVAL;
   1387 
   1388     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
   1389     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) || (value == NULL) ||
   1390         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL) ||
   1391         (identifier == NULL)) {
   1392         ALOGE("snd_use_case_set(): failed, invalid arguments");
   1393         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1394         return -EINVAL;
   1395     }
   1396 
   1397     ALOGD("snd_use_case_set(): uc_mgr %p identifier %s value %s", uc_mgr,
   1398          identifier, value);
   1399     strlcpy(ident, identifier, sizeof(ident));
   1400     if(!(ident1 = strtok_r(ident, "/", &temp_ptr))) {
   1401         ALOGV("No multiple identifiers found in identifier value");
   1402         ident[0] = 0;
   1403     } else {
   1404         if (!strncmp(ident1, "_swdev", 6)) {
   1405             if(!(ident2 = strtok_r(NULL, "/", &temp_ptr))) {
   1406                 ALOGD("Invalid disable device value: %s, but enabling new \
   1407                      device", ident2);
   1408             } else {
   1409                 ret = snd_ucm_del_ident_from_list(
   1410                           &uc_mgr->card_ctxt_ptr->dev_list_head, ident2);
   1411                 if (ret < 0) {
   1412                     ALOGV("Ignore device %s disable, device not part of \
   1413                          enabled list", ident2);
   1414                 } else {
   1415                     ALOGV("swdev: device value to be disabled: %s", ident2);
   1416                     /* Disable mixer controls for
   1417                      * corresponding use cases and device */
   1418                     ret = set_controls_of_device_for_all_usecases(uc_mgr,
   1419                               ident2, 0);
   1420                     if (ret < 0) {
   1421                         ALOGV("Device %s not disabled, no valid use case \
   1422                               found: %d", ident2, errno);
   1423                     }
   1424                 }
   1425             }
   1426             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1427             ret = snd_use_case_set(uc_mgr, "_enadev", value);
   1428             if (ret < 0) {
   1429                 ALOGV("Device %s not enabled, no valid use case found: %d",
   1430                     value, errno);
   1431             }
   1432             return ret;
   1433         } else if (!strncmp(ident1, "_swmod", 6)) {
   1434             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1435             if(!(ident2 = strtok_r(NULL, "/", &temp_ptr))) {
   1436                 ALOGD("Invalid modifier value: %s, but enabling new modifier",
   1437                     ident2);
   1438             } else {
   1439                 ret = snd_use_case_set(uc_mgr, "_dismod", ident2);
   1440                 if (ret < 0) {
   1441                     ALOGV("Modifier %s not disabled, no valid use case \
   1442                          found: %d", ident2, errno);
   1443                 }
   1444             }
   1445             ret = snd_use_case_set(uc_mgr, "_enamod", value);
   1446             if (ret < 0) {
   1447                 ALOGV("Modifier %s not enabled, no valid use case found: %d",
   1448                     value, errno);
   1449             }
   1450             return ret;
   1451         } else {
   1452             ALOGV("No switch device/modifier option found: %s", ident1);
   1453         }
   1454         ident[0] = 0;
   1455     }
   1456 
   1457     if (!strncmp(identifier, "_verb", 5)) {
   1458         /* Check if value is valid verb */
   1459         while (strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1460                SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))) {
   1461             if (!strncmp(uc_mgr->card_ctxt_ptr->verb_list[index], value,
   1462                 (strlen(value)+1))) {
   1463                 ret = 0;
   1464                 break;
   1465             }
   1466             index++;
   1467         }
   1468         if ((ret < 0) && (strncmp(value, SND_USE_CASE_VERB_INACTIVE,
   1469             strlen(SND_USE_CASE_VERB_INACTIVE)))) {
   1470             ALOGE("Invalid verb identifier value");
   1471         } else {
   1472             ALOGV("Index:%d Verb:%s", index,
   1473                 uc_mgr->card_ctxt_ptr->verb_list[index]);
   1474             /* Disable the mixer controls for current use case
   1475              * for all the enabled devices */
   1476             if (strncmp(uc_mgr->card_ctxt_ptr->current_verb,
   1477                 SND_USE_CASE_VERB_INACTIVE,
   1478                 strlen(SND_USE_CASE_VERB_INACTIVE))) {
   1479                 ret = set_controls_of_usecase_for_all_devices(uc_mgr,
   1480                       uc_mgr->card_ctxt_ptr->current_verb, 0, CTRL_LIST_VERB);
   1481                 if (ret != 0)
   1482                     ALOGE("Failed to disable controls for use case: %s",
   1483                         uc_mgr->card_ctxt_ptr->current_verb);
   1484             }
   1485             strlcpy(uc_mgr->card_ctxt_ptr->current_verb, value, MAX_STR_LEN);
   1486             /* Enable the mixer controls for the new use case
   1487              * for all the enabled devices */
   1488             if (strncmp(uc_mgr->card_ctxt_ptr->current_verb,
   1489                SND_USE_CASE_VERB_INACTIVE,
   1490                strlen(SND_USE_CASE_VERB_INACTIVE))) {
   1491                uc_mgr->card_ctxt_ptr->current_verb_index = index;
   1492                ret = set_controls_of_usecase_for_all_devices(uc_mgr,
   1493                      uc_mgr->card_ctxt_ptr->current_verb, 1, CTRL_LIST_VERB);
   1494             }
   1495         }
   1496     } else if (!strncmp(identifier, "_enadev", 7)) {
   1497         index = 0; ret = 0;
   1498         list_size =
   1499             snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1500         for (index = 0; index < list_size; index++) {
   1501             if ((ident1 =
   1502                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1503                 index))) {
   1504                 if (!strncmp(ident1, value, (strlen(value)+1))) {
   1505                     ALOGV("Ignore enable as %s device is already part of \
   1506                          enabled list", value);
   1507                     free(ident1);
   1508                     break;
   1509                 }
   1510                 free(ident1);
   1511             }
   1512         }
   1513         if (index == list_size) {
   1514             ALOGV("enadev: device value to be enabled: %s", value);
   1515             snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1516                 value);
   1517         }
   1518         snd_ucm_print_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1519         /* Apply Mixer controls of all verb and modifiers for this device*/
   1520         ret = set_controls_of_device_for_all_usecases(uc_mgr, value, 1);
   1521     } else if (!strncmp(identifier, "_disdev", 7)) {
   1522         ret = snd_ucm_get_status_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1523                   value);
   1524         if (ret < 0) {
   1525             ALOGD("disdev: device %s not enabled, no need to disable", value);
   1526         } else if (ret == 0) {
   1527             ALOGV("disdev: device %s not active, remove from the list", value);
   1528             ret =
   1529             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1530             value);
   1531             if (ret < 0) {
   1532                 ALOGE("Invalid device: Device not part of enabled device list");
   1533             }
   1534         } else {
   1535             ret =
   1536             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1537             value);
   1538             if (ret < 0) {
   1539                 ALOGE("Invalid device: Device not part of enabled device list");
   1540             } else {
   1541                 ALOGV("disdev: device value to be disabled: %s", value);
   1542                 index = get_use_case_index(uc_mgr, value, CTRL_LIST_DEVICE);
   1543                 /* Apply Mixer controls for corresponding device and modifier */
   1544                 ret = snd_use_case_apply_mixer_controls(uc_mgr, value, 0,
   1545                           CTRL_LIST_DEVICE, index);
   1546             }
   1547         }
   1548     } else if (!strncmp(identifier, "_enamod", 7)) {
   1549         index = 0; ret = 0;
   1550         verb_index = uc_mgr->card_ctxt_ptr->current_verb_index;
   1551         if (verb_index < 0) {
   1552             ALOGE("Invalid verb identifier value");
   1553         } else {
   1554             ALOGV("Index:%d Verb:%s", verb_index,
   1555                  uc_mgr->card_ctxt_ptr->verb_list[verb_index]);
   1556             verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
   1557             while(strncmp(verb_list[verb_index].modifier_list[index], value,
   1558                   (strlen(value)+1))) {
   1559                 if (!strncmp(verb_list[verb_index].modifier_list[index],
   1560                     SND_UCM_END_OF_LIST, strlen(SND_UCM_END_OF_LIST))){
   1561                     ret = -EINVAL;
   1562                     break;
   1563                 }
   1564                 index++;
   1565             }
   1566             if (ret < 0) {
   1567                 ALOGE("Invalid modifier identifier value");
   1568             } else {
   1569                 snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->mod_list_head,
   1570                     value);
   1571                 /* Enable the mixer controls for the new use case
   1572                  * for all the enabled devices */
   1573                 ret = set_controls_of_usecase_for_all_devices(uc_mgr, value, 1,
   1574                           CTRL_LIST_MODIFIER);
   1575             }
   1576         }
   1577     } else if (!strncmp(identifier, "_dismod", 7)) {
   1578         ret = snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->mod_list_head,
   1579                   value);
   1580         if (ret < 0) {
   1581             ALOGE("Modifier not enabled currently, invalid modifier");
   1582         } else {
   1583             ALOGV("dismod: modifier value to be disabled: %s", value);
   1584             /* Enable the mixer controls for the new use case
   1585              * for all the enabled devices */
   1586             ret = set_controls_of_usecase_for_all_devices(uc_mgr, value, 0,
   1587                       CTRL_LIST_MODIFIER);
   1588         }
   1589     } else {
   1590         ALOGE("Unknown identifier value: %s", identifier);
   1591     }
   1592     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1593     return ret;
   1594 }
   1595 
   1596 /**
   1597  * Set new value for an identifier based on use case
   1598  * uc_mgr - UCM structure
   1599  * identifier - _verb, _enadev, _disdev, _enamod, _dismod
   1600  *        _swdev, _swmod
   1601  * value - Value to be set
   1602  * usecase - usecase/device for which this command needs to be executed
   1603  * returns 0 on success, otherwise a negative error code
   1604  */
   1605 int snd_use_case_set_case(snd_use_case_mgr_t *uc_mgr,
   1606                      const char *identifier,
   1607                      const char *value, const char *usecase)
   1608 {
   1609     use_case_verb_t *verb_list;
   1610     char ident[MAX_STR_LEN], *ident1, *ident2, *temp_ptr;
   1611     int verb_index, list_size, index = 0, ret = -EINVAL;
   1612 
   1613     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
   1614     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) || (value == NULL) ||
   1615         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL) ||
   1616         (identifier == NULL)) {
   1617         ALOGE("snd_use_case_set_case(): failed, invalid arguments");
   1618         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1619         return -EINVAL;
   1620     }
   1621 
   1622     ALOGD("snd_use_case_set_case(): uc_mgr %p identifier %s value %s",
   1623         uc_mgr, identifier, value);
   1624     strlcpy(ident, identifier, sizeof(ident));
   1625     if(!(ident1 = strtok_r(ident, "/", &temp_ptr))) {
   1626         ALOGV("No multiple identifiers found in identifier value");
   1627         ident[0] = 0;
   1628     } else {
   1629         if (!strncmp(ident1, "_swdev", 6)) {
   1630             if(!(ident2 = strtok_r(NULL, "/", &temp_ptr))) {
   1631                 ALOGD("Invalid disable device value: %s, but enabling new \
   1632                      device", ident2);
   1633             } else {
   1634                 ret = snd_ucm_del_ident_from_list(
   1635                           &uc_mgr->card_ctxt_ptr->dev_list_head, ident2);
   1636                 if (ret < 0) {
   1637                     ALOGV("Ignore device %s disable, device not part of \
   1638                          enabled list", ident2);
   1639                 } else {
   1640                     ALOGV("swdev: device value to be disabled: %s", ident2);
   1641                     /* Disable mixer controls for
   1642                      * corresponding use cases and device */
   1643                     ret = set_controls_of_device_for_usecase(uc_mgr, ident2,
   1644                               usecase, 0);
   1645                     if (ret < 0) {
   1646                         ALOGV("Device %s not disabled, no valid use case \
   1647                              found: %d", ident2, errno);
   1648                     }
   1649                 }
   1650             }
   1651             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1652             ret = snd_use_case_set_case(uc_mgr, "_enadev", value, usecase);
   1653             if (ret < 0) {
   1654                 ALOGV("Device %s not enabled, no valid use case found: %d",
   1655                     value, errno);
   1656             }
   1657             return ret;
   1658         } else if (!strncmp(ident1, "_swmod", 6)) {
   1659             pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1660             if(!(ident2 = strtok_r(NULL, "/", &temp_ptr))) {
   1661                 ALOGD("Invalid modifier value: %s, but enabling new modifier",
   1662                     ident2);
   1663             } else {
   1664                 ret = snd_use_case_set_case(uc_mgr, "_dismod", ident2, usecase);
   1665                 if (ret < 0) {
   1666                     ALOGV("Modifier %s not disabled, no valid use case \
   1667                          found: %d", ident2, errno);
   1668                 }
   1669             }
   1670             ret = snd_use_case_set_case(uc_mgr, "_enamod", value, usecase);
   1671             if (ret < 0) {
   1672                 ALOGV("Modifier %s not enabled, no valid use case found: %d",
   1673                     value, errno);
   1674             }
   1675             return ret;
   1676         } else {
   1677             ALOGV("No switch device/modifier option found: %s", ident1);
   1678         }
   1679         ident[0] = 0;
   1680     }
   1681 
   1682     if (!strncmp(identifier, "_verb", 5)) {
   1683         /* Check if value is valid verb */
   1684         while (strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1685                SND_UCM_END_OF_LIST, MAX_STR_LEN)) {
   1686             if (!strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1687                 value, MAX_STR_LEN)) {
   1688                 ret = 0;
   1689                 break;
   1690             }
   1691             index++;
   1692         }
   1693         if ((ret < 0) && (strncmp(value, SND_USE_CASE_VERB_INACTIVE,
   1694             MAX_STR_LEN))) {
   1695             ALOGE("Invalid verb identifier value");
   1696         } else {
   1697             ALOGV("Index:%d Verb:%s", index,
   1698                  uc_mgr->card_ctxt_ptr->verb_list[index]);
   1699             /* Disable the mixer controls for current use case
   1700              * for specified device */
   1701             if (strncmp(uc_mgr->card_ctxt_ptr->current_verb,
   1702                 SND_USE_CASE_VERB_INACTIVE, MAX_STR_LEN)) {
   1703                 ret = set_controls_of_usecase_for_device(uc_mgr,
   1704                           uc_mgr->card_ctxt_ptr->current_verb, usecase,
   1705                           0, CTRL_LIST_VERB);
   1706                 if (ret != 0)
   1707                     ALOGE("Failed to disable controls for use case: %s",
   1708                         uc_mgr->card_ctxt_ptr->current_verb);
   1709             }
   1710             strlcpy(uc_mgr->card_ctxt_ptr->current_verb, value, MAX_STR_LEN);
   1711             /* Enable the mixer controls for the new use case
   1712              * for specified device */
   1713             if (strncmp(uc_mgr->card_ctxt_ptr->current_verb,
   1714                 SND_USE_CASE_VERB_INACTIVE, MAX_STR_LEN)) {
   1715                uc_mgr->card_ctxt_ptr->current_verb_index = index;
   1716                index = 0;
   1717                list_size =
   1718                snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1719                for (index = 0; index < list_size; index++) {
   1720                    if ((ident1 = snd_ucm_get_value_at_index(
   1721                        uc_mgr->card_ctxt_ptr->dev_list_head, index))) {
   1722                        if (!strncmp(ident1, usecase, MAX_STR_LEN)) {
   1723                            ALOGV("Device already part of enabled list: %s",
   1724                                usecase);
   1725                            free(ident1);
   1726                            break;
   1727                        }
   1728                        free(ident1);
   1729                    }
   1730                }
   1731                if (index == list_size) {
   1732                    ALOGV("enadev: device value to be enabled: %s", usecase);
   1733                    snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1734                         usecase);
   1735                }
   1736                ret = set_controls_of_usecase_for_device(uc_mgr,
   1737                          uc_mgr->card_ctxt_ptr->current_verb, usecase,
   1738                          1, CTRL_LIST_VERB);
   1739             }
   1740         }
   1741     } else if (!strncmp(identifier, "_enadev", 7)) {
   1742         index = 0; ret = 0;
   1743         list_size =
   1744             snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1745         for (index = 0; index < list_size; index++) {
   1746             if ((ident1 =
   1747                 snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1748                 index))) {
   1749                 if (!strncmp(ident1, value, MAX_STR_LEN)) {
   1750                     ALOGV("Device already part of enabled list: %s", value);
   1751                     free(ident1);
   1752                     break;
   1753                 }
   1754                 free(ident1);
   1755             }
   1756         }
   1757         if (index == list_size) {
   1758             ALOGV("enadev: device value to be enabled: %s", value);
   1759             snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1760                 value);
   1761         }
   1762         snd_ucm_print_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1763         /* Apply Mixer controls of usecase for this device*/
   1764         ret = set_controls_of_device_for_usecase(uc_mgr, value, usecase, 1);
   1765     } else if (!strncmp(identifier, "_disdev", 7)) {
   1766         ret = snd_ucm_get_status_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   1767                   value);
   1768         if (ret < 0) {
   1769             ALOGD("disdev: device %s not enabled, no need to disable", value);
   1770         } else if (ret == 0) {
   1771             ALOGV("disdev: device %s not active, remove from the list", value);
   1772             ret =
   1773             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1774             value);
   1775             if (ret < 0) {
   1776                 ALOGE("Invalid device: Device not part of enabled device list");
   1777             }
   1778         } else {
   1779             ret =
   1780             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1781             value);
   1782             if (ret < 0) {
   1783                 ALOGE("Invalid device: Device not part of enabled device list");
   1784             } else {
   1785                 ALOGV("disdev: device value to be disabled: %s", value);
   1786                 /* Apply Mixer controls of usecase for this device*/
   1787                 ret = set_controls_of_device_for_usecase(uc_mgr, value,
   1788                           usecase, 0);
   1789             }
   1790         }
   1791     } else if (!strncmp(identifier, "_enamod", 7)) {
   1792         if (!strncmp(uc_mgr->card_ctxt_ptr->current_verb,
   1793             SND_USE_CASE_VERB_INACTIVE, MAX_STR_LEN)) {
   1794             ALOGE("Invalid use case verb value");
   1795             ret = -EINVAL;
   1796         } else {
   1797             ret = 0;
   1798             while(strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1799                   uc_mgr->card_ctxt_ptr->current_verb, MAX_STR_LEN)) {
   1800                 if (!strncmp(uc_mgr->card_ctxt_ptr->verb_list[index],
   1801                     SND_UCM_END_OF_LIST, MAX_STR_LEN)){
   1802                     ret = -EINVAL;
   1803                     break;
   1804                 }
   1805                 index++;
   1806             }
   1807         }
   1808         if (ret < 0) {
   1809             ALOGE("Invalid verb identifier value");
   1810         } else {
   1811             verb_index = index; index = 0; ret = 0;
   1812             verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
   1813             ALOGV("Index:%d Verb:%s", verb_index,
   1814                  uc_mgr->card_ctxt_ptr->verb_list[verb_index]);
   1815             while(strncmp(verb_list[verb_index].modifier_list[index],
   1816                 value, MAX_STR_LEN)) {
   1817                 if (!strncmp(verb_list[verb_index].modifier_list[index],
   1818                     SND_UCM_END_OF_LIST, MAX_STR_LEN)){
   1819                     ret = -EINVAL;
   1820                     break;
   1821                 }
   1822                 index++;
   1823             }
   1824             if (ret < 0) {
   1825                 ALOGE("Invalid modifier identifier value");
   1826             } else {
   1827                 index = 0;
   1828                 list_size =
   1829                 snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   1830                 for (index = 0; index < list_size; index++) {
   1831                     if ((ident1 = snd_ucm_get_value_at_index(
   1832                         uc_mgr->card_ctxt_ptr->dev_list_head, index))) {
   1833                         if (!strncmp(ident1, usecase, MAX_STR_LEN)) {
   1834                             ALOGV("Device already part of enabled list: %s",
   1835                                 usecase);
   1836                             free(ident1);
   1837                             break;
   1838                         }
   1839                         free(ident1);
   1840                     }
   1841                 }
   1842                 if (index == list_size) {
   1843                     ALOGV("enadev: device value to be enabled: %s", usecase);
   1844                     snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   1845                          usecase);
   1846                 }
   1847                 snd_ucm_add_ident_to_list(&uc_mgr->card_ctxt_ptr->mod_list_head,
   1848                     value);
   1849                 /* Enable the mixer controls for the new use case
   1850                  * for all the enabled devices */
   1851                 ret = set_controls_of_usecase_for_device(uc_mgr, value,
   1852                       usecase, 1, CTRL_LIST_MODIFIER);
   1853             }
   1854         }
   1855     } else if (!strncmp(identifier, "_dismod", 7)) {
   1856         ret = snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->mod_list_head,
   1857               value);
   1858         if (ret < 0) {
   1859             ALOGE("Modifier not enabled currently, invalid modifier");
   1860         } else {
   1861             ALOGV("dismod: modifier value to be disabled: %s", value);
   1862             /* Enable the mixer controls for the new use case
   1863              * for all the enabled devices */
   1864             ret = set_controls_of_usecase_for_device(uc_mgr, value, usecase,
   1865                       0, CTRL_LIST_MODIFIER);
   1866         }
   1867     } else {
   1868         ALOGE("Unknown identifier value: %s", identifier);
   1869     }
   1870     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   1871     return ret;
   1872 }
   1873 
   1874 /**
   1875  * Open and initialise use case core for sound card
   1876  * uc_mgr - Returned use case manager pointer
   1877  * card_name - Sound card name.
   1878  * returns 0 on success, otherwise a negative error code
   1879  */
   1880 int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr, const char *card_name)
   1881 {
   1882     snd_use_case_mgr_t *uc_mgr_ptr = NULL;
   1883     int index, ret = -EINVAL;
   1884     char tmp[2];
   1885 
   1886     ALOGV("snd_use_case_open(): card_name %s", card_name);
   1887 
   1888     if (card_name == NULL) {
   1889         ALOGE("snd_use_case_mgr_open: failed, invalid arguments");
   1890         return ret;
   1891     }
   1892 
   1893     for (index = 0; index < (int)MAX_NUM_CARDS; index++) {
   1894         if(!strncmp(card_name, card_mapping_list[index].card_name,
   1895            (strlen(card_mapping_list[index].card_name)+1))) {
   1896             ret = 0;
   1897             break;
   1898         }
   1899     }
   1900 
   1901     if (ret < 0) {
   1902         ALOGE("Card %s not found", card_name);
   1903     } else {
   1904         uc_mgr_ptr = (snd_use_case_mgr_t *)calloc(1,
   1905                          sizeof(snd_use_case_mgr_t));
   1906         if (uc_mgr_ptr == NULL) {
   1907             ALOGE("Failed to allocate memory for instance");
   1908             return -ENOMEM;
   1909         }
   1910         uc_mgr_ptr->snd_card_index = index;
   1911         uc_mgr_ptr->card_ctxt_ptr = (card_ctxt_t *)calloc(1,
   1912                                         sizeof(card_ctxt_t));
   1913         if (uc_mgr_ptr->card_ctxt_ptr == NULL) {
   1914             ALOGE("Failed to allocate memory for card context");
   1915             free(uc_mgr_ptr);
   1916             uc_mgr_ptr = NULL;
   1917             return -ENOMEM;
   1918         }
   1919         uc_mgr_ptr->card_ctxt_ptr->card_number =
   1920             card_mapping_list[index].card_number;
   1921         uc_mgr_ptr->card_ctxt_ptr->card_name =
   1922             (char *)malloc((strlen(card_name)+1)*sizeof(char));
   1923         if (uc_mgr_ptr->card_ctxt_ptr->card_name == NULL) {
   1924             ALOGE("Failed to allocate memory for card name");
   1925             free(uc_mgr_ptr->card_ctxt_ptr);
   1926             free(uc_mgr_ptr);
   1927             uc_mgr_ptr = NULL;
   1928             return -ENOMEM;
   1929         }
   1930         strlcpy(uc_mgr_ptr->card_ctxt_ptr->card_name, card_name,
   1931             ((strlen(card_name)+1)*sizeof(char)));
   1932         uc_mgr_ptr->card_ctxt_ptr->control_device =
   1933             (char *)malloc((strlen("/dev/snd/controlC")+2)*sizeof(char));
   1934         if (uc_mgr_ptr->card_ctxt_ptr->control_device == NULL) {
   1935             ALOGE("Failed to allocate memory for control device string");
   1936             free(uc_mgr_ptr->card_ctxt_ptr->card_name);
   1937             free(uc_mgr_ptr->card_ctxt_ptr);
   1938             free(uc_mgr_ptr);
   1939             uc_mgr_ptr = NULL;
   1940             return -ENOMEM;
   1941         }
   1942         strlcpy(uc_mgr_ptr->card_ctxt_ptr->control_device,
   1943             "/dev/snd/controlC", 18);
   1944         snprintf(tmp, sizeof(tmp), "%d",
   1945             uc_mgr_ptr->card_ctxt_ptr->card_number);
   1946         strlcat(uc_mgr_ptr->card_ctxt_ptr->control_device, tmp,
   1947             (strlen("/dev/snd/controlC")+2)*sizeof(char));
   1948         uc_mgr_ptr->device_list_count = 0;
   1949         uc_mgr_ptr->modifier_list_count = 0;
   1950         uc_mgr_ptr->current_device_list = NULL;
   1951         uc_mgr_ptr->current_modifier_list = NULL;
   1952         uc_mgr_ptr->current_tx_device = -1;
   1953         uc_mgr_ptr->current_rx_device = -1;
   1954         pthread_mutexattr_init(&uc_mgr_ptr->card_ctxt_ptr->card_lock_attr);
   1955         pthread_mutex_init(&uc_mgr_ptr->card_ctxt_ptr->card_lock,
   1956             &uc_mgr_ptr->card_ctxt_ptr->card_lock_attr);
   1957         strlcpy(uc_mgr_ptr->card_ctxt_ptr->current_verb,
   1958                 SND_USE_CASE_VERB_INACTIVE, MAX_STR_LEN);
   1959         /* Reset all mixer controls if any applied
   1960          * previously for the same card */
   1961     snd_use_case_mgr_reset(uc_mgr_ptr);
   1962         uc_mgr_ptr->card_ctxt_ptr->current_verb_index = -1;
   1963         /* Parse config files and update mixer controls */
   1964         ret = snd_ucm_parse(&uc_mgr_ptr);
   1965         if(ret < 0) {
   1966             ALOGE("Failed to parse config files: %d", ret);
   1967             snd_ucm_free_mixer_list(&uc_mgr_ptr);
   1968         }
   1969         ALOGV("Open mixer device: %s",
   1970             uc_mgr_ptr->card_ctxt_ptr->control_device);
   1971         uc_mgr_ptr->card_ctxt_ptr->mixer_handle =
   1972             mixer_open(uc_mgr_ptr->card_ctxt_ptr->control_device);
   1973         ALOGV("Mixer handle %p", uc_mgr_ptr->card_ctxt_ptr->mixer_handle);
   1974         *uc_mgr = uc_mgr_ptr;
   1975     }
   1976     ALOGV("snd_use_case_open(): returning instance %p", uc_mgr_ptr);
   1977     return ret;
   1978 }
   1979 
   1980 
   1981 /**
   1982  * \brief Reload and re-parse use case configuration files for sound card.
   1983  * \param uc_mgr Use case manager
   1984  * \return zero if success, otherwise a negative error code
   1985  */
   1986 int snd_use_case_mgr_reload(snd_use_case_mgr_t *uc_mgr) {
   1987     ALOGE("Reload is not implemented for now as there is no use case currently");
   1988     return 0;
   1989 }
   1990 
   1991 /**
   1992  * \brief Close use case manager
   1993  * \param uc_mgr Use case manager
   1994  * \return zero if success, otherwise a negative error code
   1995  */
   1996 int snd_use_case_mgr_close(snd_use_case_mgr_t *uc_mgr)
   1997 {
   1998     int ret = 0;
   1999 
   2000     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) ||
   2001         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL)) {
   2002         ALOGE("snd_use_case_mgr_close(): failed, invalid arguments");
   2003         return -EINVAL;
   2004     }
   2005 
   2006     ALOGV("snd_use_case_close(): instance %p", uc_mgr);
   2007     ret = snd_use_case_mgr_reset(uc_mgr);
   2008     if (ret < 0)
   2009         ALOGE("Failed to reset ucm session");
   2010     snd_ucm_free_mixer_list(&uc_mgr);
   2011     pthread_mutexattr_destroy(&uc_mgr->card_ctxt_ptr->card_lock_attr);
   2012     pthread_mutex_destroy(&uc_mgr->card_ctxt_ptr->card_lock);
   2013     if (uc_mgr->card_ctxt_ptr->mixer_handle) {
   2014         mixer_close(uc_mgr->card_ctxt_ptr->mixer_handle);
   2015         uc_mgr->card_ctxt_ptr->mixer_handle = NULL;
   2016     }
   2017     uc_mgr->snd_card_index = -1;
   2018     uc_mgr->current_tx_device = -1;
   2019     uc_mgr->current_rx_device = -1;
   2020     free(uc_mgr->card_ctxt_ptr->control_device);
   2021     free(uc_mgr->card_ctxt_ptr->card_name);
   2022     free(uc_mgr->card_ctxt_ptr);
   2023     uc_mgr->card_ctxt_ptr = NULL;
   2024     free(uc_mgr);
   2025     uc_mgr = NULL;
   2026     ALOGV("snd_use_case_mgr_close(): card instace closed successfully");
   2027     return ret;
   2028 }
   2029 
   2030 /**
   2031  * \brief Reset use case manager verb, device, modifier to deafult settings.
   2032  * \param uc_mgr Use case manager
   2033  * \return zero if success, otherwise a negative error code
   2034  */
   2035 int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
   2036 {
   2037     char *ident_value;
   2038     int index, list_size, ret = 0;
   2039 
   2040     ALOGV("snd_use_case_reset(): instance %p", uc_mgr);
   2041     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
   2042     if ((uc_mgr->snd_card_index >= (int)MAX_NUM_CARDS) ||
   2043         (uc_mgr->snd_card_index < 0) || (uc_mgr->card_ctxt_ptr == NULL)) {
   2044         ALOGE("snd_use_case_mgr_reset(): failed, invalid arguments");
   2045         pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   2046         return -EINVAL;
   2047     }
   2048 
   2049     /* Disable mixer controls of all the enabled modifiers */
   2050     list_size = snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
   2051     for (index = (list_size-1); index >= 0; index--) {
   2052         if ((ident_value =
   2053             snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->mod_list_head,
   2054                 index))) {
   2055             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->mod_list_head,
   2056                 ident_value);
   2057             ret = set_controls_of_usecase_for_all_devices(uc_mgr,
   2058                       ident_value, 0, CTRL_LIST_MODIFIER);
   2059         if (ret != 0)
   2060                 ALOGE("Failed to disable mixer controls for %s", ident_value);
   2061             free(ident_value);
   2062         }
   2063     }
   2064     /* Clear the enabled modifiers list */
   2065     if (uc_mgr->modifier_list_count) {
   2066         for (index = 0; index < uc_mgr->modifier_list_count; index++) {
   2067             free(uc_mgr->current_modifier_list[index]);
   2068             uc_mgr->current_modifier_list[index] = NULL;
   2069         }
   2070         free(uc_mgr->current_modifier_list);
   2071         uc_mgr->current_modifier_list = NULL;
   2072         uc_mgr->modifier_list_count = 0;
   2073     }
   2074     /* Disable mixer controls of current use case verb */
   2075     if(strncmp(uc_mgr->card_ctxt_ptr->current_verb, SND_USE_CASE_VERB_INACTIVE,
   2076        strlen(SND_USE_CASE_VERB_INACTIVE))) {
   2077         ret = set_controls_of_usecase_for_all_devices(uc_mgr,
   2078                   uc_mgr->card_ctxt_ptr->current_verb, 0, CTRL_LIST_VERB);
   2079         if (ret != 0)
   2080             ALOGE("Failed to disable mixer controls for %s",
   2081                 uc_mgr->card_ctxt_ptr->current_verb);
   2082         strlcpy(uc_mgr->card_ctxt_ptr->current_verb, SND_USE_CASE_VERB_INACTIVE,
   2083             MAX_STR_LEN);
   2084     }
   2085     /* Disable mixer controls of all the enabled devices */
   2086     list_size = snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->dev_list_head);
   2087     for (index = (list_size-1); index >= 0; index--) {
   2088         if ((ident_value =
   2089             snd_ucm_get_value_at_index(uc_mgr->card_ctxt_ptr->dev_list_head,
   2090                 index))) {
   2091             snd_ucm_del_ident_from_list(&uc_mgr->card_ctxt_ptr->dev_list_head,
   2092                 ident_value);
   2093             ret = set_controls_of_device_for_all_usecases(uc_mgr,
   2094                       ident_value, 0);
   2095         if (ret != 0)
   2096                 ALOGE("Failed to disable or no mixer controls set for %s",
   2097                     ident_value);
   2098         free(ident_value);
   2099         }
   2100     }
   2101     /* Clear the enabled devices list */
   2102     if (uc_mgr->device_list_count) {
   2103         for (index = 0; index < uc_mgr->device_list_count; index++) {
   2104             free(uc_mgr->current_device_list[index]);
   2105             uc_mgr->current_device_list[index] = NULL;
   2106         }
   2107         free(uc_mgr->current_device_list);
   2108         uc_mgr->current_device_list = NULL;
   2109         uc_mgr->device_list_count = 0;
   2110     }
   2111     uc_mgr->current_tx_device = -1;
   2112     uc_mgr->current_rx_device = -1;
   2113     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   2114     return ret;
   2115 }
   2116 
   2117 /* 2nd stage parsing done in seperate thread */
   2118 void *second_stage_parsing_thread(void *uc_mgr_ptr)
   2119 {
   2120     use_case_verb_t *verb_list;
   2121     char path[200];
   2122     struct stat st;
   2123     int fd, index = 0, ret = 0, rc = 0;
   2124     char *read_buf = NULL, *next_str = NULL, *current_str = NULL, *buf = NULL;
   2125     char *p = NULL, *verb_name = NULL, *file_name = NULL, *temp_ptr = NULL;
   2126     snd_use_case_mgr_t **uc_mgr = (snd_use_case_mgr_t **)&uc_mgr_ptr;
   2127 
   2128     strlcpy(path, CONFIG_DIR, (strlen(CONFIG_DIR)+1));
   2129     strlcat(path, (*uc_mgr)->card_ctxt_ptr->card_name, sizeof(path));
   2130     ALOGV("master config file path:%s", path);
   2131     fd = open(path, O_RDONLY);
   2132     if (fd < 0) {
   2133         ALOGE("failed to open config file %s error %d\n", path, errno);
   2134         return NULL;
   2135     }
   2136     if (fstat(fd, &st) < 0) {
   2137         ALOGE("failed to stat %s error %d\n", path, errno);
   2138         close(fd);
   2139         return NULL;
   2140     }
   2141     read_buf = (char *) mmap(0, st.st_size, PROT_READ | PROT_WRITE,
   2142                MAP_PRIVATE, fd, 0);
   2143     if (read_buf == MAP_FAILED) {
   2144         ALOGE("failed to mmap file error %d\n", errno);
   2145         close(fd);
   2146         return NULL;
   2147     }
   2148     current_str = read_buf;
   2149     verb_name = NULL;
   2150     while (*current_str != (char)EOF)  {
   2151         next_str = strchr(current_str, '\n');
   2152         if (!next_str)
   2153             break;
   2154         *next_str++ = '\0';
   2155         if (verb_name == NULL) {
   2156             buf = strstr(current_str, "SectionUseCase");
   2157             if (buf == NULL) {
   2158                 if((current_str = next_str) == NULL)
   2159                     break;
   2160                 else
   2161                     continue;
   2162             }
   2163             /* Ignore parsing first use case (HiFi) as it is already parsed
   2164              * in 1st stage of parsing */
   2165             if (index == 0) {
   2166                 index++;
   2167                 if((current_str = next_str) == NULL)
   2168                     break;
   2169                 else
   2170                     continue;
   2171             }
   2172             p = strtok_r(buf, ".", &temp_ptr);
   2173             while (p != NULL) {
   2174                 p = strtok_r(NULL, "\"", &temp_ptr);
   2175                 if (p == NULL)
   2176                     break;
   2177                 verb_name = (char *)malloc((strlen(p)+1)*sizeof(char));
   2178                 if(verb_name == NULL) {
   2179                     ret = -ENOMEM;
   2180                     break;
   2181                 }
   2182                 strlcpy(verb_name, p, (strlen(p)+1)*sizeof(char));
   2183                 break;
   2184             }
   2185         } else {
   2186             buf = strstr(current_str, "File");
   2187             if (buf == NULL) {
   2188                 if((current_str = next_str) == NULL)
   2189                     break;
   2190                 else
   2191                     continue;
   2192             }
   2193             p = strtok_r(buf, "\"", &temp_ptr);
   2194             while (p != NULL) {
   2195                 p = strtok_r(NULL, "\"", &temp_ptr);
   2196                 if (p == NULL)
   2197                     break;
   2198                 file_name = (char *)malloc((strlen(p)+1)*sizeof(char));
   2199                 if(file_name == NULL) {
   2200                     ret = -ENOMEM;
   2201                     break;
   2202                 }
   2203                 strlcpy(file_name, p, (strlen(p)+1)*sizeof(char));
   2204                 break;
   2205             }
   2206             verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   2207             if (file_name != NULL) {
   2208                 ret = snd_ucm_parse_verb(uc_mgr, file_name, index);
   2209                 verb_list[index].use_case_name =
   2210                     (char *)malloc((strlen(verb_name)+1)*sizeof(char));
   2211                 strlcpy(verb_list[index].use_case_name, verb_name,
   2212                     ((strlen(verb_name)+1)*sizeof(char)));
   2213                 /* Verb list might have been appended with END OF LIST in
   2214                  * 1st stage parsing. Delete this entry so that new verbs
   2215                  * are appended from here and END OF LIST will be added
   2216                  * again at the end of 2nd stage parsing
   2217                  */
   2218                 if((*uc_mgr)->card_ctxt_ptr->verb_list[index]) {
   2219                     free((*uc_mgr)->card_ctxt_ptr->verb_list[index]);
   2220                     (*uc_mgr)->card_ctxt_ptr->verb_list[index] = NULL;
   2221                 }
   2222                 (*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2223                     (char *)malloc((strlen(verb_name)+1)*sizeof(char));
   2224                 strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index], verb_name,
   2225                     ((strlen(verb_name)+1)*sizeof(char)));
   2226                 free(verb_name);
   2227                 verb_name = NULL;
   2228                 free(file_name);
   2229                 file_name = NULL;
   2230             }
   2231             index++;
   2232             (*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2233                 (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2234             strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index],
   2235                  SND_UCM_END_OF_LIST,
   2236                  ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   2237         }
   2238         if((current_str = next_str) == NULL)
   2239             break;
   2240     }
   2241     if (verb_name != NULL) {
   2242         free(verb_name);
   2243         verb_name = NULL;
   2244     }
   2245     if (file_name != NULL) {
   2246         free(file_name);
   2247         file_name = NULL;
   2248     }
   2249     munmap(read_buf, st.st_size);
   2250     close(fd);
   2251 #if PARSE_DEBUG
   2252         /* Prints use cases and mixer controls parsed from config files */
   2253         snd_ucm_print((*uc_mgr));
   2254 #endif
   2255     if(ret < 0)
   2256         ALOGE("Failed to parse config files: %d", ret);
   2257     ALOGE("Exiting parsing thread uc_mgr %p\n", uc_mgr);
   2258     return NULL;
   2259 }
   2260 
   2261 /* Function can be used by UCM clients to wait until parsing completes
   2262  * uc_mgr - use case manager structure
   2263  * Returns 0 on success, error number otherwise
   2264 */
   2265 int snd_use_case_mgr_wait_for_parsing(snd_use_case_mgr_t *uc_mgr)
   2266 {
   2267     int ret;
   2268 
   2269     ret = pthread_join(uc_mgr->thr, NULL);
   2270     return ret;
   2271 }
   2272 
   2273 /* Parse config files and update mixer controls for the use cases
   2274  * 1st stage parsing done to parse HiFi config file
   2275  * uc_mgr - use case manager structure
   2276  * Returns 0 on sucess, negative error code otherwise
   2277  */
   2278 static int snd_ucm_parse(snd_use_case_mgr_t **uc_mgr)
   2279 {
   2280     use_case_verb_t *verb_list;
   2281     struct stat st;
   2282     int fd, verb_count, index = 0, ret = 0, rc;
   2283     char *read_buf, *next_str, *current_str, *buf, *p, *verb_name;
   2284     char *file_name = NULL, *temp_ptr;
   2285     char path[200];
   2286 
   2287     strlcpy(path, CONFIG_DIR, (strlen(CONFIG_DIR)+1));
   2288     strlcat(path, (*uc_mgr)->card_ctxt_ptr->card_name, sizeof(path));
   2289     ALOGV("master config file path:%s", path);
   2290     fd = open(path, O_RDONLY);
   2291     if (fd < 0) {
   2292         ALOGE("failed to open config file %s error %d\n", path, errno);
   2293         return -EINVAL;
   2294     }
   2295     if (fstat(fd, &st) < 0) {
   2296         ALOGE("failed to stat %s error %d\n", path, errno);
   2297         close(fd);
   2298         return -EINVAL;
   2299     }
   2300     read_buf = (char *) mmap(0, st.st_size, PROT_READ | PROT_WRITE,
   2301                MAP_PRIVATE, fd, 0);
   2302     if (read_buf == MAP_FAILED) {
   2303         ALOGE("failed to mmap file error %d\n", errno);
   2304         close(fd);
   2305         return -EINVAL;
   2306     }
   2307     current_str = read_buf;
   2308     verb_count = get_verb_count(current_str);
   2309     (*uc_mgr)->card_ctxt_ptr->use_case_verb_list =
   2310         (use_case_verb_t *)malloc((verb_count+1)*(sizeof(use_case_verb_t)));
   2311     if ((*uc_mgr)->card_ctxt_ptr->use_case_verb_list == NULL) {
   2312         ALOGE("failed to allocate memory for use case verb list\n");
   2313         munmap(read_buf, st.st_size);
   2314         close(fd);
   2315         return -ENOMEM;
   2316     }
   2317     if (((*uc_mgr)->card_ctxt_ptr->verb_list =
   2318         (char **)malloc((verb_count+2)*(sizeof(char *)))) == NULL) {
   2319         ALOGE("failed to allocate memory for verb list\n");
   2320         munmap(read_buf, st.st_size);
   2321         close(fd);
   2322         return -ENOMEM;
   2323     }
   2324     verb_name = NULL;
   2325     if ((ret = is_single_config_format(current_str))) {
   2326         ALOGD("Single config file format detected\n");
   2327         ret = parse_single_config_format(uc_mgr, current_str, verb_count);
   2328         munmap(read_buf, st.st_size);
   2329         close(fd);
   2330         return ret;
   2331     }
   2332     while (*current_str != (char)EOF)  {
   2333         next_str = strchr(current_str, '\n');
   2334         if (!next_str)
   2335             break;
   2336         *next_str++ = '\0';
   2337         if (verb_name == NULL) {
   2338             buf = strstr(current_str, "SectionUseCase");
   2339             if (buf == NULL) {
   2340                 if((current_str = next_str) == NULL)
   2341                     break;
   2342                 else
   2343                     continue;
   2344             }
   2345             verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   2346             p = strtok_r(buf, ".", &temp_ptr);
   2347             while (p != NULL) {
   2348                 p = strtok_r(NULL, "\"", &temp_ptr);
   2349                 if (p == NULL)
   2350                     break;
   2351                 verb_name = (char *)malloc((strlen(p)+1)*sizeof(char));
   2352                 if(verb_name == NULL) {
   2353                     ret = -ENOMEM;
   2354                     break;
   2355                 }
   2356                 strlcpy(verb_name, p, (strlen(p)+1)*sizeof(char));
   2357                 if ((verb_list[index].use_case_name =
   2358                     (char *)malloc((strlen(verb_name)+1)*sizeof(char)))) {
   2359                     strlcpy(verb_list[index].use_case_name,
   2360                         verb_name, ((strlen(verb_name)+1)*sizeof(char)));
   2361                 } else {
   2362                     ret = -ENOMEM;
   2363                     break;
   2364                 }
   2365                 if (((*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2366                     (char *)malloc((strlen(verb_name)+1)*sizeof(char)))) {
   2367                     strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index],
   2368                         verb_name, ((strlen(verb_name)+1)*sizeof(char)));
   2369                 } else {
   2370                     ret = -ENOMEM;
   2371                     break;
   2372                 }
   2373                 break;
   2374             }
   2375         } else {
   2376             buf = strstr(current_str, "File");
   2377             if (buf == NULL) {
   2378                 if((current_str = next_str) == NULL)
   2379                     break;
   2380                 else
   2381                     continue;
   2382             }
   2383             p = strtok_r(buf, "\"", &temp_ptr);
   2384             while (p != NULL) {
   2385                 p = strtok_r(NULL, "\"", &temp_ptr);
   2386                 if (p == NULL)
   2387                     break;
   2388                 file_name = (char *)malloc((strlen(p)+1)*sizeof(char));
   2389                 if(file_name == NULL) {
   2390                     ret = -ENOMEM;
   2391                     break;
   2392                 }
   2393                 strlcpy(file_name, p, (strlen(p)+1)*sizeof(char));
   2394                 break;
   2395             }
   2396             if (file_name != NULL) {
   2397                 ret = snd_ucm_parse_verb(uc_mgr, file_name, index);
   2398                 if (ret < 0)
   2399                     ALOGE("Failed to parse config file %s\n", file_name);
   2400                 free(verb_name);
   2401                 verb_name = NULL;
   2402                 free(file_name);
   2403                 file_name = NULL;
   2404             }
   2405             index++;
   2406             /* Break here so that only one first use case config file (HiFi)
   2407              * from master config file is parsed initially and all other
   2408              * config files are parsed in seperate thread created below so
   2409              * that audio HAL can initialize faster during boot-up
   2410              */
   2411             break;
   2412         }
   2413         if((current_str = next_str) == NULL)
   2414             break;
   2415     }
   2416     munmap(read_buf, st.st_size);
   2417     close(fd);
   2418     if (((*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2419         (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)))) {
   2420         strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index], SND_UCM_END_OF_LIST,
   2421                 ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   2422     } else {
   2423         ALOGE("Failed to allocate memory\n");
   2424         ret = -ENOMEM;
   2425     }
   2426     if (!ret) {
   2427         ALOGD("Creating Parsing thread uc_mgr %p\n", uc_mgr);
   2428         rc = pthread_create(&(*uc_mgr)->thr, 0, second_stage_parsing_thread,
   2429                  (void*)(*uc_mgr));
   2430         if(rc < 0) {
   2431             ALOGE("Failed to create parsing thread rc %d errno %d\n", rc, errno);
   2432         } else {
   2433             ALOGV("Prasing thread created successfully\n");
   2434         }
   2435     }
   2436     if (verb_name)
   2437         free(verb_name);
   2438     if (file_name)
   2439         free(file_name);
   2440     return ret;
   2441 }
   2442 
   2443 /* Parse a single config file format
   2444  * uc_mgr - use case manager structure
   2445  * buf - config file buffer to be parsed
   2446  * Returns 0 on sucess, negative error code otherwise
   2447  */
   2448 static int parse_single_config_format(snd_use_case_mgr_t **uc_mgr,
   2449 char *current_str, int num_verbs)
   2450 {
   2451     struct stat st;
   2452     card_mctrl_t *list;
   2453     use_case_verb_t *verb_list;
   2454     int verb_count = 0, device_count = 0, mod_count = 0, index = -1, ret = 0;
   2455     char *next_str, *buf, *p, *verb_ptr, *temp_ptr;
   2456 
   2457     verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   2458     while (*current_str != (char)EOF)  {
   2459         next_str = strchr(current_str, '\n');
   2460         if (!next_str)
   2461             break;
   2462         *next_str++ = '\0';
   2463         if ((buf = strcasestr(current_str, "SectionUseCase")) != NULL) {
   2464             if (index != -1) {
   2465                 list = (verb_list[index].verb_ctrls +
   2466                             verb_list[index].verb_count);
   2467                 list->case_name = (char *)
   2468                     malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2469                 if(list->case_name == NULL) {
   2470                     free(verb_list[index].verb_ctrls);
   2471                     return -ENOMEM;
   2472                 }
   2473                 strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   2474                    (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2475                 list->ena_mixer_list = NULL;
   2476                 list->dis_mixer_list = NULL;
   2477                 list->ena_mixer_count = 0;
   2478                 list->dis_mixer_count = 0;
   2479                 list->playback_dev_name = NULL;
   2480                 list->capture_dev_name = NULL;
   2481                 list->acdb_id = 0;
   2482                 list->capability = 0;
   2483             }
   2484             index++;
   2485             p = strtok_r(buf, ".", &temp_ptr);
   2486             while (p != NULL) {
   2487                 p = strtok_r(NULL, "\"", &temp_ptr);
   2488                 if (p == NULL)
   2489                     break;
   2490                 if ((verb_list[index].use_case_name =
   2491                     (char *)malloc((strlen(p)+1)*sizeof(char)))) {
   2492                     strlcpy(verb_list[index].use_case_name,
   2493                         p, ((strlen(p)+1)*sizeof(char)));
   2494                 } else {
   2495                     ret = -ENOMEM;
   2496                     break;
   2497                 }
   2498                 if (((*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2499                     (char *)malloc((strlen(p)+1)*sizeof(char)))) {
   2500                     strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index],
   2501                        p, ((strlen(p)+1)*sizeof(char)));
   2502                 } else {
   2503                     ret = -ENOMEM;
   2504                     break;
   2505                 }
   2506                 break;
   2507             }
   2508             verb_list[index].verb_count = 0;
   2509             verb_list[index].device_count = 0;
   2510             verb_list[index].mod_count = 0;
   2511             verb_list[index].device_list = NULL;
   2512             verb_list[index].modifier_list = NULL;
   2513             verb_list[index].verb_ctrls = NULL;
   2514             verb_list[index].device_ctrls = NULL;
   2515             verb_list[index].mod_ctrls = NULL;
   2516             verb_count = get_num_verbs_config_format(next_str);
   2517             verb_list[index].verb_ctrls = (card_mctrl_t *)
   2518                 malloc((verb_count+1)*sizeof(card_mctrl_t));
   2519             if (verb_list[index].verb_ctrls == NULL) {
   2520                ret = -ENOMEM;
   2521                break;
   2522             }
   2523             verb_list[index].verb_count = 0;
   2524         } else if (!strncasecmp(current_str, "SectionVerb", 11)) {
   2525             ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2526                     &next_str, index, CTRL_LIST_VERB);
   2527             if (ret < 0)
   2528                 break;
   2529         } else if (!strncasecmp(current_str, "SectionDevice", 13)) {
   2530             if (device_count == 0) {
   2531                 device_count = get_num_device_config_format(next_str);
   2532                 verb_list[0].device_ctrls = (card_mctrl_t *)
   2533                     malloc((device_count+1)*sizeof(card_mctrl_t));
   2534                 if (verb_list[0].device_ctrls == NULL) {
   2535                     ret = -ENOMEM;
   2536                     break;
   2537                 }
   2538                 verb_list[0].device_list =
   2539                     (char **)malloc((device_count+1)*sizeof(char *));
   2540                 if (verb_list[0].device_list == NULL)
   2541                     return -ENOMEM;
   2542                 verb_list[0].device_count = 0;
   2543             }
   2544             ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2545                       &next_str, 0, CTRL_LIST_DEVICE);
   2546             if (ret < 0) {
   2547                 break;
   2548             } else {
   2549                 list = (verb_list[0].device_ctrls +
   2550                            (verb_list[0].device_count - 1));
   2551                 verb_ptr = (char *)
   2552                     malloc((strlen(list->case_name)+1)*sizeof(char));
   2553                     if (verb_ptr == NULL) {
   2554                         ret = -ENOMEM;
   2555                         break;
   2556                     }
   2557                     strlcpy(verb_ptr, list->case_name,
   2558                         ((strlen(list->case_name)+1)*sizeof(char)));
   2559                     verb_list[0].device_list[(verb_list[0].device_count-1)]
   2560                         = verb_ptr;
   2561             }
   2562         } else if (!strncasecmp(current_str, "SectionModifier", 15)) {
   2563             if (mod_count == 0) {
   2564                 mod_count = get_num_mod_config_format(next_str);
   2565                 verb_list[0].mod_ctrls = (card_mctrl_t *)
   2566                     malloc((mod_count+1)*sizeof(card_mctrl_t));
   2567                 if (verb_list[0].mod_ctrls == NULL) {
   2568                     ret = -ENOMEM;
   2569                     break;
   2570                 }
   2571                 verb_list[0].modifier_list =
   2572                     (char **)malloc((mod_count+1)*sizeof(char *));
   2573                 if (verb_list[0].modifier_list == NULL)
   2574                     return -ENOMEM;
   2575                 verb_list[0].mod_count = 0;
   2576             }
   2577             ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2578                      &next_str, 0, CTRL_LIST_MODIFIER);
   2579             if (ret < 0) {
   2580                 break;
   2581             } else {
   2582                 list = (verb_list[0].mod_ctrls +
   2583                         (verb_list[0].mod_count - 1));
   2584                 verb_ptr = (char *)
   2585                     malloc((strlen(list->case_name)+1)*sizeof(char));
   2586                 if (verb_ptr == NULL) {
   2587                     ret = -ENOMEM;
   2588                     break;
   2589                 }
   2590                 strlcpy(verb_ptr, list->case_name,
   2591                    ((strlen(list->case_name)+1)*sizeof(char)));
   2592                 verb_list[0].modifier_list[(verb_list[0].mod_count - 1)]
   2593                     = verb_ptr;
   2594             }
   2595         }
   2596         if((current_str = next_str) == NULL)
   2597             break;
   2598     }
   2599     list = (verb_list[index].verb_ctrls +
   2600             verb_list[index].verb_count);
   2601     list->case_name =
   2602         (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2603     if(list->case_name == NULL) {
   2604         free(verb_list[index].verb_ctrls);
   2605         return -ENOMEM;
   2606     }
   2607     strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   2608         (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2609     list->ena_mixer_list = NULL;
   2610     list->dis_mixer_list = NULL;
   2611     list->ena_mixer_count = 0;
   2612     list->dis_mixer_count = 0;
   2613     list->playback_dev_name = NULL;
   2614     list->capture_dev_name = NULL;
   2615     list->acdb_id = 0;
   2616     list->capability = 0;
   2617     index++;
   2618     if (index != -1) {
   2619         if (((*uc_mgr)->card_ctxt_ptr->verb_list[index] =
   2620             (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)))) {
   2621             strlcpy((*uc_mgr)->card_ctxt_ptr->verb_list[index],
   2622                 SND_UCM_END_OF_LIST,
   2623                 ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   2624         } else {
   2625             ALOGE("Failed to allocate memory\n");
   2626             ret = -ENOMEM;
   2627         }
   2628     }
   2629     /* Add end of list to device list */
   2630     verb_ptr =
   2631        (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2632     if (verb_ptr == NULL)
   2633         return -ENOMEM;
   2634     strlcpy(verb_ptr, SND_UCM_END_OF_LIST,
   2635         ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   2636     verb_list[0].device_list[verb_list[0].device_count] = verb_ptr;
   2637     /* Add end of list to modifier list */
   2638     verb_ptr =
   2639     (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2640         if (verb_ptr == NULL)
   2641             return -ENOMEM;
   2642     strlcpy(verb_ptr, SND_UCM_END_OF_LIST,
   2643         ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   2644     verb_list[0].modifier_list[verb_list[0].mod_count] = verb_ptr;
   2645     /* Add end of list to device controls list */
   2646     list = (verb_list[0].device_ctrls +
   2647                verb_list[0].device_count);
   2648     list->case_name =
   2649         (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2650     if(list->case_name == NULL) {
   2651         free(verb_list[0].device_ctrls);
   2652         return -ENOMEM;
   2653     }
   2654     strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   2655         (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2656     list->ena_mixer_list = NULL;
   2657     list->dis_mixer_list = NULL;
   2658     list->ena_mixer_count = 0;
   2659     list->dis_mixer_count = 0;
   2660     list->playback_dev_name = NULL;
   2661     list->capture_dev_name = NULL;
   2662     list->acdb_id = 0;
   2663     list->capability = 0;
   2664     /* Add end of list to modifier controls list */
   2665     list = (verb_list[0].mod_ctrls +
   2666         verb_list[0].mod_count);
   2667     list->case_name =
   2668         (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2669     if(list->case_name == NULL) {
   2670         free(verb_list[0].mod_ctrls);
   2671         return -ENOMEM;
   2672     }
   2673     strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   2674         (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   2675     list->ena_mixer_list = NULL;
   2676     list->dis_mixer_list = NULL;
   2677     list->ena_mixer_count = 0;
   2678     list->dis_mixer_count = 0;
   2679     list->playback_dev_name = NULL;
   2680     list->capture_dev_name = NULL;
   2681     list->acdb_id = 0;
   2682     list->capability = 0;
   2683     for (index = 1; index < num_verbs; index++) {
   2684         verb_list[index].device_ctrls = verb_list[0].device_ctrls;
   2685         verb_list[index].device_list = verb_list[0].device_list;
   2686         verb_list[index].device_count = verb_list[0].device_count;
   2687         verb_list[index].mod_ctrls = verb_list[0].mod_ctrls;
   2688         verb_list[index].modifier_list = verb_list[0].modifier_list;
   2689         verb_list[index].mod_count = verb_list[0].mod_count;
   2690     }
   2691     if (ret < 0) {
   2692         ALOGE("Failed to parse config file ret %d errno %d\n", ret, errno);
   2693     } else {
   2694         ALOGV("Prasing done successfully\n");
   2695 #if PARSE_DEBUG
   2696         /* Prints use cases and mixer controls parsed from config files */
   2697         snd_ucm_print((*uc_mgr));
   2698 #endif
   2699     }
   2700     return ret;
   2701 }
   2702 
   2703 /* Returns number of verb sections for specific use case verb*/
   2704 static int get_num_verbs_config_format(const char *nxt_str)
   2705 {
   2706     char *current_str, *next_str, *str_addr, *buf;
   2707     int count = 0;
   2708 
   2709     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   2710     if (next_str == NULL) {
   2711         ALOGE("Failed to allocate memory");
   2712         return -ENOMEM;
   2713     }
   2714     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   2715     str_addr = next_str;
   2716     current_str = next_str;
   2717     while(1) {
   2718         next_str = strchr(current_str, '\n');
   2719         if (!next_str)
   2720             break;
   2721         *next_str++ = '\0';
   2722         buf = strcasestr(current_str, "SectionUseCase");
   2723         if (buf != NULL)
   2724             break;
   2725         buf = strcasestr(current_str, "SectionVerb");
   2726         if (buf != NULL)
   2727             count++;
   2728         if (*next_str == (char)EOF)
   2729             break;
   2730         if((current_str = next_str) == NULL)
   2731             break;
   2732     }
   2733     free(str_addr);
   2734     return count;
   2735 }
   2736 
   2737 /* Returns number of common device sections for all use case verbs*/
   2738 static int get_num_device_config_format(const char *nxt_str)
   2739 {
   2740     char *current_str, *next_str, *str_addr, *buf;
   2741     int count = 1;
   2742 
   2743     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   2744     if (next_str == NULL) {
   2745         ALOGE("Failed to allocate memory");
   2746         return -ENOMEM;
   2747     }
   2748     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   2749     str_addr = next_str;
   2750     current_str = next_str;
   2751     while(1) {
   2752         next_str = strchr(current_str, '\n');
   2753         if (!next_str)
   2754             break;
   2755         *next_str++ = '\0';
   2756         buf = strcasestr(current_str, "SectionDevice");
   2757         if (buf != NULL)
   2758             count++;
   2759         if (*next_str == (char)EOF)
   2760             break;
   2761         if((current_str = next_str) == NULL)
   2762             break;
   2763     }
   2764     free(str_addr);
   2765     return count;
   2766 }
   2767 
   2768 /* Returns number of common modifier sections for all use case verbs*/
   2769 static int get_num_mod_config_format(const char *nxt_str)
   2770 {
   2771     char *current_str, *next_str, *str_addr, *buf;
   2772     int count = 1;
   2773 
   2774     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   2775     if (next_str == NULL) {
   2776         ALOGE("Failed to allocate memory");
   2777         return -ENOMEM;
   2778     }
   2779     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   2780     str_addr = next_str;
   2781     current_str = next_str;
   2782     while(1) {
   2783         next_str = strchr(current_str, '\n');
   2784         if (!next_str)
   2785             break;
   2786         *next_str++ = '\0';
   2787         buf = strcasestr(current_str, "SectionModifier");
   2788         if (buf != NULL)
   2789             count++;
   2790         if (*next_str == (char)EOF)
   2791             break;
   2792         if((current_str = next_str) == NULL)
   2793             break;
   2794     }
   2795     free(str_addr);
   2796     return count;
   2797 }
   2798 
   2799 /* Gets the number of use case verbs defined by master config file */
   2800 static int get_verb_count(const char *nxt_str)
   2801 {
   2802     char *current_str, *next_str, *str_addr, *buf, *p;
   2803     int count = 0;
   2804 
   2805     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   2806     if (next_str == NULL) {
   2807         ALOGE("Failed to allocate memory");
   2808         return -ENOMEM;
   2809     }
   2810     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   2811     str_addr = next_str;
   2812     current_str = next_str;
   2813     while(1) {
   2814         next_str = strchr(current_str, '\n');
   2815         if (!next_str)
   2816             break;
   2817         *next_str++ = '\0';
   2818         buf = strstr(current_str, "SectionUseCase");
   2819         if (buf != NULL)
   2820             count++;
   2821         if (*next_str == (char)EOF)
   2822             break;
   2823         if((current_str = next_str) == NULL)
   2824             break;
   2825     }
   2826     free(str_addr);
   2827     return count;
   2828 }
   2829 
   2830 /* Returns one if single config file per sound card format is being used */
   2831 static int is_single_config_format(const char *nxt_str)
   2832 {
   2833     char *current_str, *next_str, *str_addr, *buf;
   2834     int ret = 1, count = 0;
   2835 
   2836     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   2837     if (next_str == NULL) {
   2838         ALOGE("Failed to allocate memory");
   2839         return -ENOMEM;
   2840     }
   2841     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   2842     str_addr = next_str;
   2843     current_str = next_str;
   2844     while(1) {
   2845         next_str = strchr(current_str, '\n');
   2846         if (!next_str)
   2847             break;
   2848         *next_str++ = '\0';
   2849         buf = strstr(current_str, "SectionUseCase");
   2850         if (buf != NULL)
   2851             count++;
   2852         buf = strstr(current_str, "File");
   2853         if (buf != NULL)
   2854             ret = 0;
   2855         if ((*next_str == (char)EOF) || (count == 2))
   2856             break;
   2857         if((current_str = next_str) == NULL)
   2858             break;
   2859     }
   2860     free(str_addr);
   2861     return ret;
   2862 }
   2863 
   2864 /* Parse a use case verb config files and update mixer controls for the verb
   2865  * uc_mgr - use case manager structure
   2866  * file_name - use case verb config file name
   2867  * index - index of the verb in the list
   2868  * Returns 0 on sucess, negative error code otherwise
   2869  */
   2870 static int snd_ucm_parse_verb(snd_use_case_mgr_t **uc_mgr,
   2871 const char *file_name, int index)
   2872 {
   2873     struct stat st;
   2874     card_mctrl_t *list;
   2875     int device_count, modifier_count;
   2876     int fd, ret = 0, parse_count = 0;
   2877     char *read_buf, *next_str, *current_str, *verb_ptr;
   2878     char path[200];
   2879     use_case_verb_t *verb_list;
   2880 
   2881     strlcpy(path, CONFIG_DIR, (strlen(CONFIG_DIR)+1));
   2882     strlcat(path, file_name, sizeof(path));
   2883     ALOGV("path:%s", path);
   2884     verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   2885     while(1) {
   2886         device_count = 0; modifier_count = 0;
   2887         if (parse_count == 0) {
   2888             verb_list[index].verb_count = 0;
   2889             verb_list[index].device_count = 0;
   2890             verb_list[index].mod_count = 0;
   2891             verb_list[index].device_list = NULL;
   2892             verb_list[index].modifier_list = NULL;
   2893             verb_list[index].verb_ctrls = NULL;
   2894             verb_list[index].device_ctrls = NULL;
   2895             verb_list[index].mod_ctrls = NULL;
   2896         }
   2897         fd = open(path, O_RDONLY);
   2898         if (fd < 0) {
   2899              ALOGE("failed to open config file %s error %d\n", path, errno);
   2900              return -EINVAL;
   2901         }
   2902         if (fstat(fd, &st) < 0) {
   2903             ALOGE("failed to stat %s error %d\n", path, errno);
   2904             close(fd);
   2905             return -EINVAL;
   2906         }
   2907         read_buf = (char *) mmap(0, st.st_size, PROT_READ | PROT_WRITE,
   2908                    MAP_PRIVATE, fd, 0);
   2909         if (read_buf == MAP_FAILED) {
   2910             ALOGE("failed to mmap file error %d\n", errno);
   2911             close(fd);
   2912             return -EINVAL;
   2913         }
   2914         current_str = read_buf;
   2915         while (*current_str != (char)EOF)  {
   2916             next_str = strchr(current_str, '\n');
   2917             if (!next_str)
   2918                 break;
   2919             *next_str++ = '\0';
   2920             if (!strncasecmp(current_str, "SectionVerb", 11)) {
   2921                 if (parse_count == 0) {
   2922                     verb_list[index].verb_count++;
   2923                 } else {
   2924                     ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2925                               &next_str, index, CTRL_LIST_VERB);
   2926                     if (ret < 0)
   2927                         break;
   2928                 }
   2929             } else if (!strncasecmp(current_str, "SectionDevice", 13)) {
   2930                 if (parse_count == 0) {
   2931                     verb_list[index].device_count++;
   2932                     device_count++;
   2933                 } else {
   2934                     ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2935                               &next_str, index, CTRL_LIST_DEVICE);
   2936                     if (ret < 0) {
   2937                         break;
   2938                     } else {
   2939                         list = (verb_list[index].device_ctrls +
   2940                                    (verb_list[index].device_count - 1));
   2941                         verb_ptr = (char *)
   2942                             malloc((strlen(list->case_name)+1)*sizeof(char));
   2943                         if (verb_ptr == NULL) {
   2944                             ret = -ENOMEM;
   2945                             break;
   2946                         }
   2947                         strlcpy(verb_ptr, list->case_name,
   2948                             ((strlen(list->case_name)+1)*sizeof(char)));
   2949                         verb_list[index].device_list[device_count] = verb_ptr;
   2950                         device_count++;
   2951                     }
   2952                 }
   2953             } else if (!strncasecmp(current_str, "SectionModifier", 15)) {
   2954                 if (parse_count == 0) {
   2955                     verb_list[index].mod_count++;
   2956                     modifier_count++;
   2957                 } else {
   2958                     ret = snd_ucm_parse_section(uc_mgr, &current_str,
   2959                               &next_str, index, CTRL_LIST_MODIFIER);
   2960                     if (ret < 0) {
   2961                         break;
   2962                     } else {
   2963                         list = (verb_list[index].mod_ctrls +
   2964                                (verb_list[index].mod_count - 1));
   2965                         verb_ptr = (char *)
   2966                             malloc((strlen(list->case_name)+1)*sizeof(char));
   2967                         if (verb_ptr == NULL) {
   2968                             ret = -ENOMEM;
   2969                             break;
   2970                         }
   2971                         strlcpy(verb_ptr, list->case_name,
   2972                             ((strlen(list->case_name)+1)*sizeof(char)));
   2973                         verb_list[index].modifier_list[modifier_count]
   2974                             = verb_ptr;
   2975                         modifier_count++;
   2976                     }
   2977                 }
   2978             }
   2979             if((current_str = next_str) == NULL)
   2980                 break;
   2981         }
   2982         munmap(read_buf, st.st_size);
   2983         close(fd);
   2984         if(ret < 0)
   2985             return ret;
   2986         if (parse_count == 0) {
   2987             verb_list[index].device_list =
   2988                 (char **)malloc((device_count+1)*sizeof(char *));
   2989             if (verb_list[index].device_list == NULL)
   2990                 return -ENOMEM;
   2991             verb_list[index].modifier_list =
   2992                 (char **)malloc((modifier_count+1)*sizeof(char *));
   2993             if (verb_list[index].modifier_list == NULL)
   2994                 return -ENOMEM;
   2995             parse_count += verb_list[index].verb_count;
   2996             verb_list[index].verb_ctrls = (card_mctrl_t *)
   2997                 malloc((verb_list[index].verb_count+1)*sizeof(card_mctrl_t));
   2998             if (verb_list[index].verb_ctrls == NULL) {
   2999                ret = -ENOMEM;
   3000                break;
   3001             }
   3002             verb_list[index].verb_count = 0;
   3003             parse_count += verb_list[index].device_count;
   3004             verb_list[index].device_ctrls = (card_mctrl_t *)
   3005                 malloc((verb_list[index].device_count+1)*sizeof(card_mctrl_t));
   3006             if (verb_list[index].device_ctrls == NULL) {
   3007                ret = -ENOMEM;
   3008                break;
   3009             }
   3010             verb_list[index].device_count = 0;
   3011             parse_count += verb_list[index].mod_count;
   3012             verb_list[index].mod_ctrls = (card_mctrl_t *)
   3013                 malloc((verb_list[index].mod_count+1)*sizeof(card_mctrl_t));
   3014             if (verb_list[index].mod_ctrls == NULL) {
   3015                ret = -ENOMEM;
   3016                break;
   3017             }
   3018             verb_list[index].mod_count = 0;
   3019             continue;
   3020         } else {
   3021             verb_ptr =
   3022             (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3023             if (verb_ptr == NULL)
   3024                 return -ENOMEM;
   3025             strlcpy(verb_ptr, SND_UCM_END_OF_LIST,
   3026                 ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   3027             verb_list[index].device_list[device_count] = verb_ptr;
   3028             verb_ptr =
   3029             (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3030             if (verb_ptr == NULL)
   3031                 return -ENOMEM;
   3032             strlcpy(verb_ptr, SND_UCM_END_OF_LIST,
   3033                 ((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char)));
   3034             verb_list[index].modifier_list[modifier_count] = verb_ptr;
   3035             list = (verb_list[index].verb_ctrls +
   3036                        verb_list[index].verb_count);
   3037             list->case_name =
   3038                  (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3039             if(list->case_name == NULL) {
   3040                 free(verb_list[index].verb_ctrls);
   3041                 return -ENOMEM;
   3042             }
   3043             strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   3044                (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3045             list->ena_mixer_list = NULL;
   3046             list->dis_mixer_list = NULL;
   3047             list->ena_mixer_count = 0;
   3048             list->dis_mixer_count = 0;
   3049             list->playback_dev_name = NULL;
   3050             list->capture_dev_name = NULL;
   3051             list->acdb_id = 0;
   3052             list->capability = 0;
   3053             list = (verb_list[index].device_ctrls +
   3054                        verb_list[index].device_count);
   3055             list->case_name =
   3056                  (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3057             if(list->case_name == NULL) {
   3058                 free(verb_list[index].device_ctrls);
   3059                 return -ENOMEM;
   3060             }
   3061             strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   3062                (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3063             list->ena_mixer_list = NULL;
   3064             list->dis_mixer_list = NULL;
   3065             list->ena_mixer_count = 0;
   3066             list->dis_mixer_count = 0;
   3067             list->playback_dev_name = NULL;
   3068             list->capture_dev_name = NULL;
   3069             list->acdb_id = 0;
   3070             list->capability = 0;
   3071             list = (verb_list[index].mod_ctrls +
   3072                        verb_list[index].mod_count);
   3073             list->case_name =
   3074                  (char *)malloc((strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3075             if(list->case_name == NULL) {
   3076                 free(verb_list[index].mod_ctrls);
   3077                 return -ENOMEM;
   3078             }
   3079             strlcpy(list->case_name, SND_UCM_END_OF_LIST,
   3080                (strlen(SND_UCM_END_OF_LIST)+1)*sizeof(char));
   3081             list->ena_mixer_list = NULL;
   3082             list->dis_mixer_list = NULL;
   3083             list->ena_mixer_count = 0;
   3084             list->dis_mixer_count = 0;
   3085             list->playback_dev_name = NULL;
   3086             list->capture_dev_name = NULL;
   3087             list->acdb_id = 0;
   3088             list->capability = 0;
   3089             parse_count = 0;
   3090             break;
   3091         }
   3092     }
   3093     return ret;
   3094 }
   3095 
   3096 /* Print mixer controls in a specific list
   3097  * list - list to be printed
   3098  * verb_index - verb index
   3099  * count - number of elements in the list
   3100  * Returns 0 on sucess, negative error code otherwise
   3101  */
   3102 static int print_list(card_mctrl_t *list, int verb_index, int count)
   3103 {
   3104     int i, j;
   3105 
   3106     for(i=0; i < count; i++) {
   3107         ALOGD("\tcase name: %s\n", list[i].case_name);
   3108         ALOGD("\tEnable sequence: %d\n", list[i].ena_mixer_count);
   3109         for(j=0; j<list[i].ena_mixer_count; j++) {
   3110             ALOGD("\t\t%s : %d : %d: %s\n",
   3111                 list[i].ena_mixer_list[j].control_name,
   3112                 list[i].ena_mixer_list[j].type,
   3113                 list[i].ena_mixer_list[j].value,
   3114                 list[i].ena_mixer_list[j].string);
   3115         }
   3116         ALOGD("\tDisable sequence: %d\n", list[i].dis_mixer_count);
   3117         for(j=0; j<list[i].dis_mixer_count; j++) {
   3118             ALOGD("\t\t%s : %d : %d : %s\n",
   3119                 list[i].dis_mixer_list[j].control_name,
   3120                 list[i].dis_mixer_list[j].type,
   3121                 list[i].dis_mixer_list[j].value,
   3122                 list[i].dis_mixer_list[j].string);
   3123         }
   3124     }
   3125     return 0;
   3126 }
   3127 
   3128 /* Print mixer controls extracted from config files
   3129  * uc_mgr - use case manager structure
   3130  * Returns 0 on sucess, negative error code otherwise
   3131  */
   3132 static int snd_ucm_print(snd_use_case_mgr_t *uc_mgr)
   3133 {
   3134     card_mctrl_t *list;
   3135     int i, j, verb_index = 0;
   3136     use_case_verb_t *verb_list;
   3137 
   3138     pthread_mutex_lock(&uc_mgr->card_ctxt_ptr->card_lock);
   3139     verb_list = uc_mgr->card_ctxt_ptr->use_case_verb_list;
   3140     while(strncmp(uc_mgr->card_ctxt_ptr->verb_list[verb_index],
   3141          SND_UCM_END_OF_LIST, 3)) {
   3142         ALOGD("\nuse case verb: %s\n",
   3143             uc_mgr->card_ctxt_ptr->verb_list[verb_index]);
   3144         if(verb_list[verb_index].device_list) {
   3145             ALOGD("\tValid device list:");
   3146             i = 0;
   3147             while(strncmp(verb_list[verb_index].device_list[i],
   3148                   SND_UCM_END_OF_LIST, 3)) {
   3149                 ALOGD("\t\t%s", verb_list[verb_index].device_list[i]);
   3150                 i++;
   3151             }
   3152         }
   3153         if(verb_list[verb_index].modifier_list) {
   3154             ALOGD("\tValid modifier list:");
   3155             i = 0;
   3156             while(strncmp(verb_list[verb_index].modifier_list[i],
   3157                   SND_UCM_END_OF_LIST, 3)) {
   3158                 ALOGD("\t\t%s", verb_list[verb_index].modifier_list[i]);
   3159                 i++;
   3160             }
   3161         }
   3162         ALOGD("Verbs:\n");
   3163         list = verb_list[verb_index].verb_ctrls;
   3164         print_list(list, verb_index, verb_list[verb_index].verb_count);
   3165         ALOGD("Devices:\n");
   3166         list = verb_list[verb_index].device_ctrls;
   3167         print_list(list, verb_index, verb_list[verb_index].device_count);
   3168         ALOGD("Modifier:\n");
   3169         list = verb_list[verb_index].mod_ctrls;
   3170         print_list(list, verb_index, verb_list[verb_index].mod_count);
   3171         verb_index++;
   3172     }
   3173     pthread_mutex_unlock(&uc_mgr->card_ctxt_ptr->card_lock);
   3174     return 0;
   3175 }
   3176 
   3177 /* Gets the number of controls for specific sequence of a use cae */
   3178 static int get_controls_count(const char *nxt_str)
   3179 {
   3180     char *current_str, *next_str, *str_addr;
   3181     int count = 0;
   3182 
   3183     next_str = (char *)malloc((strlen(nxt_str)+1)*sizeof(char));
   3184     if (next_str == NULL) {
   3185         ALOGE("Failed to allocate memory");
   3186         return -ENOMEM;
   3187     }
   3188     strlcpy(next_str, nxt_str, ((strlen(nxt_str)+1)*sizeof(char)));
   3189     str_addr = next_str;
   3190     while(1) {
   3191         current_str = next_str;
   3192         next_str = strchr(current_str, '\n');
   3193         if ((!next_str) || (!strncasecmp(current_str, "EndSection", 10)))
   3194             break;
   3195         *next_str++ = '\0';
   3196         if (strcasestr(current_str, "EndSequence") != NULL) {
   3197             break;
   3198         } else {
   3199             count++;
   3200         }
   3201         if (*next_str == (char)EOF)
   3202             break;
   3203         if(!strncasecmp(current_str, "EndSection", 10))
   3204             break;
   3205     }
   3206     free(str_addr);
   3207     return count;
   3208 }
   3209 
   3210 /* Parse a section of config files
   3211  * uc_mgr - use case manager structure
   3212  * Returns 0 on sucess, negative error code otherwise
   3213  */
   3214 static int snd_ucm_parse_section(snd_use_case_mgr_t **uc_mgr, char **cur_str,
   3215 char **nxt_str, int verb_index, int ctrl_list_type)
   3216 {
   3217     use_case_verb_t *verb_list;
   3218     card_mctrl_t *list;
   3219     int enable_seq = 0, disable_seq = 0, controls_count = 0, ret = 0;
   3220     char *p, *current_str, *next_str, *name;
   3221 
   3222     verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   3223     if (ctrl_list_type == CTRL_LIST_VERB) {
   3224         list = (verb_list[verb_index].verb_ctrls +
   3225             verb_list[verb_index].verb_count);
   3226     } else if (ctrl_list_type == CTRL_LIST_DEVICE) {
   3227         list = (verb_list[verb_index].device_ctrls +
   3228             verb_list[verb_index].device_count);
   3229     } else if (ctrl_list_type == CTRL_LIST_MODIFIER) {
   3230         list = (verb_list[verb_index].mod_ctrls +
   3231             verb_list[verb_index].mod_count);
   3232     } else {
   3233         ALOGE("Invalid list type: %d\n", ctrl_list_type);
   3234         return -EINVAL;
   3235     }
   3236     list->case_name = NULL;
   3237     list->ena_mixer_list = NULL;
   3238     list->dis_mixer_list = NULL;
   3239     list->ena_mixer_count = 0;
   3240     list->dis_mixer_count = 0;
   3241     list->playback_dev_name = NULL;
   3242     list->capture_dev_name = NULL;
   3243     list->acdb_id = 0;
   3244     list->capability = 0;
   3245     list->effects_mixer_ctl = NULL;
   3246     current_str = *cur_str; next_str = *nxt_str;
   3247     while(strncasecmp(current_str, "EndSection", 10)) {
   3248         current_str = next_str;
   3249         next_str = strchr(current_str, '\n');
   3250         if ((!next_str) || (!strncasecmp(current_str, "EndSection", 10)))
   3251             break;
   3252         *next_str++ = '\0';
   3253         if (strcasestr(current_str, "EndSequence") != NULL) {
   3254             if (enable_seq == 1)
   3255                 enable_seq = 0;
   3256             else if (disable_seq == 1)
   3257                 disable_seq = 0;
   3258             else
   3259                 ALOGE("Error: improper config file\n");
   3260         }
   3261         if (enable_seq == 1) {
   3262             ret = snd_ucm_extract_controls(current_str, &list->ena_mixer_list,
   3263                   list->ena_mixer_count);
   3264             if (ret < 0)
   3265                 break;
   3266             list->ena_mixer_count++;
   3267         } else if (disable_seq == 1) {
   3268             ret = snd_ucm_extract_controls(current_str, &list->dis_mixer_list,
   3269                   list->dis_mixer_count);
   3270             if (ret < 0)
   3271                 break;
   3272             list->dis_mixer_count++;
   3273         } else if (strcasestr(current_str, "Name") != NULL) {
   3274             ret = snd_ucm_extract_name(current_str, &list->case_name);
   3275             if (ret < 0)
   3276                 break;
   3277             ALOGV("Name of section is %s\n", list->case_name);
   3278         } else if (strcasestr(current_str, "PlaybackPCM") != NULL) {
   3279             ret = snd_ucm_extract_dev_name(current_str,
   3280                       &list->playback_dev_name);
   3281             if (ret < 0)
   3282                 break;
   3283             ALOGV("Device name of playback is %s\n",
   3284                 list->playback_dev_name);
   3285         } else if (strcasestr(current_str, "CapturePCM") != NULL) {
   3286             ret = snd_ucm_extract_dev_name(current_str,
   3287                       &list->capture_dev_name);
   3288             if (ret < 0)
   3289                 break;
   3290             ALOGV("Device name of capture is %s\n", list->capture_dev_name);
   3291         } else if (strcasestr(current_str, "ACDBID") != NULL) {
   3292             ret = snd_ucm_extract_acdb(current_str, &list->acdb_id,
   3293                       &list->capability);
   3294             if (ret < 0)
   3295                 break;
   3296             ALOGV("ACDB ID: %d CAPABILITY: %d\n", list->acdb_id,
   3297                 list->capability);
   3298         } else if (strcasestr(current_str, "EffectsMixerCTL") != NULL) {
   3299             ret = snd_ucm_extract_effects_mixer_ctl(current_str,
   3300                       &list->effects_mixer_ctl);
   3301             if (ret < 0)
   3302                 break;
   3303             ALOGV("Effects mixer ctl: %s: %d\n", list->effects_mixer_ctl);
   3304         }
   3305         if (strcasestr(current_str, "EnableSequence") != NULL) {
   3306             controls_count = get_controls_count(next_str);
   3307             if (controls_count < 0) {
   3308                 ret = -ENOMEM;
   3309                 break;
   3310             }
   3311             list->ena_mixer_list =
   3312             (mixer_control_t *)malloc((controls_count*sizeof(mixer_control_t)));
   3313             if (list->ena_mixer_list == NULL) {
   3314                 ret = -ENOMEM;
   3315                 break;
   3316             }
   3317             enable_seq = 1;
   3318         } else if (strcasestr(current_str, "DisableSequence") != NULL) {
   3319             controls_count = get_controls_count(next_str);
   3320             if (controls_count < 0) {
   3321                 ret = -ENOMEM;
   3322                 break;
   3323             }
   3324             list->dis_mixer_list =
   3325             (mixer_control_t *)malloc((controls_count*sizeof(mixer_control_t)));
   3326             if (list->dis_mixer_list == NULL) {
   3327                 ret = -ENOMEM;
   3328                 break;
   3329             }
   3330             disable_seq = 1;
   3331         }
   3332         if (*next_str == (char)EOF)
   3333              break;
   3334     }
   3335     if(ret == 0) {
   3336         *cur_str = current_str; *nxt_str = next_str;
   3337         if (ctrl_list_type == CTRL_LIST_VERB) {
   3338             verb_list[verb_index].verb_count++;
   3339         } else if (ctrl_list_type == CTRL_LIST_DEVICE) {
   3340             verb_list[verb_index].device_count++;
   3341         } else if (ctrl_list_type == CTRL_LIST_MODIFIER) {
   3342             verb_list[verb_index].mod_count++;
   3343         }
   3344     }
   3345     return ret;
   3346 }
   3347 
   3348 /* Extract a mixer control name from config file
   3349  * Returns 0 on sucess, negative error code otherwise
   3350  */
   3351 static int snd_ucm_extract_name(char *buf, char **case_name)
   3352 {
   3353     int ret = 0;
   3354     char *p, *name = *case_name, *temp_ptr;
   3355 
   3356     p = strtok_r(buf, "\"", &temp_ptr);
   3357     while (p != NULL) {
   3358         p = strtok_r(NULL, "\"", &temp_ptr);
   3359         if (p == NULL)
   3360             break;
   3361         name = (char *)malloc((strlen(p)+1)*sizeof(char));
   3362         if(name == NULL) {
   3363             ret = -ENOMEM;
   3364             break;
   3365         }
   3366         strlcpy(name, p, (strlen(p)+1)*sizeof(char));
   3367         *case_name = name;
   3368         break;
   3369     }
   3370     return ret;
   3371 }
   3372 
   3373 /* Extract a ACDB ID and capability of use case from config file
   3374  * Returns 0 on sucess, negative error code otherwise
   3375  */
   3376 static int snd_ucm_extract_acdb(char *buf, int *id, int *cap)
   3377 {
   3378     char *p, key[] = "0123456789", *temp_ptr;
   3379 
   3380     p = strpbrk(buf, key);
   3381     if (p == NULL) {
   3382         *id = 0;
   3383         *cap = 0;
   3384     } else {
   3385         p = strtok_r(p, ":", &temp_ptr);
   3386         while (p != NULL) {
   3387             *id = atoi(p);
   3388             p = strtok_r(NULL, "\0", &temp_ptr);
   3389             if (p == NULL)
   3390                 break;
   3391             *cap = atoi(p);
   3392             break;
   3393         }
   3394     }
   3395     return 0;
   3396 }
   3397 
   3398 /* Extract Effects Mixer ID of device from config file
   3399  * Returns 0 on sucess, negative error code otherwise
   3400  */
   3401 static int snd_ucm_extract_effects_mixer_ctl(char *buf, char **mixer_name)
   3402 {
   3403     int ret = 0;
   3404     char *p, *name = *mixer_name, *temp_ptr;
   3405 
   3406     p = strtok_r(buf, "\"", &temp_ptr);
   3407     while (p != NULL) {
   3408         p = strtok_r(NULL, "\"", &temp_ptr);
   3409         if (p == NULL)
   3410             break;
   3411         name = (char *)malloc((strlen(p)+1)*sizeof(char));
   3412         if(name == NULL) {
   3413             ret = -ENOMEM;
   3414             break;
   3415         }
   3416         strlcpy(name, p, (strlen(p)+1)*sizeof(char));
   3417         *mixer_name = name;
   3418         break;
   3419     }
   3420     return ret;
   3421 }
   3422 
   3423 /* Extract a playback and capture device name of use case from config file
   3424  * Returns 0 on sucess, negative error code otherwise
   3425  */
   3426 static int snd_ucm_extract_dev_name(char *buf, char **dev_name)
   3427 {
   3428     char key[] = "0123456789";
   3429     char *p, *name = *dev_name;
   3430     char dev_pre[] = "hw:0,";
   3431     char *temp_ptr;
   3432 
   3433     p = strpbrk(buf, key);
   3434     if (p == NULL) {
   3435         *dev_name = NULL;
   3436     } else {
   3437         p = strtok_r(p, "\r\n", &temp_ptr);
   3438         if (p == NULL) {
   3439             *dev_name = NULL;
   3440         } else {
   3441             name = (char *)malloc((strlen(p)+strlen(dev_pre)+1)*sizeof(char));
   3442             if(name == NULL)
   3443                  return -ENOMEM;
   3444             strlcpy(name, dev_pre, (strlen(p)+strlen(dev_pre)+1)*sizeof(char));
   3445             strlcat(name, p, (strlen(p)+strlen(dev_pre)+1)*sizeof(char));
   3446             *dev_name = name;
   3447         }
   3448     }
   3449     return 0;
   3450 }
   3451 
   3452 static int get_num_values(const char *buf)
   3453 {
   3454     char *buf_addr, *p;
   3455     int count = 0;
   3456     char *temp_ptr;
   3457 
   3458     buf_addr = (char *)malloc((strlen(buf)+1)*sizeof(char));
   3459     if (buf_addr == NULL) {
   3460         ALOGE("Failed to allocate memory");
   3461         return -ENOMEM;
   3462     }
   3463     strlcpy(buf_addr, buf, ((strlen(buf)+1)*sizeof(char)));
   3464     p = strtok_r(buf_addr, " ", &temp_ptr);
   3465     while (p != NULL) {
   3466         count++;
   3467         p = strtok_r(NULL, " ", &temp_ptr);
   3468         if (p == NULL)
   3469             break;
   3470     }
   3471     free(buf_addr);
   3472     return count;
   3473 }
   3474 
   3475 /* Extract a mixer control from config file
   3476  * Returns 0 on sucess, negative error code otherwise
   3477  */
   3478 static int snd_ucm_extract_controls(char *buf, mixer_control_t **mixer_list,
   3479 int size)
   3480 {
   3481     unsigned long temp;
   3482     int ret = -EINVAL, i, index = 0, count = 0;
   3483     char *p, *ps, *pmv, temp_coeff[20];
   3484     mixer_control_t *list;
   3485     static const char *const seps = "\r\n";
   3486     char *temp_ptr, *temp_vol_ptr;
   3487 
   3488     p = strtok_r(buf, "'", &temp_ptr);
   3489     while (p != NULL) {
   3490         p = strtok_r(NULL, "'", &temp_ptr);
   3491         if (p == NULL)
   3492             break;
   3493         list = ((*mixer_list)+size);
   3494         list->control_name = (char *)malloc((strlen(p)+1)*sizeof(char));
   3495         if(list->control_name == NULL) {
   3496             ret = -ENOMEM;
   3497             free((*mixer_list));
   3498             break;
   3499         }
   3500         strlcpy(list->control_name, p, (strlen(p)+1)*sizeof(char));
   3501         p = strtok_r(NULL, ":", &temp_ptr);
   3502         if (p == NULL)
   3503             break;
   3504         if(!strncmp(p, "0", 1)) {
   3505             list->type = TYPE_STR;
   3506         } else if(!strncmp(p, "1", 1)) {
   3507             list->type = TYPE_INT;
   3508         } else if(!strncmp(p, "2", 1)) {
   3509             list->type = TYPE_MULTI_VAL;
   3510         } else {
   3511             ALOGE("Unknown type: p %s\n", p);
   3512         }
   3513         p = strtok_r(NULL, seps, &temp_ptr);
   3514         if (p == NULL)
   3515             break;
   3516         if(list->type == TYPE_INT) {
   3517             list->value = atoi(p);
   3518             list->string = NULL;
   3519             list->mulval = NULL;
   3520         } else if(list->type == TYPE_STR) {
   3521             list->value = -1;
   3522             list->string = (char *)malloc((strlen(p)+1)*sizeof(char));
   3523             list->mulval = NULL;
   3524             if(list->string == NULL) {
   3525                 ret = -ENOMEM;
   3526                 free((*mixer_list));
   3527                 free(list->control_name);
   3528                 break;
   3529             }
   3530             strlcpy(list->string, p, (strlen(p)+1)*sizeof(char));
   3531         } else if(list->type == TYPE_MULTI_VAL) {
   3532             if (p != NULL) {
   3533                 count = get_num_values(p);
   3534                 list->mulval = (char **)malloc(count*sizeof(char *));
   3535                 if (list->mulval == NULL) {
   3536                     ret = -ENOMEM;
   3537                     free((*mixer_list));
   3538                     free(list->control_name);
   3539                     break;
   3540                 }
   3541                 index = 0;
   3542                 /* To support volume values in percentage */
   3543                 if ((count == 1) && (strstr(p, "%") != NULL)) {
   3544                     pmv = strtok_r(p, " ", &temp_vol_ptr);
   3545                     while (pmv != NULL) {
   3546                         list->mulval[index] =
   3547                             (char *)malloc((strlen(pmv)+1)*sizeof(char));
   3548                         strlcpy(list->mulval[index], pmv, (strlen(pmv)+1));
   3549                         index++;
   3550                         pmv = strtok_r(NULL, " ", &temp_vol_ptr);
   3551                         if (pmv == NULL)
   3552                             break;
   3553                     }
   3554                 } else {
   3555                     pmv = strtok_r(p, " ", &temp_vol_ptr);
   3556                     while (pmv != NULL) {
   3557                         temp = strtoul(pmv, &ps, 16);
   3558                         snprintf(temp_coeff, sizeof(temp_coeff),"%lu", temp);
   3559                         list->mulval[index] =
   3560                             (char *)malloc((strlen(temp_coeff)+1)*sizeof(char));
   3561                         strlcpy(list->mulval[index], temp_coeff,
   3562                             (strlen(temp_coeff)+1));
   3563                         index++;
   3564                         pmv = strtok_r(NULL, " ", &temp_vol_ptr);
   3565                         if (pmv == NULL)
   3566                             break;
   3567                     }
   3568                 }
   3569                 list->value = count;
   3570                 list->string = NULL;
   3571             }
   3572         } else {
   3573             ALOGE("Unknown type: p %s\n", p);
   3574             list->value = -1;
   3575             list->string = NULL;
   3576         }
   3577         ret = 0;
   3578         break;
   3579     }
   3580     return ret;
   3581 }
   3582 
   3583 void free_list(card_mctrl_t *list, int verb_index, int count)
   3584 {
   3585     int case_index = 0, index = 0, mindex = 0;
   3586 
   3587     for(case_index = 0; case_index < count; case_index++) {
   3588         for(index = 0; index < list[case_index].ena_mixer_count; index++) {
   3589             if(list[case_index].ena_mixer_list[index].control_name) {
   3590                 free(list[case_index].ena_mixer_list[index].control_name);
   3591             }
   3592             if(list[case_index].ena_mixer_list[index].string) {
   3593                 free(list[case_index].ena_mixer_list[index].string);
   3594             }
   3595             if(list[case_index].ena_mixer_list[index].mulval) {
   3596                 for(mindex = 0;
   3597                     mindex < list[case_index].ena_mixer_list[index].value;
   3598                     mindex++) {
   3599                     free(list[case_index].ena_mixer_list[index].mulval[mindex]);
   3600                 }
   3601                 if(list[case_index].ena_mixer_list[index].mulval) {
   3602                     free(list[case_index].ena_mixer_list[index].mulval);
   3603                 }
   3604             }
   3605         }
   3606         for(index = 0; index < list[case_index].dis_mixer_count; index++) {
   3607             if(list[case_index].dis_mixer_list[index].control_name) {
   3608                 free(list[case_index].dis_mixer_list[index].control_name);
   3609             }
   3610             if(list[case_index].dis_mixer_list[index].string) {
   3611                 free(list[case_index].dis_mixer_list[index].string);
   3612             }
   3613             if(list[case_index].dis_mixer_list[index].mulval) {
   3614                 for(mindex = 0;
   3615                     mindex < list[case_index].dis_mixer_list[index].value;
   3616                     mindex++) {
   3617                     free(list[case_index].dis_mixer_list[index].mulval[mindex]);
   3618                 }
   3619                 if(list[case_index].dis_mixer_list[index].mulval) {
   3620                     free(list[case_index].dis_mixer_list[index].mulval);
   3621                 }
   3622             }
   3623         }
   3624         if(list[case_index].case_name) {
   3625             free(list[case_index].case_name);
   3626         }
   3627         if(list[case_index].ena_mixer_list) {
   3628             free(list[case_index].ena_mixer_list);
   3629         }
   3630         if(list[case_index].dis_mixer_list) {
   3631             free(list[case_index].dis_mixer_list);
   3632         }
   3633         if(list[case_index].playback_dev_name) {
   3634             free(list[case_index].playback_dev_name);
   3635         }
   3636         if(list[case_index].capture_dev_name) {
   3637             free(list[case_index].capture_dev_name);
   3638         }
   3639         if(list[case_index].effects_mixer_ctl) {
   3640             list[case_index].effects_mixer_ctl = NULL;
   3641         }
   3642     }
   3643 }
   3644 
   3645 void snd_ucm_free_mixer_list(snd_use_case_mgr_t **uc_mgr)
   3646 {
   3647     card_mctrl_t *ctrl_list;
   3648     use_case_verb_t *verb_list;
   3649     int index = 0, verb_index = 0;
   3650 
   3651     pthread_mutex_lock(&(*uc_mgr)->card_ctxt_ptr->card_lock);
   3652     verb_list = (*uc_mgr)->card_ctxt_ptr->use_case_verb_list;
   3653     while(strncmp((*uc_mgr)->card_ctxt_ptr->verb_list[verb_index],
   3654           SND_UCM_END_OF_LIST, 3)) {
   3655         ctrl_list = verb_list[verb_index].verb_ctrls;
   3656         free_list(ctrl_list, verb_index, verb_list[verb_index].verb_count);
   3657         if(verb_list[verb_index].use_case_name)
   3658             free(verb_list[verb_index].use_case_name);
   3659         if((*uc_mgr)->card_ctxt_ptr->verb_list[verb_index]) {
   3660             free((*uc_mgr)->card_ctxt_ptr->verb_list[verb_index]);
   3661         }
   3662         verb_index++;
   3663     }
   3664     verb_index -= 1;
   3665     ctrl_list = verb_list[verb_index].device_ctrls;
   3666     free_list(ctrl_list, verb_index, verb_list[verb_index].device_count);
   3667     ctrl_list = verb_list[verb_index].mod_ctrls;
   3668     free_list(ctrl_list, verb_index, verb_list[verb_index].mod_count);
   3669     index = 0;
   3670     while(1) {
   3671         if (verb_list[verb_index].device_list[index]) {
   3672             if (!strncmp(verb_list[verb_index].device_list[index],
   3673                 SND_UCM_END_OF_LIST, 3)) {
   3674                 free(verb_list[verb_index].device_list[index]);
   3675                 break;
   3676             } else {
   3677                 free(verb_list[verb_index].device_list[index]);
   3678                 index++;
   3679             }
   3680         }
   3681     }
   3682     if (verb_list[verb_index].device_list)
   3683         free(verb_list[verb_index].device_list);
   3684     index = 0;
   3685     while(1) {
   3686         if (verb_list[verb_index].modifier_list[index]) {
   3687             if (!strncmp(verb_list[verb_index].modifier_list[index],
   3688                 SND_UCM_END_OF_LIST, 3)) {
   3689                 free(verb_list[verb_index].modifier_list[index]);
   3690                 break;
   3691             } else {
   3692                 free(verb_list[verb_index].modifier_list[index]);
   3693                 index++;
   3694             }
   3695         }
   3696     }
   3697     if (verb_list[verb_index].modifier_list)
   3698         free(verb_list[verb_index].modifier_list);
   3699     if((*uc_mgr)->card_ctxt_ptr->use_case_verb_list)
   3700         free((*uc_mgr)->card_ctxt_ptr->use_case_verb_list);
   3701     if((*uc_mgr)->card_ctxt_ptr->verb_list)
   3702         free((*uc_mgr)->card_ctxt_ptr->verb_list);
   3703     pthread_mutex_unlock(&(*uc_mgr)->card_ctxt_ptr->card_lock);
   3704 }
   3705 
   3706 /* Add an identifier to the respective list
   3707  * head - list head
   3708  * value - node value that needs to be added
   3709  * Returns 0 on sucess, negative error code otherwise
   3710  */
   3711 static int snd_ucm_add_ident_to_list(struct snd_ucm_ident_node **head,
   3712 const char *value)
   3713 {
   3714     struct snd_ucm_ident_node *temp, *node;
   3715 
   3716     node =
   3717         (struct snd_ucm_ident_node *)malloc(sizeof(struct snd_ucm_ident_node));
   3718     if (node == NULL) {
   3719         ALOGE("Failed to allocate memory for new node");
   3720         return -ENOMEM;
   3721     } else {
   3722         node->next = NULL;
   3723         strlcpy(node->ident, value, MAX_STR_LEN);
   3724         node->active = 0;
   3725         node->capability = 0;
   3726     }
   3727     if (*head == NULL) {
   3728         *head = node;
   3729     } else {
   3730         temp = *head;
   3731         while (temp->next != NULL) {
   3732             temp = temp->next;
   3733         }
   3734         temp->next = node;
   3735     }
   3736     ALOGV("add_to_list: head %p, value %s", *head, node->ident);
   3737     return 0;
   3738 }
   3739 
   3740 /* Get the status of identifier at particulare index of the list
   3741  * head - list head
   3742  * ident - identifier value for which status needs to be get
   3743  * status - status to be set (1 - active, 0 - inactive)
   3744  */
   3745 static int snd_ucm_get_status_at_index(struct snd_ucm_ident_node *head,
   3746 const char *ident)
   3747 {
   3748     while (head != NULL) {
   3749         if(!strncmp(ident, head->ident, (strlen(head->ident)+1))) {
   3750             break;
   3751         }
   3752         head = head->next;
   3753     }
   3754     if (head == NULL) {
   3755         ALOGV("Element not found in the list");
   3756     } else {
   3757         return(head->active);
   3758     }
   3759     return -EINVAL;
   3760 }
   3761 
   3762 /* Get the node at particular index
   3763  * head - list head
   3764  * index - index value
   3765  */
   3766 struct snd_ucm_ident_node *snd_ucm_get_device_node(struct snd_ucm_ident_node *head,
   3767 int index)
   3768 {
   3769     if (head == NULL) {
   3770         ALOGV("Empty list");
   3771         return NULL;
   3772     }
   3773 
   3774     if ((index < 0) || (index >= (snd_ucm_get_size_of_list(head)))) {
   3775         ALOGE("Element with given index %d doesn't exist in the list", index);
   3776         return NULL;
   3777     }
   3778 
   3779     while (index) {
   3780         head = head->next;
   3781         index--;
   3782     }
   3783 
   3784     return head;
   3785 }
   3786 
   3787 /* Set the status of identifier at particulare index of the list
   3788  * head - list head
   3789  * ident - identifier value for which status needs to be set
   3790  * status - status to be set (1 - active, 0 - inactive)
   3791  */
   3792 static void snd_ucm_set_status_at_index(struct snd_ucm_ident_node *head,
   3793 const char *ident, int status, int capability)
   3794 {
   3795     while (head != NULL) {
   3796         if(!strncmp(ident, head->ident, (strlen(head->ident)+1))) {
   3797             break;
   3798         }
   3799         head = head->next;
   3800     }
   3801     if (head == NULL) {
   3802         ALOGE("Element not found to set the status");
   3803     } else {
   3804         head->active = status;
   3805         head->capability = capability;
   3806     }
   3807 }
   3808 
   3809 /* Get the identifier value at particulare index of the list
   3810  * head - list head
   3811  * index - node index value
   3812  * Returns node idetifier value at index on sucess, NULL otherwise
   3813  */
   3814 static char *snd_ucm_get_value_at_index(struct snd_ucm_ident_node *head,
   3815 int index)
   3816 {
   3817     if (head == NULL) {
   3818         ALOGV("Empty list");
   3819         return NULL;
   3820     }
   3821 
   3822     if ((index < 0) || (index >= (snd_ucm_get_size_of_list(head)))) {
   3823         ALOGE("Element with given index %d doesn't exist in the list", index);
   3824         return NULL;
   3825     }
   3826 
   3827     while (index) {
   3828         head = head->next;
   3829         index--;
   3830     }
   3831 
   3832     return (strdup(head->ident));
   3833 }
   3834 
   3835 /* Get the size of the list
   3836  * head - list head
   3837  * Returns size of list on sucess, negative error code otherwise
   3838  */
   3839 static int snd_ucm_get_size_of_list(struct snd_ucm_ident_node *head)
   3840 {
   3841     int index = 0;
   3842 
   3843     if (head == NULL) {
   3844         ALOGV("Empty list");
   3845         return 0;
   3846     }
   3847 
   3848     while (head->next != NULL) {
   3849         index++;
   3850         head = head->next;
   3851     }
   3852 
   3853     return (index+1);
   3854 }
   3855 
   3856 static void snd_ucm_print_list(struct snd_ucm_ident_node *head)
   3857 {
   3858     int index = 0;
   3859 
   3860     ALOGV("print_list: head %p", head);
   3861     if (head == NULL) {
   3862         ALOGV("Empty list");
   3863         return;
   3864     }
   3865 
   3866     while (head->next != NULL) {
   3867         ALOGV("index: %d, value: %s", index, head->ident);
   3868         index++;
   3869         head = head->next;
   3870     }
   3871     ALOGV("index: %d, value: %s", index, head->ident);
   3872 }
   3873 
   3874 /* Delete an identifier from respective list
   3875  * head - list head
   3876  * value - node value that needs to be deleted
   3877  * Returns 0 on sucess, negative error code otherwise
   3878  *
   3879  */
   3880 static int snd_ucm_del_ident_from_list(struct snd_ucm_ident_node **head,
   3881 const char *value)
   3882 {
   3883     struct snd_ucm_ident_node *temp1, *temp2;
   3884     int ret = -EINVAL;
   3885 
   3886     if (*head == NULL) {
   3887         ALOGE("del_from_list: Empty list");
   3888         return -EINVAL;
   3889     } else if (!strncmp((*head)->ident, value, (strlen(value)+1))) {
   3890             temp2 = *head;
   3891             *head = temp2->next;
   3892             ret = 0;
   3893     } else {
   3894         temp1 = *head;
   3895         temp2 = temp1->next;
   3896         while (temp2 != NULL) {
   3897             if (!strncmp(temp2->ident, value, (strlen(value)+1))) {
   3898                 temp1->next = temp2->next;
   3899                 ret = 0;
   3900                 break;
   3901             }
   3902             temp1 = temp1->next;
   3903             temp2 = temp1->next;
   3904         }
   3905     }
   3906     if (ret < 0) {
   3907         ALOGE("Element not found in enabled list");
   3908     } else {
   3909         temp2->next = NULL;
   3910         temp2->ident[0] = 0;
   3911         temp2->active = 0;
   3912         temp2->capability = 0;
   3913         free(temp2);
   3914         temp2 = NULL;
   3915     }
   3916     return ret;
   3917 }
   3918