1 /* 2 * This library is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU Lesser General Public 4 * License as published by the Free Software Foundation; either 5 * version 2 of the License, or (at your option) any later version. 6 * 7 * This library is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 * Lesser General Public License for more details. 11 * 12 * You should have received a copy of the GNU Lesser General Public 13 * License along with this library; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 15 * 16 * Support for the verb/device/modifier core logic and API, 17 * command line tool and file parser was kindly sponsored by 18 * Texas Instruments Inc. 19 * Support for multiple active modifiers and devices, 20 * transition sequences, multiple client access and user defined use 21 * cases was kindly sponsored by Wolfson Microelectronics PLC. 22 * 23 * Copyright (C) 2008-2010 SlimLogic Ltd 24 * Copyright (C) 2010 Wolfson Microelectronics PLC 25 * Copyright (C) 2010 Texas Instruments Inc. 26 * Copyright (C) 2010 Red Hat Inc. 27 * Authors: Liam Girdwood <lrg@slimlogic.co.uk> 28 * Stefan Schmidt <stefan@slimlogic.co.uk> 29 * Justin Xu <justinx@slimlogic.co.uk> 30 * Jaroslav Kysela <perex@perex.cz> 31 */ 32 33 34 35 #if 0 36 #define UC_MGR_DEBUG 37 #endif 38 39 #include "local.h" 40 #include <pthread.h> 41 #include "use-case.h" 42 43 #define SYNTAX_VERSION_MAX 2 44 45 #define MAX_CARD_SHORT_NAME 32 46 #define MAX_CARD_LONG_NAME 80 47 48 #define SEQUENCE_ELEMENT_TYPE_CDEV 1 49 #define SEQUENCE_ELEMENT_TYPE_CSET 2 50 #define SEQUENCE_ELEMENT_TYPE_SLEEP 3 51 #define SEQUENCE_ELEMENT_TYPE_EXEC 4 52 #define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE 5 53 #define SEQUENCE_ELEMENT_TYPE_CSET_TLV 6 54 #define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ 7 55 56 struct ucm_value { 57 struct list_head list; 58 char *name; 59 char *data; 60 }; 61 62 /* sequence of a component device */ 63 struct component_sequence { 64 struct use_case_device *device; /* component device */ 65 int enable; /* flag to choose enable or disable list of the device */ 66 }; 67 68 struct sequence_element { 69 struct list_head list; 70 unsigned int type; 71 union { 72 long sleep; /* Sleep time in microseconds if sleep element, else 0 */ 73 char *cdev; 74 char *cset; 75 char *exec; 76 struct component_sequence cmpt_seq; /* component sequence */ 77 } data; 78 }; 79 80 /* 81 * Transition sequences. i.e. transition between one verb, device, mod to another 82 */ 83 struct transition_sequence { 84 struct list_head list; 85 char *name; 86 struct list_head transition_list; 87 }; 88 89 /* 90 * Modifier Supported Devices. 91 */ 92 enum dev_list_type { 93 DEVLIST_NONE, 94 DEVLIST_SUPPORTED, 95 DEVLIST_CONFLICTING 96 }; 97 98 struct dev_list_node { 99 struct list_head list; 100 char *name; 101 }; 102 103 struct dev_list { 104 enum dev_list_type type; 105 struct list_head list; 106 }; 107 108 struct ctl_dev { 109 struct list_head list; 110 char *device; 111 }; 112 113 struct ctl_list { 114 struct list_head list; 115 struct list_head dev_list; 116 snd_ctl_t *ctl; 117 snd_ctl_card_info_t *ctl_info; 118 }; 119 120 struct ucm_dev_name { 121 struct list_head list; 122 char *name1; 123 char *name2; 124 }; 125 126 /* 127 * Describes a Use Case Modifier and it's enable and disable sequences. 128 * A use case verb can have N modifiers. 129 */ 130 struct use_case_modifier { 131 struct list_head list; 132 struct list_head active_list; 133 134 char *name; 135 char *comment; 136 137 /* modifier enable and disable sequences */ 138 struct list_head enable_list; 139 struct list_head disable_list; 140 141 /* modifier transition list */ 142 struct list_head transition_list; 143 144 /* list of devices supported or conflicting */ 145 struct dev_list dev_list; 146 147 /* values */ 148 struct list_head value_list; 149 }; 150 151 /* 152 * Describes a Use Case Device and it's enable and disable sequences. 153 * A use case verb can have N devices. 154 */ 155 struct use_case_device { 156 struct list_head list; 157 struct list_head active_list; 158 159 char *name; 160 char *comment; 161 162 /* device enable and disable sequences */ 163 struct list_head enable_list; 164 struct list_head disable_list; 165 166 /* device transition list */ 167 struct list_head transition_list; 168 169 /* list of devices supported or conflicting */ 170 struct dev_list dev_list; 171 172 /* value list */ 173 struct list_head value_list; 174 }; 175 176 /* 177 * Describes a Use Case Verb and it's enable and disable sequences. 178 * A use case verb can have N devices and N modifiers. 179 */ 180 struct use_case_verb { 181 struct list_head list; 182 183 unsigned int active: 1; 184 185 char *name; 186 char *comment; 187 188 /* verb enable and disable sequences */ 189 struct list_head enable_list; 190 struct list_head disable_list; 191 192 /* verb transition list */ 193 struct list_head transition_list; 194 195 struct list_head device_list; 196 197 /* component device list */ 198 struct list_head cmpt_device_list; 199 200 /* modifiers that can be used with this use case */ 201 struct list_head modifier_list; 202 203 /* value list */ 204 struct list_head value_list; 205 206 /* temporary modifications lists */ 207 struct list_head rename_list; 208 struct list_head remove_list; 209 }; 210 211 /* 212 * Manages a sound card and all its use cases. 213 */ 214 struct snd_use_case_mgr { 215 char *card_name; 216 char *conf_file_name; 217 char *conf_dir_name; 218 char *comment; 219 int conf_format; 220 221 /* use case verb, devices and modifier configs parsed from files */ 222 struct list_head verb_list; 223 224 /* default settings - sequence */ 225 struct list_head default_list; 226 227 /* default settings - value list */ 228 struct list_head value_list; 229 230 /* current status */ 231 struct use_case_verb *active_verb; 232 struct list_head active_devices; 233 struct list_head active_modifiers; 234 235 /* locking */ 236 pthread_mutex_t mutex; 237 238 /* list of opened control devices */ 239 struct list_head ctl_list; 240 241 /* Components don't define cdev, the card device. When executing 242 * a sequence of a component device, ucm manager enters component 243 * domain and needs to provide cdev to the component. This cdev 244 * should be defined by the machine, parent of the component. 245 */ 246 int in_component_domain; 247 char *cdev; 248 }; 249 250 #define uc_error SNDERR 251 252 #ifdef UC_MGR_DEBUG 253 #define uc_dbg SNDERR 254 #else 255 #define uc_dbg(fmt, arg...) do { } while (0) 256 #endif 257 258 void uc_mgr_error(const char *fmt, ...); 259 void uc_mgr_stdout(const char *fmt, ...); 260 261 int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg); 262 int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr); 263 int uc_mgr_scan_master_configs(const char **_list[]); 264 265 int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name); 266 int uc_mgr_remove_device(struct use_case_verb *verb, const char *name); 267 int uc_mgr_rename_device(struct use_case_verb *verb, const char *src, 268 const char *dst); 269 270 void uc_mgr_free_dev_name_list(struct list_head *base); 271 void uc_mgr_free_sequence_element(struct sequence_element *seq); 272 void uc_mgr_free_transition_element(struct transition_sequence *seq); 273 void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr); 274 void uc_mgr_free(snd_use_case_mgr_t *uc_mgr); 275 276 int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr, 277 snd_ctl_t **ctl, 278 const char *device); 279 280 struct ctl_list *uc_mgr_get_one_ctl(snd_use_case_mgr_t *uc_mgr); 281 snd_ctl_t *uc_mgr_get_ctl(snd_use_case_mgr_t *uc_mgr); 282 void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr); 283 284 int uc_mgr_add_value(struct list_head *base, const char *key, char *val); 285 286 int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr, 287 char **_rvalue, 288 const char *value); 289 290 int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr, 291 snd_config_t *parent, 292 snd_config_t *cond); 293 294 /** The name of the environment variable containing the UCM directory */ 295 #define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM" 296 297 /** The name of the environment variable containing the UCM directory (new syntax) */ 298 #define ALSA_CONFIG_UCM2_VAR "ALSA_CONFIG_UCM2" 299