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

📄 state.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	int err = restore_config_value(handle, info, type, value, ctl, idx, doit);	long val;	if (err != 0)		return err;	switch (type) {	case SND_CTL_ELEM_TYPE_BYTES:	case SND_CTL_ELEM_TYPE_IEC958:		err = snd_config_get_integer(value, &val);		if (err < 0 || val < 0 || val > 255) {			cerror(doit, "bad control.%d.value.%d content", numid, idx);			return force_restore && doit ? 0 : -EINVAL;		}		snd_ctl_elem_value_set_byte(ctl, idx, val);		return 1;		break;	default:		break;	}	return 0;}static int set_control(snd_ctl_t *handle, snd_config_t *control,		       int *maxnumid, int doit){	snd_ctl_elem_value_t *ctl;	snd_ctl_elem_info_t *info;	snd_config_iterator_t i, next;	unsigned int numid1;	snd_ctl_elem_iface_t iface = -1;	int iface1;	const char *name1;	unsigned int numid;	snd_ctl_elem_type_t type;	unsigned int count;	long device = -1;	long device1;	long subdevice = -1;	long subdevice1;	const char *name = NULL;	long index1;	long index = -1;	snd_config_t *value = NULL;	snd_config_t *comment = NULL;	unsigned int idx;	int err;	char *set;	const char *id;	snd_ctl_elem_value_alloca(&ctl);	snd_ctl_elem_info_alloca(&info);	if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {		cerror(doit, "control is not a compound");		return -EINVAL;	}	err = snd_config_get_id(control, &id);	if (err < 0) {		cerror(doit, "unable to get id");		return -EINVAL;	}	numid = atoi(id);	if ((int)numid > *maxnumid)		*maxnumid = numid;	snd_config_for_each(i, next, control) {		snd_config_t *n = snd_config_iterator_entry(i);		const char *fld;		if (snd_config_get_id(n, &fld) < 0)			continue;		if (strcmp(fld, "comment") == 0) {			if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {				cerror(doit, "control.%d.%s is invalid", numid, fld);				return -EINVAL;			}			comment = n;			continue;		}		if (strcmp(fld, "iface") == 0) {			iface = (snd_ctl_elem_iface_t)config_iface(n);			continue;		}		if (strcmp(fld, "device") == 0) {			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {				cerror(doit, "control.%d.%s is invalid", numid, fld);				return -EINVAL;			}			snd_config_get_integer(n, &device);			continue;		}		if (strcmp(fld, "subdevice") == 0) {			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {				cerror(doit, "control.%d.%s is invalid", numid, fld);				return -EINVAL;			}			snd_config_get_integer(n, &subdevice);			continue;		}		if (strcmp(fld, "name") == 0) {			if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {				cerror(doit, "control.%d.%s is invalid", numid, fld);				return -EINVAL;			}			snd_config_get_string(n, &name);			continue;		}		if (strcmp(fld, "index") == 0) {			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {				cerror(doit, "control.%d.%s is invalid", numid, fld);				return -EINVAL;			}			snd_config_get_integer(n, &index);			continue;		}		if (strcmp(fld, "value") == 0) {			value = n;			continue;		}		cerror(doit, "unknown control.%d.%s field", numid, fld);	}	if (!value) {		cerror(doit, "missing control.%d.value", numid);		return -EINVAL;	}	if (device < 0)		device = 0;	if (subdevice < 0)		subdevice = 0;	if (index < 0)		index = 0;	err = -EINVAL;	if (!force_restore) {		snd_ctl_elem_info_set_numid(info, numid);		err = snd_ctl_elem_info(handle, info);	}	if (err < 0 && name) {		snd_ctl_elem_info_set_numid(info, 0);		snd_ctl_elem_info_set_interface(info, iface);		snd_ctl_elem_info_set_device(info, device);		snd_ctl_elem_info_set_subdevice(info, subdevice);		snd_ctl_elem_info_set_name(info, name);		snd_ctl_elem_info_set_index(info, index);		err = snd_ctl_elem_info(handle, info);		if (err < 0 && comment && is_user_control(comment)) {			err = add_user_control(handle, info, comment);			if (err < 0) {				cerror(doit, "failed to add user control #%d (%s)",				       numid, snd_strerror(err));				return err;			}		}	}	if (err < 0) {		cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err));		return -ENOENT;	}	numid1 = snd_ctl_elem_info_get_numid(info);	iface1 = snd_ctl_elem_info_get_interface(info);	device1 = snd_ctl_elem_info_get_device(info);	subdevice1 = snd_ctl_elem_info_get_subdevice(info);	name1 = snd_ctl_elem_info_get_name(info);	index1 = snd_ctl_elem_info_get_index(info);	count = snd_ctl_elem_info_get_count(info);	type = snd_ctl_elem_info_get_type(info);	if (err |= numid != numid1 && !force_restore)		cerror(doit, "warning: numid mismatch (%d/%d) for control #%d", 		      numid, numid1, numid);	if (err |= iface != iface1)		cerror(doit, "warning: iface mismatch (%d/%d) for control #%d", iface, iface1, numid);	if (err |= device != device1)		cerror(doit, "warning: device mismatch (%ld/%ld) for control #%d", device, device1, numid);	if (err |= subdevice != subdevice1)		cerror(doit, "warning: subdevice mismatch (%ld/%ld) for control #%d", subdevice, subdevice1, numid);	if (err |= strcmp(name, name1))		cerror(doit, "warning: name mismatch (%s/%s) for control #%d", name, name1, numid);	if (err |= index != index1)		cerror(doit, "warning: index mismatch (%ld/%ld) for control #%d", index, index1, numid);	if (err < 0) {		cerror(doit, "failed to obtain info for control #%d (%s)", numid, snd_strerror(err));		return -ENOENT;	}	if (comment) {		if (check_comment_type(comment, type) < 0)			cerror(doit, "incompatible field type for control #%d", numid);		if (type == SND_CTL_ELEM_TYPE_INTEGER) {			if (check_comment_range(handle, comment, info, value, doit) < 0) {				cerror(doit, "value range mismatch for control #%d",				      numid);				return -EINVAL;			}		}	}	if (snd_ctl_elem_info_is_inactive(info) ||				!snd_ctl_elem_info_is_writable(info))		return 0;	snd_ctl_elem_value_set_numid(ctl, numid1);	if (count == 1) {		err = restore_config_value(handle, info, type, value, ctl, 0, doit);		if (err < 0)			return err;		if (err > 0)			goto _ok;	}	switch (type) {	case SND_CTL_ELEM_TYPE_BYTES:	case SND_CTL_ELEM_TYPE_IEC958:	{		const char *buf;		err = snd_config_get_string(value, &buf);		if (err >= 0) {			int c1 = 0;			int len = strlen(buf);			unsigned int idx = 0;			int size = type == SND_CTL_ELEM_TYPE_BYTES ?				count : sizeof(snd_aes_iec958_t);			if (size * 2 != len) {				cerror(doit, "bad control.%d.value contents\n", numid);				return -EINVAL;			}			while (*buf) {				int c = *buf++;				if ((c = hextodigit(c)) < 0) {					cerror(doit, "bad control.%d.value contents\n", numid);					return -EINVAL;				}				if (idx % 2 == 1)					snd_ctl_elem_value_set_byte(ctl, idx / 2, c1 << 4 | c);				else					c1 = c;				idx++;			}			goto _ok;		}	}	default:		break;	}	if (snd_config_get_type(value) != SND_CONFIG_TYPE_COMPOUND) {		if (!force_restore || !doit) {			cerror(doit, "bad control.%d.value type", numid);			return -EINVAL;		}		for (idx = 0; idx < count; ++idx) {			err = restore_config_value2(handle, info, type, value,						    ctl, idx, numid, doit);			if (err < 0)				return err;		}		goto _ok;	}	set = (char*) alloca(count);	memset(set, 0, count);	snd_config_for_each(i, next, value) {		snd_config_t *n = snd_config_iterator_entry(i);		const char *id;		if (snd_config_get_id(n, &id) < 0)			continue;		idx = atoi(id);		if (idx >= count || set[idx]) {			cerror(doit, "bad control.%d.value index", numid);			if (!force_restore || !doit)				return -EINVAL;			continue;		}		err = restore_config_value2(handle, info, type, n,					    ctl, idx, numid, doit);		if (err < 0)			return err;		if (err > 0)			set[idx] = 1;	}	for (idx = 0; idx < count; ++idx) {		if (!set[idx]) {			cerror(doit, "control.%d.value.%d is not specified", numid, idx);			if (!force_restore || !doit)				return -EINVAL;		}	} _ok:	err = doit ? snd_ctl_elem_write(handle, ctl) : 0;	if (err < 0) {		error("Cannot write control '%d:%ld:%ld:%s:%ld' : %s", (int)iface, device, subdevice, name, index, snd_strerror(err));		return err;	}	return 0;}static int set_controls(int card, snd_config_t *top, int doit){	snd_ctl_t *handle;	snd_ctl_card_info_t *info;	snd_config_t *control;	snd_config_iterator_t i, next;	int err, maxnumid = -1;	char name[32], tmpid[16];	const char *id;	snd_ctl_card_info_alloca(&info);	sprintf(name, "hw:%d", card);	err = snd_ctl_open(&handle, name, 0);	if (err < 0) {		error("snd_ctl_open error: %s", snd_strerror(err));		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_searchv(top, &control, "state", id, "control", 0);	if (err < 0) {		if (force_restore) {			sprintf(tmpid, "card%d", card);			err = snd_config_searchv(top, &control, "state", tmpid, "control", 0);			if (! err)				id = tmpid;		}		if (err < 0) {			fprintf(stderr, "No state is present for card %s\n", id);			goto _close;		}		id = tmpid;	}	if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {		cerror(doit, "state.%s.control is not a compound\n", id);		return -EINVAL;	}	snd_config_for_each(i, next, control) {		snd_config_t *n = snd_config_iterator_entry(i);		err = set_control(handle, n, &maxnumid, doit);		if (err < 0 && (!force_restore || !doit))			goto _close;	}	/* check if we have additional controls in driver */	/* in this case we should go through init procedure */	if (!doit && maxnumid >= 0) {		snd_ctl_elem_id_t *id;		snd_ctl_elem_info_t *info;		snd_ctl_elem_id_alloca(&id);		snd_ctl_elem_info_alloca(&info);		snd_ctl_elem_info_set_numid(info, maxnumid+1);		if (snd_ctl_elem_info(handle, info) == 0) {			/* not very informative */			/* but value is used for check only */			err = -EAGAIN;			goto _close;		}	} _close:	snd_ctl_close(handle);	return err;}int save_state(const char *file, const char *cardname){	int err;	snd_config_t *config;	snd_input_t *in;	snd_output_t *out;	int stdio;	err = snd_config_top(&config);	if (err < 0) {		error("snd_config_top error: %s", snd_strerror(err));		return err;	}	stdio = !strcmp(file, "-");	if (!stdio && (err = snd_input_stdio_open(&in, file, "r")) >= 0) {		err = snd_config_load(config, in);		snd_input_close(in);#if 0		if (err < 0) {			error("snd_config_load error: %s", snd_strerror(err));			return err;		}#endif	}	if (!cardname) {		int card, first = 1;		card = -1;		/* find each installed soundcards */		while (1) {			if (snd_card_next(&card) < 0)				break;			if (card < 0) {				if (first) {					if (ignore_nocards) {						return 0;					} else {						error("No soundcards found...");						return -ENODEV;					}				}				break;			}			first = 0;			if ((err = get_controls(card, config)))				return err;		}	} else {		int cardno;		cardno = snd_card_get_index(cardname);		if (cardno < 0) {			error("Cannot find soundcard '%s'...", cardname);			return cardno;		}		if ((err = get_controls(cardno, config))) {			return err;		}	}		if (stdio)		err = snd_output_stdio_attach(&out, stdout, 0);	else		err = snd_output_stdio_open(&out, file, "w");	if (err < 0) {		error("Cannot open %s for writing: %s", file, snd_strerror(err));		return -errno;	}	err = snd_config_save(config, out);	snd_output_close(out);	if (err < 0)		error("snd_config_save: %s", snd_strerror(err));	return 0;}int load_state(const char *file, const char *initfile, const char *cardname,	       int do_init){	int err, finalerr = 0;	snd_config_t *config;	snd_input_t *in;	int stdio;	err = snd_config_top(&config);	if (err < 0) {		error("snd_config_top error: %s", snd_strerror(err));		return err;	}	stdio = !strcmp(file, "-");	if (stdio)		err = snd_input_stdio_attach(&in, stdin, 0);	else		err = snd_input_stdio_open(&in, file, "r");	if (err >= 0) {		err = snd_config_load(config, in);		snd_input_close(in);		if (err < 0) {			error("snd_config_load error: %s", snd_strerror(err));			return err;		}	} else {		int card, first = 1;		char cardname1[16];		error("Cannot open %s for reading: %s", file, snd_strerror(err));		finalerr = err;		card = -1;		/* find each installed soundcards */		while (1) {			if (snd_card_next(&card) < 0)				break;			if (card < 0)				break;			first = 0;			if (!do_init)				break;			sprintf(cardname1, "%i", card);			err = init(initfile, cardname1);			if (err < 0) {				finalerr = err;				initfailed(card, "init");			}			initfailed(card, "restore");		}		if (first)			finalerr = 0;	/* no cards, no error code */		return finalerr;	}	if (!cardname) {		int card, first = 1;		char cardname1[16];		card = -1;		/* find each installed soundcards */		while (1) {			if (snd_card_next(&card) < 0)				break;			if (card < 0) {				if (first) {					if (ignore_nocards) {						return 0;					} else {						error("No soundcards found...");						return -ENODEV;					}				}				break;			}			first = 0;			/* do a check if controls matches state file */ 			if (do_init && set_controls(card, config, 0)) {				sprintf(cardname1, "%i", card);				err = init(initfile, cardname1);				if (err < 0) {					initfailed(card, "init");					finalerr = err;				}			}			if ((err = set_controls(card, config, 1))) {				if (!force_restore)					finalerr = err;				initfailed(card, "restore");			}		}	} else {		int cardno;		cardno = snd_card_get_index(cardname);		if (cardno < 0) {			error("Cannot find soundcard '%s'...", cardname);			return -ENODEV;		}		/* do a check if controls matches state file */		if (do_init && set_controls(cardno, config, 0)) {			err = init(initfile, cardname);			if (err < 0) {				initfailed(cardno, "init");				return err;			}		}		if ((err = set_controls(cardno, config, 1))) {			initfailed(cardno, "restore");			if (!force_restore)				return err;		}	}	return finalerr;}

⌨️ 快捷键说明

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