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

📄 init_parse.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Advanced Linux Sound Architecture Control Program - Parse initialization files *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>, *		     Greg Kroah-Hartman <greg@kroah.com>, *		     Kay Sievers <kay.sievers@vrfy.org> * * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program 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 General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA * */#include <stdlib.h>#include <stdio.h>#include <stddef.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <ctype.h>#include <errno.h>#include <fnmatch.h>#include <sys/stat.h>#include <sys/un.h>#include <sys/wait.h>#include <sys/select.h>#include <sys/types.h>#include <dirent.h>#include <math.h>#include <alsa/asoundlib.h>#include "aconfig.h"#include "alsactl.h"#include "list.h"#define PATH_SIZE	512#define NAME_SIZE	128#define EJUSTRETURN	0x7fffffffenum key_op {	KEY_OP_UNSET,	KEY_OP_MATCH,	KEY_OP_NOMATCH,	KEY_OP_ADD,	KEY_OP_ASSIGN,	KEY_OP_ASSIGN_FINAL};struct pair {	char *key;	char *value;	struct pair *next;};struct space {	struct pair *pairs;	char *rootdir;	char *go_to;	char *program_result;	const char *filename;	int linenum;	int log_run;	int exit_code;	int quit;	unsigned int ctl_id_changed;	snd_hctl_t *ctl_handle;	snd_ctl_card_info_t *ctl_card_info;	snd_ctl_elem_id_t *ctl_id;	snd_ctl_elem_info_t *ctl_info;	snd_ctl_elem_value_t *ctl_value;};static void Perror(struct space *space, const char *fmt, ...){	va_list arg;	va_start(arg, fmt);	fprintf(stderr, "%s:%i: ", space->filename, space->linenum);	vfprintf(stderr, fmt, arg);	putc('\n', stderr);	va_end(arg);}#include "init_sysdeps.c"#include "init_utils_string.c"#include "init_utils_run.c"#include "init_sysfs.c"static void free_space(struct space *space){	struct pair *pair = space->pairs;	struct pair *next = pair;	while (next) {		pair = next;		next = pair->next;		free(pair->value);		free(pair->key);		free(pair);	}	space->pairs = NULL;	if (space->ctl_value) {		snd_ctl_elem_value_free(space->ctl_value);		space->ctl_value = NULL;	}	if (space->ctl_info) {		snd_ctl_elem_info_free(space->ctl_info);		space->ctl_info = NULL;	}	if (space->ctl_id) {		snd_ctl_elem_id_free(space->ctl_id);		space->ctl_id = NULL;	}	if (space->ctl_card_info) {		snd_ctl_card_info_free(space->ctl_card_info);		space->ctl_card_info = NULL;	}	if (space->ctl_handle) {		snd_hctl_close(space->ctl_handle);		space->ctl_handle = NULL;	}	if (space->rootdir)		free(space->rootdir);	if (space->program_result)		free(space->program_result);	if (space->go_to)		free(space->go_to);	free(space);}static struct pair *value_find(struct space *space, const char *key){	struct pair *pair = space->pairs;		while (pair && strcmp(pair->key, key) != 0)		pair = pair->next;	return pair;}static int value_set(struct space *space, const char *key, const char *value){	struct pair *pair;		pair = value_find(space, key);	if (pair) {		free(pair->value);		pair->value = strdup(value);		if (pair->value == NULL)			return -ENOMEM;	} else {		pair = malloc(sizeof(struct pair));		if (pair == NULL)			return -ENOMEM;		pair->key = strdup(key);		if (pair->key == NULL) {			free(pair);			return -ENOMEM;		}		pair->value = strdup(value);		if (pair->value == NULL) {			free(pair->key);			free(pair);			return -ENOMEM;		}		pair->next = space->pairs;		space->pairs = pair;	}	return 0;}static int init_space(struct space **space, int card){	struct space *res;	char device[16];	int err;	res = calloc(1, sizeof(struct space));	if (res == NULL)		return -ENOMEM;	res->ctl_id_changed = ~0;	res->linenum = -1;	sprintf(device, "hw:%u", card);	err = snd_hctl_open(&res->ctl_handle, device, 0);	if (err < 0)		goto error;	err = snd_hctl_load(res->ctl_handle);	if (err < 0)		goto error;	err = snd_ctl_card_info_malloc(&res->ctl_card_info);	if (err < 0)		goto error;	err = snd_ctl_card_info(snd_hctl_ctl(res->ctl_handle), res->ctl_card_info);	if (err < 0)		goto error;	err = snd_ctl_elem_id_malloc(&res->ctl_id);	if (err < 0)		goto error;	err = snd_ctl_elem_info_malloc(&res->ctl_info);	if (err < 0)		goto error;	err = snd_ctl_elem_value_malloc(&res->ctl_value);	if (err < 0)		goto error;	*space = res;	return 0; error: 	free_space(res); 	return err;}static const char *cardinfo_get(struct space *space, const char *attr){	if (strncasecmp(attr, "CARD", 4) == 0) {		static char res[16];		sprintf(res, "%u", snd_ctl_card_info_get_card(space->ctl_card_info));		return res;	}	if (strncasecmp(attr, "ID", 2) == 0)		return snd_ctl_card_info_get_id(space->ctl_card_info);	if (strncasecmp(attr, "DRIVER", 6) == 0)		return snd_ctl_card_info_get_driver(space->ctl_card_info);	if (strncasecmp(attr, "NAME", 4) == 0)		return snd_ctl_card_info_get_name(space->ctl_card_info);	if (strncasecmp(attr, "LONGNAME", 8) == 0)		return snd_ctl_card_info_get_longname(space->ctl_card_info);	if (strncasecmp(attr, "MIXERNAME", 9) == 0)		return snd_ctl_card_info_get_mixername(space->ctl_card_info);	if (strncasecmp(attr, "COMPONENTS", 10) == 0)		return snd_ctl_card_info_get_components(space->ctl_card_info);	Perror(space, "unknown cardinfo{} attribute '%s'", attr);	return NULL;}static int check_id_changed(struct space *space, unsigned int what){	snd_hctl_elem_t *elem;	int err;	if ((space->ctl_id_changed & what & 1) != 0) {		snd_ctl_elem_id_set_numid(space->ctl_id, 0);		elem = snd_hctl_find_elem(space->ctl_handle, space->ctl_id);		if (!elem)			return -ENOENT;		err = snd_hctl_elem_info(elem, space->ctl_info);		if (err == 0)			space->ctl_id_changed &= ~1;		return err;	}	if ((space->ctl_id_changed & what & 2) != 0) {		snd_ctl_elem_id_set_numid(space->ctl_id, 0);		elem = snd_hctl_find_elem(space->ctl_handle, space->ctl_id);		if (!elem)			return -ENOENT;		err = snd_hctl_elem_read(elem, space->ctl_value);		if (err == 0)			space->ctl_id_changed &= ~2;		return err;	}	return 0;}static const char *get_ctl_value(struct space *space){	snd_ctl_elem_type_t type;	unsigned int idx, count;	static char res[1024], tmp[16];	static const char hex[] = "0123456789abcdef";	char *pos;	const char *pos1;	type = snd_ctl_elem_info_get_type(space->ctl_info);	count = snd_ctl_elem_info_get_count(space->ctl_info);	res[0] = '\0';	switch (type) {	case SND_CTL_ELEM_TYPE_BOOLEAN:		for (idx = 0; idx < count; idx++) {			if (idx > 0)				strlcat(res, ",", sizeof(res));			strlcat(res, snd_ctl_elem_value_get_boolean(space->ctl_value, idx) ? "on" : "off", sizeof(res));		}		break;	case SND_CTL_ELEM_TYPE_INTEGER:		for (idx = 0; idx < count; idx++) {			if (idx > 0)				strlcat(res, ",", sizeof(res));			snprintf(tmp, sizeof(tmp), "%li", snd_ctl_elem_value_get_integer(space->ctl_value, idx));			strlcat(res, tmp, sizeof(res));		}		break;	case SND_CTL_ELEM_TYPE_INTEGER64:		for (idx = 0; idx < count; idx++) {			if (idx > 0)				strlcat(res, ",", sizeof(res));			snprintf(tmp, sizeof(tmp), "%lli", snd_ctl_elem_value_get_integer64(space->ctl_value, idx));			strlcat(res, tmp, sizeof(res));		}		break;	case SND_CTL_ELEM_TYPE_ENUMERATED:		for (idx = 0; idx < count; idx++) {			if (idx > 0)				strlcat(res, ",", sizeof(res));			snprintf(tmp, sizeof(tmp), "%u", snd_ctl_elem_value_get_enumerated(space->ctl_value, idx));			strlcat(res, tmp, sizeof(res));		}		break;	case SND_CTL_ELEM_TYPE_BYTES:	case SND_CTL_ELEM_TYPE_IEC958:		if (type == SND_CTL_ELEM_TYPE_IEC958)			count = sizeof(snd_aes_iec958_t);		if (count > (sizeof(res)-1)/2)			count = (sizeof(res)-1/2);		pos = res;		pos1 = snd_ctl_elem_value_get_bytes(space->ctl_value);		while (count > 0) {			idx = *pos1++;			*pos++ = hex[idx >> 4];			*pos++ = hex[idx & 0x0f];			count++;		}		*pos++ = '\0';		break;	default:		Perror(space, "unknown element type '%i'", type);		return NULL;	}	return res;}/* Function to convert from percentage to volume. val = percentage */#define convert_prange1(val, min, max) \        ceil((val) * ((max) - (min)) * 0.01 + (min))static int set_ctl_value(struct space *space, const char *value, int all){	snd_ctl_elem_type_t type;	unsigned int idx, idx2, count, items;	const char *pos, *pos2;	snd_hctl_elem_t *elem;	int val;	long lval;	type = snd_ctl_elem_info_get_type(space->ctl_info);	count = snd_ctl_elem_info_get_count(space->ctl_info);	switch (type) {	case SND_CTL_ELEM_TYPE_BOOLEAN:		for (idx = 0; idx < count; idx++) {			while (*value == ' ')				value++;			if (*value == '\0')				goto missing;			val = strncasecmp(value, "true", 4) == 0 ||				strncasecmp(value, "yes", 3) == 0 ||				strncasecmp(value, "on", 2) == 0 ||				strncasecmp(value, "1", 1) == 0;			snd_ctl_elem_value_set_boolean(space->ctl_value, idx, val);			if (all)				continue;			pos = strchr(value, ',');			value = pos ? pos + 1 : value + strlen(value) - 1;		}		break;	case SND_CTL_ELEM_TYPE_INTEGER:		for (idx = 0; idx < count; idx++) {			while (*value == ' ')				value++;			pos = strchr(value, ',');			if (pos)				*(char *)pos = '\0';			remove_trailing_chars((char *)value, ' ');			items = pos ? pos - value : strlen(value);			if (items > 1 && value[items-1] == '%') {				val = convert_prange1(strtol(value, NULL, 0), snd_ctl_elem_info_get_min(space->ctl_info), snd_ctl_elem_info_get_max(space->ctl_info));				snd_ctl_elem_value_set_integer(space->ctl_value, idx, val);			} else if (items > 2 && value[items-2] == 'd' && value[items-1] == 'B') {				val = strtol(value, NULL, 0) * 100;				if ((pos2 = index(value, '.')) != NULL) {					if (isdigit(*(pos2-1)) && isdigit(*(pos2-2))) {						if (val < 0)							val -= strtol(pos2 + 1, NULL, 0);						else							val += strtol(pos2 + 1, NULL, 0);					} else if (isdigit(*(pos2-1))) {						if (val < 0)							val -= strtol(pos2 + 1, NULL, 0) * 10;						else							val += strtol(pos2 + 1, NULL, 0) * 10;					}				}				val = snd_ctl_convert_from_dB(snd_hctl_ctl(space->ctl_handle), space->ctl_id, val, &lval, -1);				if (val < 0) {					Perror(space, "unable to convert dB value '%s' to internal integer range", value);					return val;				}				snd_ctl_elem_value_set_integer(space->ctl_value, idx, lval);			} else {				snd_ctl_elem_value_set_integer(space->ctl_value, idx, strtol(value, NULL, 0));			}			if (all)				continue;			value = pos ? pos + 1 : value + strlen(value) - 1;		}		break;	case SND_CTL_ELEM_TYPE_INTEGER64:		for (idx = 0; idx < count; idx++) {			while (*value == ' ')				value++;			snd_ctl_elem_value_set_integer64(space->ctl_value, idx, strtoll(value, NULL, 0));			if (all)				continue;			pos = strchr(value, ',');			value = pos ? pos + 1 : value + strlen(value) - 1;		}		break;	case SND_CTL_ELEM_TYPE_ENUMERATED:		for (idx = 0; idx < count; idx++) {			while (*value == ' ')				value++;			pos = strchr(value, ',');			if (isdigit(value[0]) || value[0] == '-') {				snd_ctl_elem_value_set_enumerated(space->ctl_value, idx, strtol(value, NULL, 0));			} else {				if (pos)					*(char *)pos = '\0';				remove_trailing_chars((char *)value, ' ');				items = snd_ctl_elem_info_get_items(space->ctl_info);				for (idx2 = 0; idx2 < items; idx2++) {					snd_ctl_elem_info_set_item(space->ctl_info, idx2);					elem = snd_hctl_find_elem(space->ctl_handle, space->ctl_id);					if (elem == NULL)						return -ENOENT;					val = snd_hctl_elem_info(elem, space->ctl_info);					if (val < 0)						return val;					if (strcasecmp(snd_ctl_elem_info_get_item_name(space->ctl_info), value) == 0) {						snd_ctl_elem_value_set_enumerated(space->ctl_value, idx, idx2);						break;					}				}				if (idx2 >= items) {					Perror(space, "wrong enum identifier '%s'", value);					return -EINVAL;				}			}			if (all)				continue;			value = pos ? pos + 1 : value + strlen(value) - 1;		}		break;	case SND_CTL_ELEM_TYPE_BYTES:	case SND_CTL_ELEM_TYPE_IEC958:		if (type == SND_CTL_ELEM_TYPE_IEC958)			count = sizeof(snd_aes_iec958_t);		while (*value == ' ')			value++;		if (strlen(value) != count * 2) {			Perror(space, "bad ctl value hexa length (should be %u bytes)", count);			return -EINVAL;		}		for (idx = 0; idx < count; idx += 2) {			val = hextodigit(*(value++)) << 4;			val |= hextodigit(*(value++));			if (val > 255) {				Perror(space, "bad ctl hexa value");				return -EINVAL;			}			snd_ctl_elem_value_set_byte(space->ctl_value, idx, val);		}		break;	default:		Perror(space, "unknown element type '%i'", type);		return -EINVAL;	}	return 0;  missing:  	printf("%i %i\n", type, count);  	Perror(space, "missing some ctl values (line %i)", space->linenum);  	return -EINVAL;}static const char *elemid_get(struct space *space, const char *attr){	long long val;	snd_ctl_elem_type_t type;	static char res[256];	if (strncasecmp(attr, "numid", 5) == 0) {		val = snd_ctl_elem_id_get_numid(space->ctl_id);	    	goto value;	}	if (strncasecmp(attr, "iface", 5) == 0 ||	    strncasecmp(attr, "interface", 9) == 0)	    	return snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(space->ctl_id));	if (strncasecmp(attr, "device", 6) == 0) {		val = snd_ctl_elem_id_get_device(space->ctl_id);	    	goto value;	}	if (strncasecmp(attr, "subdev", 6) == 0) {		val = snd_ctl_elem_id_get_subdevice(space->ctl_id);	    	goto value;	}	if (strncasecmp(attr, "name", 4) == 0)		return snd_ctl_elem_id_get_name(space->ctl_id);	if (strncasecmp(attr, "index", 5) == 0) {		val = snd_ctl_elem_id_get_index(space->ctl_id);	    	goto value;	}	if (strncasecmp(attr, "type", 4) == 0) {		if (check_id_changed(space, 1))			return NULL;		return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(space->ctl_info));	}	if (strncasecmp(attr, "attr", 4) == 0) {		if (check_id_changed(space, 1))			return NULL;		res[0] = '\0';		if (snd_ctl_elem_info_is_readable(space->ctl_info))			strcat(res, "r");		if (snd_ctl_elem_info_is_writable(space->ctl_info))			strcat(res, "w");		if (snd_ctl_elem_info_is_volatile(space->ctl_info))			strcat(res, "v");		if (snd_ctl_elem_info_is_inactive(space->ctl_info))			strcat(res, "i");		if (snd_ctl_elem_info_is_locked(space->ctl_info))			strcat(res, "l");		if (snd_ctl_elem_info_is_tlv_readable(space->ctl_info))			strcat(res, "R");		if (snd_ctl_elem_info_is_tlv_writable(space->ctl_info))			strcat(res, "W");		if (snd_ctl_elem_info_is_tlv_commandable(space->ctl_info))			strcat(res, "C");		if (snd_ctl_elem_info_is_owner(space->ctl_info))			strcat(res, "o");		if (snd_ctl_elem_info_is_user(space->ctl_info))			strcat(res, "u");		return res;	}	if (strncasecmp(attr, "owner", 5) == 0) {		if (check_id_changed(space, 1))			return NULL;		val = snd_ctl_elem_info_get_owner(space->ctl_info);		goto value;	}	if (strncasecmp(attr, "count", 5) == 0) {		if (check_id_changed(space, 1))			return NULL;		val = snd_ctl_elem_info_get_count(space->ctl_info);		goto value;	}	if (strncasecmp(attr, "min", 3) == 0) {		if (check_id_changed(space, 1))			return NULL;		type = snd_ctl_elem_info_get_type(space->ctl_info);		if (type == SND_CTL_ELEM_TYPE_INTEGER64)			val = snd_ctl_elem_info_get_min64(space->ctl_info);		else if (type == SND_CTL_ELEM_TYPE_INTEGER)			val = snd_ctl_elem_info_get_min(space->ctl_info);		else			goto empty;		goto value;	}	if (strncasecmp(attr, "max", 3) == 0) {		if (check_id_changed(space, 1))			return NULL;		type = snd_ctl_elem_info_get_type(space->ctl_info);		if (type == SND_CTL_ELEM_TYPE_INTEGER64)			val = snd_ctl_elem_info_get_max64(space->ctl_info);		else if (type == SND_CTL_ELEM_TYPE_INTEGER)			val = snd_ctl_elem_info_get_max(space->ctl_info);		else			goto empty;		goto value;

⌨️ 快捷键说明

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