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 "ucm_local.h"
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <ctype.h>
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <stdarg.h>
 | 
					#include <stdarg.h>
 | 
				
			||||||
#include <pthread.h>
 | 
					#include <pthread.h>
 | 
				
			||||||
| 
						 | 
					@ -323,6 +324,72 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
 | 
				
			||||||
	return err;
 | 
						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
 | 
					 * \brief Execute the sequence
 | 
				
			||||||
 * \param uc_mgr Use case manager
 | 
					 * \param uc_mgr Use case manager
 | 
				
			||||||
| 
						 | 
					@ -420,6 +487,11 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
				goto __fail;
 | 
									goto __fail;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case SEQUENCE_ELEMENT_TYPE_SYSSET:
 | 
				
			||||||
 | 
								err = execute_sysset(s->data.sysset);
 | 
				
			||||||
 | 
								if (err < 0)
 | 
				
			||||||
 | 
									goto __fail;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		case SEQUENCE_ELEMENT_TYPE_SLEEP:
 | 
							case SEQUENCE_ELEMENT_TYPE_SLEEP:
 | 
				
			||||||
			usleep(s->data.sleep);
 | 
								usleep(s->data.sleep);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -772,6 +772,16 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
 | 
				
			||||||
			continue;
 | 
								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) {
 | 
							if (strcmp(cmd, "usleep") == 0) {
 | 
				
			||||||
			curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
 | 
								curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
 | 
				
			||||||
			err = parse_integer_substitute3(uc_mgr, n, &curr->data.sleep);
 | 
								err = parse_integer_substitute3(uc_mgr, n, &curr->data.sleep);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,7 @@
 | 
				
			||||||
#define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE	5
 | 
					#define SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE	5
 | 
				
			||||||
#define SEQUENCE_ELEMENT_TYPE_CSET_TLV		6
 | 
					#define SEQUENCE_ELEMENT_TYPE_CSET_TLV		6
 | 
				
			||||||
#define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ		7
 | 
					#define SEQUENCE_ELEMENT_TYPE_CMPT_SEQ		7
 | 
				
			||||||
 | 
					#define SEQUENCE_ELEMENT_TYPE_SYSSET		8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ucm_value {
 | 
					struct ucm_value {
 | 
				
			||||||
        struct list_head list;
 | 
					        struct list_head list;
 | 
				
			||||||
| 
						 | 
					@ -73,6 +74,7 @@ struct sequence_element {
 | 
				
			||||||
		char *cdev;
 | 
							char *cdev;
 | 
				
			||||||
		char *cset;
 | 
							char *cset;
 | 
				
			||||||
		char *exec;
 | 
							char *exec;
 | 
				
			||||||
 | 
							char *sysset;
 | 
				
			||||||
		struct component_sequence cmpt_seq; /* component sequence */
 | 
							struct component_sequence cmpt_seq; /* component sequence */
 | 
				
			||||||
	} data;
 | 
						} data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -269,6 +271,7 @@ struct snd_use_case_mgr {
 | 
				
			||||||
void uc_mgr_error(const char *fmt, ...);
 | 
					void uc_mgr_error(const char *fmt, ...);
 | 
				
			||||||
void uc_mgr_stdout(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);
 | 
					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(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);
 | 
					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];
 | 
						char path[PATH_MAX], link[PATH_MAX + 1];
 | 
				
			||||||
	struct stat sb;
 | 
						struct stat sb;
 | 
				
			||||||
	ssize_t len;
 | 
						ssize_t len;
 | 
				
			||||||
	char *e;
 | 
						const char *e;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	e = getenv("SYSFS_PATH");
 | 
						e = uc_mgr_sysfs_root();
 | 
				
			||||||
	if (e == NULL)
 | 
						if (e == NULL)
 | 
				
			||||||
		e = "/sys";
 | 
							return NULL;
 | 
				
			||||||
	if (id[0] == '/')
 | 
						if (id[0] == '/')
 | 
				
			||||||
		id++;
 | 
							id++;
 | 
				
			||||||
	snprintf(path, sizeof(path), "%s/%s", e, id);
 | 
						snprintf(path, sizeof(path), "%s/%s", e, id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,16 @@ void uc_mgr_stdout(const char *fmt,...)
 | 
				
			||||||
	va_end(va);
 | 
						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 ctl_list *uc_mgr_get_master_ctl(snd_use_case_mgr_t *uc_mgr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct list_head *pos;
 | 
						struct list_head *pos;
 | 
				
			||||||
| 
						 | 
					@ -479,6 +489,9 @@ void uc_mgr_free_sequence_element(struct sequence_element *seq)
 | 
				
			||||||
	case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
 | 
						case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
 | 
				
			||||||
		free(seq->data.cset);
 | 
							free(seq->data.cset);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case SEQUENCE_ELEMENT_TYPE_SYSSET:
 | 
				
			||||||
 | 
							free(seq->data.sysset);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case SEQUENCE_ELEMENT_TYPE_EXEC:
 | 
						case SEQUENCE_ELEMENT_TYPE_EXEC:
 | 
				
			||||||
		free(seq->data.exec);
 | 
							free(seq->data.exec);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue