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 "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);
|
||||||
|
|
|
||||||
|
|
@ -45,13 +45,14 @@
|
||||||
#define MAX_CARD_SHORT_NAME 32
|
#define MAX_CARD_SHORT_NAME 32
|
||||||
#define MAX_CARD_LONG_NAME 80
|
#define MAX_CARD_LONG_NAME 80
|
||||||
|
|
||||||
#define SEQUENCE_ELEMENT_TYPE_CDEV 1
|
#define SEQUENCE_ELEMENT_TYPE_CDEV 1
|
||||||
#define SEQUENCE_ELEMENT_TYPE_CSET 2
|
#define SEQUENCE_ELEMENT_TYPE_CSET 2
|
||||||
#define SEQUENCE_ELEMENT_TYPE_SLEEP 3
|
#define SEQUENCE_ELEMENT_TYPE_SLEEP 3
|
||||||
#define SEQUENCE_ELEMENT_TYPE_EXEC 4
|
#define SEQUENCE_ELEMENT_TYPE_EXEC 4
|
||||||
#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