mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	ucm: implement sysset sequence command
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
		
							parent
							
								
									2b418648cf
								
							
						
					
					
						commit
						1c6fb20232
					
				
					 5 changed files with 107 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "ucm_local.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -323,6 +324,72 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
 | 
			
		|||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int execute_sysset(const char *sysset)
 | 
			
		||||
{
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	const char *e;
 | 
			
		||||
	char *s, *value;
 | 
			
		||||
	ssize_t wlen;
 | 
			
		||||
	size_t len;
 | 
			
		||||
	int fd, myerrno;
 | 
			
		||||
	bool ignore_error = false;
 | 
			
		||||
 | 
			
		||||
	if (sysset == NULL || *sysset == '\0')
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	ignore_error = sysset[0] == '-';
 | 
			
		||||
 | 
			
		||||
	if (sysset[0] == ':')
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	s = strdup(sysset[0] != '/' ? sysset : sysset + 1);
 | 
			
		||||
	if (s == NULL)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	value = strchr(s, ':');
 | 
			
		||||
	if (!value) {
 | 
			
		||||
		free(s);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	*value = '\0';
 | 
			
		||||
	value++;
 | 
			
		||||
	len = strlen(value);
 | 
			
		||||
	if (len < 1) {
 | 
			
		||||
		free(s);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	e = uc_mgr_sysfs_root();
 | 
			
		||||
	if (e == NULL) {
 | 
			
		||||
		free(s);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	snprintf(path, sizeof(path), "%s/%s", e, s);
 | 
			
		||||
 | 
			
		||||
	fd = open(path, O_WRONLY|O_CLOEXEC);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		free(s);
 | 
			
		||||
		if (ignore_error)
 | 
			
		||||
			return 0;
 | 
			
		||||
		uc_error("unable to open '%s' for write", path);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
	wlen = write(fd, value, len);
 | 
			
		||||
	myerrno = errno;
 | 
			
		||||
	close(fd);
 | 
			
		||||
	free(s);
 | 
			
		||||
 | 
			
		||||
	if (ignore_error)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (wlen != (ssize_t)len) {
 | 
			
		||||
		uc_error("unable to write '%s' to '%s': %s", value, path, strerror(myerrno));
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Execute the sequence
 | 
			
		||||
 * \param uc_mgr Use case manager
 | 
			
		||||
| 
						 | 
				
			
			@ -420,6 +487,11 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
			
		|||
				goto __fail;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case SEQUENCE_ELEMENT_TYPE_SYSSET:
 | 
			
		||||
			err = execute_sysset(s->data.sysset);
 | 
			
		||||
			if (err < 0)
 | 
			
		||||
				goto __fail;
 | 
			
		||||
			break;
 | 
			
		||||
		case SEQUENCE_ELEMENT_TYPE_SLEEP:
 | 
			
		||||
			usleep(s->data.sleep);
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -772,6 +772,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
			
		|||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (strcmp(cmd, "sysset") == 0) {
 | 
			
		||||
			curr->type = SEQUENCE_ELEMENT_TYPE_SYSSET;
 | 
			
		||||
			err = parse_string_substitute3(uc_mgr, n, &curr->data.sysset);
 | 
			
		||||
			if (err < 0) {
 | 
			
		||||
				uc_error("error: sysset requires a string!");
 | 
			
		||||
				return err;
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (strcmp(cmd, "usleep") == 0) {
 | 
			
		||||
			curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
 | 
			
		||||
			err = parse_integer_substitute3(uc_mgr, n, &curr->data.sleep);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,13 +45,14 @@
 | 
			
		|||
#define MAX_CARD_SHORT_NAME	32
 | 
			
		||||
#define MAX_CARD_LONG_NAME	80
 | 
			
		||||
 | 
			
		||||
#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_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
 | 
			
		||||
#define SEQUENCE_ELEMENT_TYPE_CSET_TLV	6
 | 
			
		||||
#define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ	7
 | 
			
		||||
#define SEQUENCE_ELEMENT_TYPE_CSET_TLV		6
 | 
			
		||||
#define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ		7
 | 
			
		||||
#define SEQUENCE_ELEMENT_TYPE_SYSSET		8
 | 
			
		||||
 | 
			
		||||
struct ucm_value {
 | 
			
		||||
        struct list_head list;
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +74,7 @@ struct sequence_element {
 | 
			
		|||
		char *cdev;
 | 
			
		||||
		char *cset;
 | 
			
		||||
		char *exec;
 | 
			
		||||
		char *sysset;
 | 
			
		||||
		struct component_sequence cmpt_seq; /* component sequence */
 | 
			
		||||
	} data;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -269,6 +271,7 @@ struct snd_use_case_mgr {
 | 
			
		|||
void uc_mgr_error(const char *fmt, ...);
 | 
			
		||||
void uc_mgr_stdout(const char *fmt, ...);
 | 
			
		||||
 | 
			
		||||
const char *uc_mgr_sysfs_root(void);
 | 
			
		||||
const char *uc_mgr_config_dir(int format);
 | 
			
		||||
int uc_mgr_config_load(int format, const char *file, snd_config_t **cfg);
 | 
			
		||||
int uc_mgr_config_load_file(snd_use_case_mgr_t *uc_mgr,  const char *file, snd_config_t **cfg);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -508,12 +508,12 @@ static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char
 | 
			
		|||
	char path[PATH_MAX], link[PATH_MAX + 1];
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
	ssize_t len;
 | 
			
		||||
	char *e;
 | 
			
		||||
	const char *e;
 | 
			
		||||
	int fd;
 | 
			
		||||
 | 
			
		||||
	e = getenv("SYSFS_PATH");
 | 
			
		||||
	e = uc_mgr_sysfs_root();
 | 
			
		||||
	if (e == NULL)
 | 
			
		||||
		e = "/sys";
 | 
			
		||||
		return NULL;
 | 
			
		||||
	if (id[0] == '/')
 | 
			
		||||
		id++;
 | 
			
		||||
	snprintf(path, sizeof(path), "%s/%s", e, id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,6 +49,16 @@ void uc_mgr_stdout(const char *fmt,...)
 | 
			
		|||
	va_end(va);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *uc_mgr_sysfs_root(void)
 | 
			
		||||
{
 | 
			
		||||
	const char *e = getenv("SYSFS_PATH");
 | 
			
		||||
	if (e == NULL)
 | 
			
		||||
		return "/sys";
 | 
			
		||||
	if (*e == '\0')
 | 
			
		||||
		uc_error("no sysfs root!");
 | 
			
		||||
	return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ctl_list *uc_mgr_get_master_ctl(snd_use_case_mgr_t *uc_mgr)
 | 
			
		||||
{
 | 
			
		||||
	struct list_head *pos;
 | 
			
		||||
| 
						 | 
				
			
			@ -479,6 +489,9 @@ void uc_mgr_free_sequence_element(struct sequence_element *seq)
 | 
			
		|||
	case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
 | 
			
		||||
		free(seq->data.cset);
 | 
			
		||||
		break;
 | 
			
		||||
	case SEQUENCE_ELEMENT_TYPE_SYSSET:
 | 
			
		||||
		free(seq->data.sysset);
 | 
			
		||||
		break;
 | 
			
		||||
	case SEQUENCE_ELEMENT_TYPE_EXEC:
 | 
			
		||||
		free(seq->data.exec);
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue