⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 state.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 3 页
字号:
		return err;	}	err = snd_ctl_card_info(handle, info);	if (err < 0) {		error("snd_ctl_card_info error: %s", snd_strerror(err));		goto _close;	}	id = snd_ctl_card_info_get_id(info);	err = snd_config_search(top, "state", &state);	if (err == 0 &&	    snd_config_get_type(state) != SND_CONFIG_TYPE_COMPOUND) {		error("config state node is not a compound");		err = -EINVAL;		goto _close;	}	if (err < 0) {		err = snd_config_compound_add(top, "state", 1, &state);		if (err < 0) {			error("snd_config_compound_add: %s", snd_strerror(err));			goto _close;		}	}	err = snd_config_search(state, id, &card);	if (err == 0 &&	    snd_config_get_type(card) != SND_CONFIG_TYPE_COMPOUND) {		error("config state.%s node is not a compound", id);		err = -EINVAL;		goto _close;	}	if (err < 0) {		err = snd_config_compound_add(state, id, 0, &card);		if (err < 0) {			error("snd_config_compound_add: %s", snd_strerror(err));			goto _close;		}	}	err = snd_config_search(card, "control", &control);	if (err == 0) {		err = snd_config_delete(control);		if (err < 0) {			error("snd_config_delete: %s", snd_strerror(err));			goto _close;		}	}	err = snd_ctl_elem_list(handle, list);	if (err < 0) {		error("Cannot determine controls: %s", snd_strerror(err));		goto _close;	}	count = snd_ctl_elem_list_get_count(list);	err = snd_config_compound_add(card, "control", count > 0, &control);	if (err < 0) {		error("snd_config_compound_add: %s", snd_strerror(err));		goto _close;	}	if (count == 0) {		err = 0;		goto _close;	}	snd_ctl_elem_list_set_offset(list, 0);	if (snd_ctl_elem_list_alloc_space(list, count) < 0) {		error("No enough memory...");		goto _close;	}	if ((err = snd_ctl_elem_list(handle, list)) < 0) {		error("Cannot determine controls (2): %s", snd_strerror(err));		goto _free;	}	for (idx = 0; idx < count; ++idx) {		snd_ctl_elem_id_t *id;		snd_ctl_elem_id_alloca(&id);		snd_ctl_elem_list_get_id(list, idx, id);		err = get_control(handle, id, control);		if (err < 0)			goto _free;	}					err = 0; _free:	snd_ctl_elem_list_free_space(list); _close:	snd_ctl_close(handle);	return err;}static long config_iface(snd_config_t *n){	long i;	long long li;	snd_ctl_elem_iface_t idx; 	const char *str;	switch (snd_config_get_type(n)) {	case SND_CONFIG_TYPE_INTEGER:		snd_config_get_integer(n, &i);		return i;	case SND_CONFIG_TYPE_INTEGER64:		snd_config_get_integer64(n, &li);		return li;	case SND_CONFIG_TYPE_STRING:		snd_config_get_string(n, &str);		break;	default:		return -1;	}	for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) {		if (strcasecmp(snd_ctl_elem_iface_name(idx), str) == 0)			return idx;	}	return -1;}static int config_bool(snd_config_t *n, int doit){	const char *str;	long val;	long long lval;	switch (snd_config_get_type(n)) {	case SND_CONFIG_TYPE_INTEGER:		snd_config_get_integer(n, &val);		if (val < 0 || val > 1)			return -1;		return val;	case SND_CONFIG_TYPE_INTEGER64:		snd_config_get_integer64(n, &lval);		if (lval < 0 || lval > 1)			return -1;		return (int) lval;	case SND_CONFIG_TYPE_STRING:		snd_config_get_string(n, &str);		break;	case SND_CONFIG_TYPE_COMPOUND:		if (!force_restore || !doit)			return -1;		n = snd_config_iterator_entry(snd_config_iterator_first(n));		return config_bool(n, doit);	default:		return -1;	}	if (strcmp(str, "on") == 0 || strcmp(str, "true") == 0)		return 1;	if (strcmp(str, "off") == 0 || strcmp(str, "false") == 0)		return 0;	return -1;}static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,			     snd_ctl_elem_info_t *info, int doit){	const char *str;	long val;	long long lval;	unsigned int idx, items;	switch (snd_config_get_type(n)) {	case SND_CONFIG_TYPE_INTEGER:		snd_config_get_integer(n, &val);		return val;	case SND_CONFIG_TYPE_INTEGER64:		snd_config_get_integer64(n, &lval);		return (int) lval;	case SND_CONFIG_TYPE_STRING:		snd_config_get_string(n, &str);		break;	case SND_CONFIG_TYPE_COMPOUND:		if (!force_restore || !doit)			return -1;		n = snd_config_iterator_entry(snd_config_iterator_first(n));		return config_enumerated(n, handle, info, doit);	default:		return -1;	}	items = snd_ctl_elem_info_get_items(info);	for (idx = 0; idx < items; idx++) {		int err;		snd_ctl_elem_info_set_item(info, idx);		err = snd_ctl_elem_info(handle, info);		if (err < 0) {			error("snd_ctl_elem_info: %s", snd_strerror(err));			return err;		}		if (strcmp(str, snd_ctl_elem_info_get_item_name(info)) == 0)			return idx;	}	return -1;}static int config_integer(snd_config_t *n, long *val, int doit){	int err = snd_config_get_integer(n, val);	if (err < 0 && force_restore && doit) {		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)			return err;		n = snd_config_iterator_entry(snd_config_iterator_first(n));		return config_integer(n, val, doit);	}	return err;}static int config_integer64(snd_config_t *n, long long *val, int doit){	int err = snd_config_get_integer64(n, val);	if (err < 0 && force_restore && doit) {		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)			return err;		n = snd_config_iterator_entry(snd_config_iterator_first(n));		return config_integer64(n, val, doit);	}	return err;}static int is_user_control(snd_config_t *conf){	snd_config_iterator_t i, next;	snd_config_for_each(i, next, conf) {		snd_config_t *n = snd_config_iterator_entry(i);		const char *id, *s;		if (snd_config_get_id(n, &id) < 0)			continue;		if (strcmp(id, "access") == 0) {			if (snd_config_get_string(n, &s) < 0)				return 0;			if (strstr(s, "user"))				return 1;		}	}	return 0;}/* * get the item type from the given comment config */static int get_comment_type(snd_config_t *n){	static const snd_ctl_elem_type_t types[] = {		SND_CTL_ELEM_TYPE_BOOLEAN,		SND_CTL_ELEM_TYPE_INTEGER,		SND_CTL_ELEM_TYPE_ENUMERATED,		SND_CTL_ELEM_TYPE_BYTES,		SND_CTL_ELEM_TYPE_IEC958,		SND_CTL_ELEM_TYPE_INTEGER64,	};	const char *type;	unsigned int i;	if (snd_config_get_string(n, &type) < 0)		return -EINVAL;	for (i = 0; i < ARRAY_SIZE(types); ++i)		if (strcmp(type, snd_ctl_elem_type_name(types[i])) == 0)			return types[i];	return -EINVAL;}/* * get the value range from the given comment config */static int get_comment_range(snd_config_t *n, int ctype,			     long *imin, long *imax, long *istep){	const char *s;	int err;	if (snd_config_get_string(n, &s) < 0)		return -EINVAL;	switch (ctype) {	case SND_CTL_ELEM_TYPE_INTEGER:		err = sscanf(s, "%li - %li (step %li)", imin, imax, istep);		if (err != 3) {			istep = 0;			err = sscanf(s, "%li - %li", imin, imax);			if (err != 2)				return -EINVAL;		}		break;	default:		return -EINVAL;	}	return 0;}static int add_user_control(snd_ctl_t *handle, snd_ctl_elem_info_t *info, snd_config_t *conf){	snd_ctl_elem_id_t *id;	snd_config_iterator_t i, next;	long imin, imax, istep;	snd_ctl_elem_type_t ctype;	unsigned int count;	int err;	unsigned int *tlv;	imin = imax = istep = 0;	count = 0;	ctype = SND_CTL_ELEM_TYPE_NONE;	tlv = NULL;	snd_config_for_each(i, next, conf) {		snd_config_t *n = snd_config_iterator_entry(i);		const char *id;		if (snd_config_get_id(n, &id) < 0)			continue;		if (strcmp(id, "type") == 0) {			err = get_comment_type(n);			if (err < 0)				return err;			ctype = err;			continue;		}		if (strcmp(id, "range") == 0) {			err = get_comment_range(n, ctype, &imin, &imax, &istep);			if (err < 0)				return err;			continue;		}		if (strcmp(id, "count") == 0) {			long v;			if ((err = snd_config_get_integer(n, &v)) < 0)				return err;			count = v;			continue;		}		if (strcmp(id, "tlv") == 0) {			const char *s;			if ((err = snd_config_get_string(n, &s)) < 0)				return -EINVAL;			if (tlv)				free(tlv);			if ((tlv = str_to_tlv(s)) == NULL)				return -EINVAL;			continue;		}	}	snd_ctl_elem_id_alloca(&id);	snd_ctl_elem_info_get_id(info, id);	if (count <= 0)		count = 1;	switch (ctype) {	case SND_CTL_ELEM_TYPE_INTEGER:		if (imin > imax || istep > imax - imin)			return -EINVAL;		err = snd_ctl_elem_add_integer(handle, id, count, imin, imax, istep);		if (err < 0)			goto error;		if (tlv)			snd_ctl_elem_tlv_write(handle, id, tlv);		break;	case SND_CTL_ELEM_TYPE_BOOLEAN:		err = snd_ctl_elem_add_boolean(handle, id, count);		break;	case SND_CTL_ELEM_TYPE_IEC958:		err = snd_ctl_elem_add_iec958(handle, id);		break;	default:		err = -EINVAL;		break;	} error:	free(tlv);	if (err < 0)		return err;	return snd_ctl_elem_info(handle, info);}/* * look for a config node with the given item name */static snd_config_t *search_comment_item(snd_config_t *conf, const char *name){	snd_config_iterator_t i, next;	snd_config_for_each(i, next, conf) {		snd_config_t *n = snd_config_iterator_entry(i);		const char *id;		if (snd_config_get_id(n, &id) < 0)			continue;		if (strcmp(id, name) == 0)			return n;	}	return NULL;}/* * check whether the config item has the same of compatible type */static int check_comment_type(snd_config_t *conf, int type){	snd_config_t *n = search_comment_item(conf, "type");	int ctype;	if (!n)		return 0; /* not defined */	ctype = get_comment_type(n);	if (ctype == type)		return 0;	if ((ctype == SND_CTL_ELEM_TYPE_BOOLEAN ||	     ctype == SND_CTL_ELEM_TYPE_INTEGER ||	     ctype == SND_CTL_ELEM_TYPE_INTEGER64 ||	     ctype == SND_CTL_ELEM_TYPE_ENUMERATED) &&	    (type == SND_CTL_ELEM_TYPE_BOOLEAN ||	     type == SND_CTL_ELEM_TYPE_INTEGER ||	     type == SND_CTL_ELEM_TYPE_INTEGER64 ||	     type == SND_CTL_ELEM_TYPE_ENUMERATED))		return 0; /* OK, compatible */	return -EINVAL;}/* * convert from an old value to a new value with the same dB level */static int convert_to_new_db(snd_config_t *value, long omin, long omax,			     long nmin, long nmax,			     long odbmin, long odbmax,			     long ndbmin, long ndbmax,			     int doit){	long val;	if (config_integer(value, &val, doit) < 0)		return -EINVAL;	if (val < omin || val > omax)		return -EINVAL;	val = ((val - omin) * (odbmax - odbmin)) / (omax - omin) + odbmin;	if (val < ndbmin)		val = ndbmin;	else if (val > ndbmax)		val = ndbmax;	val = ((val - ndbmin) * (nmax - nmin)) / (ndbmax - ndbmin) + nmin;	return snd_config_set_integer(value, val);}/* * compare the current value range with the old range in comments. * also, if dB information is available, try to compare them. * if any change occurs, try to keep the same dB level. */static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,			       snd_ctl_elem_info_t *info, snd_config_t *value,			       int doit){	snd_config_t *n;	long omin, omax, ostep;	long nmin, nmax;	long odbmin, odbmax;	long ndbmin, ndbmax;	snd_ctl_elem_id_t *id;	n = search_comment_item(conf, "range");	if (!n)		return 0;	if (get_comment_range(n, SND_CTL_ELEM_TYPE_INTEGER,			      &omin, &omax, &ostep) < 0)		return 0;	nmin = snd_ctl_elem_info_get_min(info);	nmax = snd_ctl_elem_info_get_max(info);	if (omin != nmin && omax != nmax) {		/* Hey, the range mismatches */		if (!force_restore || !doit)			return -EINVAL;	}	if (omin >= omax || nmin >= nmax)		return 0; /* invalid values */	n = search_comment_item(conf, "dbmin");	if (!n)		return 0;	if (config_integer(n, &odbmin, doit) < 0)		return 0;	n = search_comment_item(conf, "dbmax");	if (!n)		return 0;	if (config_integer(n, &odbmax, doit) < 0)		return 0;	if (odbmin >= odbmax)		return 0; /* invalid values */	snd_ctl_elem_id_alloca(&id);	snd_ctl_elem_info_get_id(info, id);	if (snd_ctl_get_dB_range(handle, id, &ndbmin, &ndbmax) < 0)		return 0;	if (ndbmin >= ndbmax)		return 0; /* invalid values */	if (omin == nmin && omax == nmax &&	    odbmin == ndbmin && odbmax == ndbmax)		return 0; /* OK, identical one */	/* Let's guess the current value from dB range */	if (snd_config_get_type(value) == SND_CONFIG_TYPE_COMPOUND) {		snd_config_iterator_t i, next;		snd_config_for_each(i, next, value) {			snd_config_t *n = snd_config_iterator_entry(i);			convert_to_new_db(n, omin, omax, nmin, nmax,					  odbmin, odbmax, ndbmin, ndbmax, doit);		}	} else		convert_to_new_db(value, omin, omax, nmin, nmax,				  odbmin, odbmax, ndbmin, ndbmax, doit);	return 0;}static int restore_config_value(snd_ctl_t *handle, snd_ctl_elem_info_t *info,				snd_ctl_elem_iface_t type,				snd_config_t *value,				snd_ctl_elem_value_t *ctl, int idx,				int doit){	long val;	long long lval;	int err;	switch (type) {	case SND_CTL_ELEM_TYPE_BOOLEAN:		val = config_bool(value, doit);		if (val >= 0) {			snd_ctl_elem_value_set_boolean(ctl, idx, val);			return 1;		}		break;	case SND_CTL_ELEM_TYPE_INTEGER:		err = config_integer(value, &val, doit);		if (err == 0) {			snd_ctl_elem_value_set_integer(ctl, idx, val);			return 1;		}		break;	case SND_CTL_ELEM_TYPE_INTEGER64:		err = config_integer64(value, &lval, doit);		if (err == 0) {			snd_ctl_elem_value_set_integer64(ctl, idx, lval);			return 1;		}		break;	case SND_CTL_ELEM_TYPE_ENUMERATED:		val = config_enumerated(value, handle, info, doit);		if (val >= 0) {			snd_ctl_elem_value_set_enumerated(ctl, idx, val);			return 1;		}		break;	case SND_CTL_ELEM_TYPE_BYTES:	case SND_CTL_ELEM_TYPE_IEC958:		break;	default:		cerror(doit, "Unknow control type: %d", type);		return -EINVAL;	}	return 0;}static int restore_config_value2(snd_ctl_t *handle, snd_ctl_elem_info_t *info,				 snd_ctl_elem_iface_t type,				 snd_config_t *value,				 snd_ctl_elem_value_t *ctl, int idx,				 unsigned int numid, int doit){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -