Blame src/ucm/utils.c

Packit Service db8eaa
/*
Packit Service db8eaa
 *  This library is free software; you can redistribute it and/or
Packit Service db8eaa
 *  modify it under the terms of the GNU Lesser General Public
Packit Service db8eaa
 *  License as published by the Free Software Foundation; either
Packit Service db8eaa
 *  version 2 of the License, or (at your option) any later version.
Packit Service db8eaa
 *
Packit Service db8eaa
 *  This library is distributed in the hope that it will be useful,
Packit Service db8eaa
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service db8eaa
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service db8eaa
 *  Lesser General Public License for more details.
Packit Service db8eaa
 *
Packit Service db8eaa
 *  You should have received a copy of the GNU Lesser General Public
Packit Service db8eaa
 *  License along with this library; if not, write to the Free Software  
Packit Service db8eaa
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service db8eaa
 *
Packit Service db8eaa
 *  Support for the verb/device/modifier core logic and API,
Packit Service db8eaa
 *  command line tool and file parser was kindly sponsored by
Packit Service db8eaa
 *  Texas Instruments Inc.
Packit Service db8eaa
 *  Support for multiple active modifiers and devices,
Packit Service db8eaa
 *  transition sequences, multiple client access and user defined use
Packit Service db8eaa
 *  cases was kindly sponsored by Wolfson Microelectronics PLC.
Packit Service db8eaa
 *
Packit Service db8eaa
 *  Copyright (C) 2008-2010 SlimLogic Ltd
Packit Service db8eaa
 *  Copyright (C) 2010 Wolfson Microelectronics PLC
Packit Service db8eaa
 *  Copyright (C) 2010 Texas Instruments Inc.
Packit Service db8eaa
 *  Copyright (C) 2010 Red Hat Inc.
Packit Service db8eaa
 *  Authors: Liam Girdwood <lrg@slimlogic.co.uk>
Packit Service db8eaa
 *	         Stefan Schmidt <stefan@slimlogic.co.uk>
Packit Service db8eaa
 *	         Justin Xu <justinx@slimlogic.co.uk>
Packit Service db8eaa
 *               Jaroslav Kysela <perex@perex.cz>
Packit Service db8eaa
 */
Packit Service db8eaa
Packit Service db8eaa
#include "ucm_local.h"
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_error(const char *fmt,...)
Packit Service db8eaa
{
Packit Service db8eaa
	va_list va;
Packit Service db8eaa
	va_start(va, fmt);
Packit Service db8eaa
	fprintf(stderr, "ucm: ");
Packit Service db8eaa
	vfprintf(stderr, fmt, va);
Packit Service db8eaa
	va_end(va);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_stdout(const char *fmt,...)
Packit Service db8eaa
{
Packit Service db8eaa
	va_list va;
Packit Service db8eaa
	va_start(va, fmt);
Packit Service db8eaa
	vfprintf(stdout, fmt, va);
Packit Service db8eaa
	va_end(va);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
struct ctl_list *uc_mgr_get_master_ctl(snd_use_case_mgr_t *uc_mgr)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct ctl_list *ctl_list = NULL, *ctl_list2;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &uc_mgr->ctl_list) {
Packit Service db8eaa
		ctl_list2 = list_entry(pos, struct ctl_list, list);
Packit Service db8eaa
		if (ctl_list2->slave)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (ctl_list) {
Packit Service db8eaa
			uc_error("multiple control device names were found!");
Packit Service db8eaa
			return NULL;
Packit Service db8eaa
		}
Packit Service db8eaa
		ctl_list = ctl_list2;
Packit Service db8eaa
	}
Packit Service db8eaa
	return ctl_list;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
struct ctl_list *uc_mgr_get_ctl_by_name(snd_use_case_mgr_t *uc_mgr, const char *name, int idx)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct ctl_list *ctl_list = NULL;
Packit Service db8eaa
	const char *s;
Packit Service db8eaa
	char cname[32];
Packit Service db8eaa
	int idx2, card, err;
Packit Service db8eaa
Packit Service db8eaa
	idx2 = idx;
Packit Service db8eaa
	list_for_each(pos, &uc_mgr->ctl_list) {
Packit Service db8eaa
		ctl_list = list_entry(pos, struct ctl_list, list);
Packit Service db8eaa
		s = snd_ctl_card_info_get_name(ctl_list->ctl_info);
Packit Service db8eaa
		if (s == NULL)
Packit Service db8eaa
			continue;
Packit Service db8eaa
		if (strcmp(s, name) == 0) {
Packit Service db8eaa
			if (idx2 == 0)
Packit Service db8eaa
				return ctl_list;
Packit Service db8eaa
			idx2--;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	idx2 = idx;
Packit Service db8eaa
	card = -1;
Packit Service db8eaa
	if (snd_card_next(&card) < 0 || card < 0)
Packit Service db8eaa
		return NULL;
Packit Service db8eaa
Packit Service db8eaa
	while (card >= 0) {
Packit Service db8eaa
		sprintf(cname, "hw:%d", card);
Packit Service db8eaa
		err = uc_mgr_open_ctl(uc_mgr, &ctl_list, cname, 1);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			continue;	/* really? */
Packit Service db8eaa
		s = snd_ctl_card_info_get_name(ctl_list->ctl_info);
Packit Service db8eaa
		if (s && strcmp(s, name) == 0) {
Packit Service db8eaa
			if (idx2 == 0)
Packit Service db8eaa
				return ctl_list;
Packit Service db8eaa
			idx2--;
Packit Service db8eaa
		}
Packit Service db8eaa
		if (snd_card_next(&card) < 0)
Packit Service db8eaa
			break;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	return NULL;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
snd_ctl_t *uc_mgr_get_ctl(snd_use_case_mgr_t *uc_mgr)
Packit Service db8eaa
{
Packit Service db8eaa
	struct ctl_list *ctl_list;
Packit Service db8eaa
Packit Service db8eaa
	ctl_list = uc_mgr_get_master_ctl(uc_mgr);
Packit Service db8eaa
	if (ctl_list)
Packit Service db8eaa
		return ctl_list->ctl;
Packit Service db8eaa
	return NULL;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static void uc_mgr_free_ctl(struct ctl_list *ctl_list)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct ctl_dev *ctl_dev;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each_safe(pos, npos, &ctl_list->dev_list) {
Packit Service db8eaa
		ctl_dev = list_entry(pos, struct ctl_dev, list);
Packit Service db8eaa
		free(ctl_dev->device);
Packit Service db8eaa
		free(ctl_dev);
Packit Service db8eaa
	}
Packit Service db8eaa
	snd_ctl_card_info_free(ctl_list->ctl_info);
Packit Service db8eaa
	free(ctl_list);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_ctl_list(snd_use_case_mgr_t *uc_mgr)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct ctl_list *ctl_list;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each_safe(pos, npos, &uc_mgr->ctl_list) {
Packit Service db8eaa
		ctl_list = list_entry(pos, struct ctl_list, list);
Packit Service db8eaa
		snd_ctl_close(ctl_list->ctl);
Packit Service db8eaa
		list_del(&ctl_list->list);
Packit Service db8eaa
		uc_mgr_free_ctl(ctl_list);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int uc_mgr_ctl_add_dev(struct ctl_list *ctl_list, const char *device)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct ctl_dev *ctl_dev;
Packit Service db8eaa
Packit Service db8eaa
	/* skip duplicates */
Packit Service db8eaa
	list_for_each(pos, &ctl_list->dev_list) {
Packit Service db8eaa
		ctl_dev = list_entry(pos, struct ctl_dev, list);
Packit Service db8eaa
		if (strcmp(ctl_dev->device, device) == 0)
Packit Service db8eaa
			return 0;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	/* allocate new device name */
Packit Service db8eaa
	ctl_dev = malloc(sizeof(*ctl_dev));
Packit Service db8eaa
	if (ctl_dev == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	ctl_dev->device = strdup(device);
Packit Service db8eaa
	if (ctl_dev->device == NULL) {
Packit Service db8eaa
		free(ctl_dev);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
	list_add_tail(&ctl_dev->list, &ctl_list->dev_list);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
static int uc_mgr_ctl_add(snd_use_case_mgr_t *uc_mgr,
Packit Service db8eaa
			  struct ctl_list **ctl_list,
Packit Service db8eaa
			  snd_ctl_t *ctl, int card,
Packit Service db8eaa
			  snd_ctl_card_info_t *info,
Packit Service db8eaa
			  const char *device,
Packit Service db8eaa
			  int slave)
Packit Service db8eaa
{
Packit Service db8eaa
	struct ctl_list *cl = NULL;
Packit Service db8eaa
	const char *id = snd_ctl_card_info_get_id(info);
Packit Service db8eaa
	char dev[MAX_CARD_LONG_NAME];
Packit Service db8eaa
	int err, hit = 0;
Packit Service db8eaa
Packit Service db8eaa
	if (id == NULL || id[0] == '\0')
Packit Service db8eaa
		return -ENOENT;
Packit Service db8eaa
	if (!(*ctl_list)) {
Packit Service db8eaa
		cl = malloc(sizeof(*cl));
Packit Service db8eaa
		if (cl == NULL)
Packit Service db8eaa
			return -ENOMEM;
Packit Service db8eaa
		INIT_LIST_HEAD(&cl->dev_list);
Packit Service db8eaa
		cl->ctl = ctl;
Packit Service db8eaa
		if (snd_ctl_card_info_malloc(&cl->ctl_info) < 0) {
Packit Service db8eaa
			free(cl);
Packit Service db8eaa
			return -ENOMEM;
Packit Service db8eaa
		}
Packit Service db8eaa
		snd_ctl_card_info_copy(cl->ctl_info, info);
Packit Service db8eaa
		cl->slave = slave;
Packit Service db8eaa
		*ctl_list = cl;
Packit Service db8eaa
	} else {
Packit Service db8eaa
		if (!slave)
Packit Service db8eaa
			(*ctl_list)->slave = slave;
Packit Service db8eaa
	}
Packit Service db8eaa
	if (card >= 0) {
Packit Service db8eaa
		snprintf(dev, sizeof(dev), "hw:%d", card);
Packit Service db8eaa
		hit |= !!(device && (strcmp(dev, device) == 0));
Packit Service db8eaa
		err = uc_mgr_ctl_add_dev(*ctl_list, dev);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			goto __nomem;
Packit Service db8eaa
	}
Packit Service db8eaa
	snprintf(dev, sizeof(dev), "hw:%s", id);
Packit Service db8eaa
	hit |= !!(device && (strcmp(dev, device) == 0));
Packit Service db8eaa
	err = uc_mgr_ctl_add_dev(*ctl_list, dev);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto __nomem;
Packit Service db8eaa
	/* the UCM name not based on the card name / id */
Packit Service db8eaa
	if (!hit && device) {
Packit Service db8eaa
		err = uc_mgr_ctl_add_dev(*ctl_list, device);
Packit Service db8eaa
		if (err < 0)
Packit Service db8eaa
			goto __nomem;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	list_add_tail(&(*ctl_list)->list, &uc_mgr->ctl_list);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
Packit Service db8eaa
__nomem:
Packit Service db8eaa
	if (*ctl_list == cl) {
Packit Service db8eaa
		uc_mgr_free_ctl(cl);
Packit Service db8eaa
		*ctl_list = NULL;
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENOMEM;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_open_ctl(snd_use_case_mgr_t *uc_mgr,
Packit Service db8eaa
		    struct ctl_list **ctll,
Packit Service db8eaa
		    const char *device,
Packit Service db8eaa
		    int slave)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos1, *pos2;
Packit Service db8eaa
	snd_ctl_t *ctl;
Packit Service db8eaa
	struct ctl_list *ctl_list;
Packit Service db8eaa
	struct ctl_dev *ctl_dev;
Packit Service db8eaa
	snd_ctl_card_info_t *info;
Packit Service db8eaa
	const char *id;
Packit Service db8eaa
	int err, card;
Packit Service db8eaa
Packit Service db8eaa
	snd_ctl_card_info_alloca(&info;;
Packit Service db8eaa
Packit Service db8eaa
	/* cache lookup */
Packit Service db8eaa
	list_for_each(pos1, &uc_mgr->ctl_list) {
Packit Service db8eaa
		ctl_list = list_entry(pos1, struct ctl_list, list);
Packit Service db8eaa
		list_for_each(pos2, &ctl_list->dev_list) {
Packit Service db8eaa
			ctl_dev = list_entry(pos2, struct ctl_dev, list);
Packit Service db8eaa
			if (strcmp(ctl_dev->device, device) == 0) {
Packit Service db8eaa
				*ctll = ctl_list;
Packit Service db8eaa
				if (!slave)
Packit Service db8eaa
					ctl_list->slave = 0;
Packit Service db8eaa
				return 0;
Packit Service db8eaa
			}
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	err = snd_ctl_open(&ctl, device, 0);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		return err;
Packit Service db8eaa
Packit Service db8eaa
	id = NULL;
Packit Service db8eaa
	err = snd_ctl_card_info(ctl, info);
Packit Service db8eaa
	if (err == 0)
Packit Service db8eaa
		id = snd_ctl_card_info_get_id(info);
Packit Service db8eaa
	if (err < 0 || id == NULL || id[0] == '\0') {
Packit Service db8eaa
		uc_error("control hardware info (%s): %s", device, snd_strerror(err));
Packit Service db8eaa
		snd_ctl_close(ctl);
Packit Service db8eaa
		return err >= 0 ? -EINVAL : err;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	/* insert to cache, if just name differs */
Packit Service db8eaa
	list_for_each(pos1, &uc_mgr->ctl_list) {
Packit Service db8eaa
		ctl_list = list_entry(pos1, struct ctl_list, list);
Packit Service db8eaa
		if (strcmp(id, snd_ctl_card_info_get_id(ctl_list->ctl_info)) == 0) {
Packit Service db8eaa
			card = snd_card_get_index(id);
Packit Service db8eaa
			err = uc_mgr_ctl_add(uc_mgr, &ctl_list, ctl, card, info, device, slave);
Packit Service db8eaa
			if (err < 0)
Packit Service db8eaa
				goto __nomem;
Packit Service db8eaa
			snd_ctl_close(ctl);
Packit Service db8eaa
			*ctll = ctl_list;
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	ctl_list = NULL;
Packit Service db8eaa
	err = uc_mgr_ctl_add(uc_mgr, &ctl_list, ctl, -1, info, device, slave);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto __nomem;
Packit Service db8eaa
Packit Service db8eaa
	*ctll = ctl_list;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
Packit Service db8eaa
__nomem:
Packit Service db8eaa
	snd_ctl_close(ctl);
Packit Service db8eaa
	return -ENOMEM;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
const char *uc_mgr_config_dir(int format)
Packit Service db8eaa
{
Packit Service db8eaa
	const char *path;
Packit Service db8eaa
Packit Service db8eaa
	if (format >= 2) {
Packit Service db8eaa
		path = getenv(ALSA_CONFIG_UCM2_VAR);
Packit Service db8eaa
		if (!path || path[0] == '\0')
Packit Service db8eaa
			path = ALSA_CONFIG_DIR "/ucm2";
Packit Service db8eaa
	} else {
Packit Service db8eaa
		path = getenv(ALSA_CONFIG_UCM_VAR);
Packit Service db8eaa
		if (!path || path[0] == '\0')
Packit Service db8eaa
			path = ALSA_CONFIG_DIR "/ucm";
Packit Service db8eaa
	}
Packit Service db8eaa
	return path;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg)
Packit Service db8eaa
{
Packit Service db8eaa
	FILE *fp;
Packit Service db8eaa
	snd_input_t *in;
Packit Service db8eaa
	snd_config_t *top;
Packit Service db8eaa
	const char *default_paths[2];
Packit Service db8eaa
	int err;
Packit Service db8eaa
Packit Service db8eaa
	fp = fopen(file, "r");
Packit Service db8eaa
	if (!fp) {
Packit Service db8eaa
		err = -errno;
Packit Service db8eaa
  __err0:
Packit Service db8eaa
		uc_error("could not open configuration file %s", file);
Packit Service db8eaa
		return err;
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_input_stdio_attach(&in, fp, 1);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto __err0;
Packit Service db8eaa
	err = snd_config_top(&top);
Packit Service db8eaa
	if (err < 0)
Packit Service db8eaa
		goto __err1;
Packit Service db8eaa
Packit Service db8eaa
	default_paths[0] = uc_mgr_config_dir(format);
Packit Service db8eaa
	default_paths[1] = NULL;
Packit Service db8eaa
	err = _snd_config_load_with_include(top, in, 0, default_paths);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		uc_error("could not load configuration file %s", file);
Packit Service db8eaa
		goto __err2;
Packit Service db8eaa
	}
Packit Service db8eaa
	err = snd_input_close(in);
Packit Service db8eaa
	if (err < 0) {
Packit Service db8eaa
		in = NULL;
Packit Service db8eaa
		goto __err2;
Packit Service db8eaa
	}
Packit Service db8eaa
	*cfg = top;
Packit Service db8eaa
	return 0;
Packit Service db8eaa
Packit Service db8eaa
 __err2:
Packit Service db8eaa
	snd_config_delete(top);
Packit Service db8eaa
 __err1:
Packit Service db8eaa
	if (in)
Packit Service db8eaa
		snd_input_close(in);
Packit Service db8eaa
	return err;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_value(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct ucm_value *val;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		val = list_entry(pos, struct ucm_value, list);
Packit Service db8eaa
		free(val->name);
Packit Service db8eaa
		free(val->data);
Packit Service db8eaa
		list_del(&val->list);
Packit Service db8eaa
		free(val);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_dev_list(struct dev_list *dev_list)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct dev_list_node *dlist;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, &dev_list->list) {
Packit Service db8eaa
		dlist = list_entry(pos, struct dev_list_node, list);
Packit Service db8eaa
		free(dlist->name);
Packit Service db8eaa
		list_del(&dlist->list);
Packit Service db8eaa
		free(dlist);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_put_to_dev_list(struct dev_list *dev_list, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct dev_list_node *dlist;
Packit Service db8eaa
	char *n;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &dev_list->list) {
Packit Service db8eaa
		dlist = list_entry(pos, struct dev_list_node, list);
Packit Service db8eaa
		if (strcmp(dlist->name, name) == 0)
Packit Service db8eaa
			return 0;
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	dlist = calloc(1, sizeof(*dlist));
Packit Service db8eaa
	if (dlist == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	n = strdup(name);
Packit Service db8eaa
	if (n == NULL) {
Packit Service db8eaa
		free(dlist);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
	dlist->name = n;
Packit Service db8eaa
	list_add(&dlist->list, &dev_list->list);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_rename_in_dev_list(struct dev_list *dev_list, const char *src,
Packit Service db8eaa
			      const char *dst)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct dev_list_node *dlist;
Packit Service db8eaa
	char *dst1;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &dev_list->list) {
Packit Service db8eaa
		dlist = list_entry(pos, struct dev_list_node, list);
Packit Service db8eaa
		if (strcmp(dlist->name, src) == 0) {
Packit Service db8eaa
			dst1 = strdup(dst);
Packit Service db8eaa
			if (dst1 == NULL)
Packit Service db8eaa
				return -ENOMEM;
Packit Service db8eaa
			free(dlist->name);
Packit Service db8eaa
			dlist->name = dst1;
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENODEV;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_remove_from_dev_list(struct dev_list *dev_list, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct dev_list_node *dlist;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &dev_list->list) {
Packit Service db8eaa
		dlist = list_entry(pos, struct dev_list_node, list);
Packit Service db8eaa
		if (strcmp(dlist->name, name) == 0) {
Packit Service db8eaa
			free(dlist->name);
Packit Service db8eaa
			list_del(&dlist->list);
Packit Service db8eaa
			free(dlist);
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
	return -ENODEV;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_sequence_element(struct sequence_element *seq)
Packit Service db8eaa
{
Packit Service db8eaa
	if (seq == NULL)
Packit Service db8eaa
		return;
Packit Service db8eaa
	switch (seq->type) {
Packit Service db8eaa
	case SEQUENCE_ELEMENT_TYPE_CDEV:
Packit Service db8eaa
		free(seq->data.cdev);
Packit Service db8eaa
		break;
Packit Service db8eaa
	case SEQUENCE_ELEMENT_TYPE_CSET:
Packit Service db8eaa
	case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE:
Packit Service db8eaa
	case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
Packit Service db8eaa
		free(seq->data.cset);
Packit Service db8eaa
		break;
Packit Service db8eaa
	case SEQUENCE_ELEMENT_TYPE_EXEC:
Packit Service db8eaa
		free(seq->data.exec);
Packit Service db8eaa
		break;
Packit Service db8eaa
	default:
Packit Service db8eaa
		break;
Packit Service db8eaa
	}
Packit Service db8eaa
	free(seq);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_sequence(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct sequence_element *seq;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		seq = list_entry(pos, struct sequence_element, list);
Packit Service db8eaa
		list_del(&seq->list);
Packit Service db8eaa
		uc_mgr_free_sequence_element(seq);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_transition_element(struct transition_sequence *tseq)
Packit Service db8eaa
{
Packit Service db8eaa
	free(tseq->name);
Packit Service db8eaa
	uc_mgr_free_sequence(&tseq->transition_list);
Packit Service db8eaa
	free(tseq);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_transition(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct transition_sequence *tseq;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		tseq = list_entry(pos, struct transition_sequence, list);
Packit Service db8eaa
		list_del(&tseq->list);
Packit Service db8eaa
		uc_mgr_free_transition_element(tseq);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_dev_name_list(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct ucm_dev_name *dev;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		dev = list_entry(pos, struct ucm_dev_name, list);
Packit Service db8eaa
		list_del(&dev->list);
Packit Service db8eaa
		free(dev->name1);
Packit Service db8eaa
		free(dev->name2);
Packit Service db8eaa
		free(dev);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_modifier(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct use_case_modifier *mod;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		mod = list_entry(pos, struct use_case_modifier, list);
Packit Service db8eaa
		free(mod->name);
Packit Service db8eaa
		free(mod->comment);
Packit Service db8eaa
		uc_mgr_free_sequence(&mod->enable_list);
Packit Service db8eaa
		uc_mgr_free_sequence(&mod->disable_list);
Packit Service db8eaa
		uc_mgr_free_transition(&mod->transition_list);
Packit Service db8eaa
		uc_mgr_free_dev_list(&mod->dev_list);
Packit Service db8eaa
		uc_mgr_free_value(&mod->value_list);
Packit Service db8eaa
		list_del(&mod->list);
Packit Service db8eaa
		free(mod);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_device(struct use_case_device *dev)
Packit Service db8eaa
{
Packit Service db8eaa
	free(dev->name);
Packit Service db8eaa
	free(dev->comment);
Packit Service db8eaa
	uc_mgr_free_sequence(&dev->enable_list);
Packit Service db8eaa
	uc_mgr_free_sequence(&dev->disable_list);
Packit Service db8eaa
	uc_mgr_free_transition(&dev->transition_list);
Packit Service db8eaa
	uc_mgr_free_dev_list(&dev->dev_list);
Packit Service db8eaa
	uc_mgr_free_value(&dev->value_list);
Packit Service db8eaa
	list_del(&dev->list);
Packit Service db8eaa
	free(dev);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_device_list(struct list_head *base)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct use_case_device *dev;
Packit Service db8eaa
	
Packit Service db8eaa
	list_for_each_safe(pos, npos, base) {
Packit Service db8eaa
		dev = list_entry(pos, struct use_case_device, list);
Packit Service db8eaa
		uc_mgr_free_device(dev);
Packit Service db8eaa
	}
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_rename_device(struct use_case_verb *verb, const char *src,
Packit Service db8eaa
			 const char *dst)
Packit Service db8eaa
{
Packit Service db8eaa
	struct use_case_device *device;
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	char *dst1;
Packit Service db8eaa
Packit Service db8eaa
	/* no errors when device is not found */
Packit Service db8eaa
	list_for_each_safe(pos, npos, &verb->device_list) {
Packit Service db8eaa
		device = list_entry(pos, struct use_case_device, list);
Packit Service db8eaa
		if (strcmp(device->name, src) == 0) {
Packit Service db8eaa
			dst1 = strdup(dst);
Packit Service db8eaa
			if (dst1 == NULL)
Packit Service db8eaa
				return -ENOMEM;
Packit Service db8eaa
			free(device->name);
Packit Service db8eaa
			device->name = dst1;
Packit Service db8eaa
			continue;
Packit Service db8eaa
		}
Packit Service db8eaa
		uc_mgr_rename_in_dev_list(&device->dev_list, src, dst);
Packit Service db8eaa
	}
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_remove_device(struct use_case_verb *verb, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	struct use_case_device *device;
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	int err, found = 0;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each_safe(pos, npos, &verb->device_list) {
Packit Service db8eaa
		device = list_entry(pos, struct use_case_device, list);
Packit Service db8eaa
		if (strcmp(device->name, name) == 0) {
Packit Service db8eaa
			uc_mgr_free_device(device);
Packit Service db8eaa
			found++;
Packit Service db8eaa
			continue;
Packit Service db8eaa
		}
Packit Service db8eaa
		err = uc_mgr_remove_from_dev_list(&device->dev_list, name);
Packit Service db8eaa
		if (err < 0 && err != -ENODEV)
Packit Service db8eaa
			return err;
Packit Service db8eaa
		if (err == 0)
Packit Service db8eaa
			found++;
Packit Service db8eaa
	}
Packit Service db8eaa
	return found == 0 ? -ENODEV : 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
const char *uc_mgr_get_variable(snd_use_case_mgr_t *uc_mgr, const char *name)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct ucm_value *value;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &uc_mgr->variable_list) {
Packit Service db8eaa
		value = list_entry(pos, struct ucm_value, list);
Packit Service db8eaa
		if (strcmp(value->name, name) == 0)
Packit Service db8eaa
			return value->data;
Packit Service db8eaa
	}
Packit Service db8eaa
	return NULL;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
int uc_mgr_set_variable(snd_use_case_mgr_t *uc_mgr, const char *name,
Packit Service db8eaa
			const char *val)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos;
Packit Service db8eaa
	struct ucm_value *curr;
Packit Service db8eaa
	char *val2;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each(pos, &uc_mgr->variable_list) {
Packit Service db8eaa
		curr = list_entry(pos, struct ucm_value, list);
Packit Service db8eaa
		if (strcmp(curr->name, name) == 0) {
Packit Service db8eaa
			val2 = strdup(val);
Packit Service db8eaa
			if (val2 == NULL)
Packit Service db8eaa
				return -ENOMEM;
Packit Service db8eaa
			free(curr->data);
Packit Service db8eaa
			curr->data = val2;
Packit Service db8eaa
			return 0;
Packit Service db8eaa
		}
Packit Service db8eaa
	}
Packit Service db8eaa
Packit Service db8eaa
	curr = calloc(1, sizeof(struct ucm_value));
Packit Service db8eaa
	if (curr == NULL)
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	curr->name = strdup(name);
Packit Service db8eaa
	if (curr->name == NULL) {
Packit Service db8eaa
		free(curr);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
	curr->data = strdup(val);
Packit Service db8eaa
	if (curr->data == NULL) {
Packit Service db8eaa
		free(curr->name);
Packit Service db8eaa
		free(curr);
Packit Service db8eaa
		return -ENOMEM;
Packit Service db8eaa
	}
Packit Service db8eaa
	list_add_tail(&curr->list, &uc_mgr->variable_list);
Packit Service db8eaa
	return 0;
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
Packit Service db8eaa
{
Packit Service db8eaa
	struct list_head *pos, *npos;
Packit Service db8eaa
	struct use_case_verb *verb;
Packit Service db8eaa
Packit Service db8eaa
	list_for_each_safe(pos, npos, &uc_mgr->verb_list) {
Packit Service db8eaa
		verb = list_entry(pos, struct use_case_verb, list);
Packit Service db8eaa
		free(verb->name);
Packit Service db8eaa
		free(verb->comment);
Packit Service db8eaa
		uc_mgr_free_sequence(&verb->enable_list);
Packit Service db8eaa
		uc_mgr_free_sequence(&verb->disable_list);
Packit Service db8eaa
		uc_mgr_free_transition(&verb->transition_list);
Packit Service db8eaa
		uc_mgr_free_value(&verb->value_list);
Packit Service db8eaa
		uc_mgr_free_device_list(&verb->device_list);
Packit Service db8eaa
		uc_mgr_free_device_list(&verb->cmpt_device_list);
Packit Service db8eaa
		uc_mgr_free_modifier(&verb->modifier_list);
Packit Service db8eaa
		uc_mgr_free_dev_name_list(&verb->rename_list);
Packit Service db8eaa
		uc_mgr_free_dev_name_list(&verb->remove_list);
Packit Service db8eaa
		list_del(&verb->list);
Packit Service db8eaa
		free(verb);
Packit Service db8eaa
	}
Packit Service db8eaa
	uc_mgr_free_sequence(&uc_mgr->boot_list);
Packit Service db8eaa
	uc_mgr_free_sequence(&uc_mgr->default_list);
Packit Service db8eaa
	uc_mgr_free_value(&uc_mgr->value_list);
Packit Service db8eaa
	uc_mgr_free_value(&uc_mgr->variable_list);
Packit Service db8eaa
	free(uc_mgr->comment);
Packit Service db8eaa
	free(uc_mgr->conf_dir_name);
Packit Service db8eaa
	free(uc_mgr->conf_file_name);
Packit Service db8eaa
	uc_mgr->comment = NULL;
Packit Service db8eaa
	uc_mgr->conf_dir_name = NULL;
Packit Service db8eaa
	uc_mgr->conf_file_name = NULL;
Packit Service db8eaa
	uc_mgr->active_verb = NULL;
Packit Service db8eaa
	INIT_LIST_HEAD(&uc_mgr->active_devices);
Packit Service db8eaa
	INIT_LIST_HEAD(&uc_mgr->active_modifiers);
Packit Service db8eaa
}
Packit Service db8eaa
Packit Service db8eaa
void uc_mgr_free(snd_use_case_mgr_t *uc_mgr)
Packit Service db8eaa
{
Packit Service db8eaa
	uc_mgr_free_verb(uc_mgr);
Packit Service db8eaa
	uc_mgr_free_ctl_list(uc_mgr);
Packit Service db8eaa
	free(uc_mgr->card_name);
Packit Service db8eaa
	free(uc_mgr);
Packit Service db8eaa
}