blob: c1655c70504f0fb9c99b1324b8e0a071c9375f0e [file] [log] [blame]
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Support for the verb/device/modifier core logic and API,
* command line tool and file parser was kindly sponsored by
* Texas Instruments Inc.
* Support for multiple active modifiers and devices,
* transition sequences, multiple client access and user defined use
* cases was kindly sponsored by Wolfson Microelectronics PLC.
*
* Copyright (C) 2008-2010 SlimLogic Ltd
* Copyright (C) 2010 Wolfson Microelectronics PLC
* Copyright (C) 2010 Texas Instruments Inc.
* Copyright (C) 2010 Red Hat Inc.
* Authors: Liam Girdwood <lrg@slimlogic.co.uk>
* Stefan Schmidt <stefan@slimlogic.co.uk>
* Justin Xu <justinx@slimlogic.co.uk>
* Jaroslav Kysela <perex@perex.cz>
*/
#if 0
#define UC_MGR_DEBUG
#endif
#include <pthread.h>
#include "local.h"
#include "use-case.h"
#define MAX_FILE 256
#define ALSA_USE_CASE_DIR ALSA_CONFIG_DIR "/ucm"
#define SEQUENCE_ELEMENT_TYPE_CDEV 1
#define SEQUENCE_ELEMENT_TYPE_CSET 2
#define SEQUENCE_ELEMENT_TYPE_SLEEP 3
#define SEQUENCE_ELEMENT_TYPE_EXEC 4
#define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE 5
struct ucm_value {
struct list_head list;
char *name;
char *data;
};
struct sequence_element {
struct list_head list;
unsigned int type;
union {
long sleep; /* Sleep time in microseconds if sleep element, else 0 */
char *cdev;
char *cset;
char *exec;
} data;
};
/*
* Transition sequences. i.e. transition between one verb, device, mod to another
*/
struct transition_sequence {
struct list_head list;
char *name;
struct list_head transition_list;
};
/*
* Modifier Supported Devices.
*/
enum dev_list_type {
DEVLIST_NONE,
DEVLIST_SUPPORTED,
DEVLIST_CONFLICTING
};
struct dev_list_node {
struct list_head list;
char *name;
};
struct dev_list {
enum dev_list_type type;
struct list_head list;
};
/*
* Describes a Use Case Modifier and it's enable and disable sequences.
* A use case verb can have N modifiers.
*/
struct use_case_modifier {
struct list_head list;
struct list_head active_list;
char *name;
char *comment;
/* modifier enable and disable sequences */
struct list_head enable_list;
struct list_head disable_list;
/* modifier transition list */
struct list_head transition_list;
/* list of devices supported or conflicting */
struct dev_list dev_list;
/* values */
struct list_head value_list;
};
/*
* Describes a Use Case Device and it's enable and disable sequences.
* A use case verb can have N devices.
*/
struct use_case_device {
struct list_head list;
struct list_head active_list;
char *name;
char *comment;
/* device enable and disable sequences */
struct list_head enable_list;
struct list_head disable_list;
/* device transition list */
struct list_head transition_list;
/* list of devices supported or conflicting */
struct dev_list dev_list;
/* value list */
struct list_head value_list;
};
/*
* Describes a Use Case Verb and it's enable and disable sequences.
* A use case verb can have N devices and N modifiers.
*/
struct use_case_verb {
struct list_head list;
unsigned int active: 1;
char *name;
char *comment;
/* verb enable and disable sequences */
struct list_head enable_list;
struct list_head disable_list;
/* verb transition list */
struct list_head transition_list;
/* hardware devices that can be used with this use case */
struct list_head device_list;
/* modifiers that can be used with this use case */
struct list_head modifier_list;
/* value list */
struct list_head value_list;
};
/*
* Manages a sound card and all its use cases.
*/
struct snd_use_case_mgr {
char *card_name;
char *comment;
/* use case verb, devices and modifier configs parsed from files */
struct list_head verb_list;
/* default settings - sequence */
struct list_head default_list;
/* default settings - value list */
struct list_head value_list;
/* current status */
struct use_case_verb *active_verb;
struct list_head active_devices;
struct list_head active_modifiers;
/* locking */
pthread_mutex_t mutex;
/* change to list of ctl handles */
snd_ctl_t *ctl;
char *ctl_dev;
};
#define uc_error SNDERR
#ifdef UC_MGR_DEBUG
#define uc_dbg SNDERR
#else
#define uc_dbg(fmt, arg...) do { } while (0)
#endif
void uc_mgr_error(const char *fmt, ...);
void uc_mgr_stdout(const char *fmt, ...);
int uc_mgr_config_load(const char *file, snd_config_t **cfg);
int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr);
int uc_mgr_scan_master_configs(const char **_list[]);
void uc_mgr_free_sequence_element(struct sequence_element *seq);
void uc_mgr_free_transition_element(struct transition_sequence *seq);
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);