mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-31 22:25:35 -04: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);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#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_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