*/
#include "ucm_local.h"
+#include <stdbool.h>
#include <ctype.h>
#include <stdarg.h>
#include <pthread.h>
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
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;
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);
#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;
char *cdev;
char *cset;
char *exec;
+ char *sysset;
struct component_sequence cmpt_seq; /* component sequence */
} data;
};
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);
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);
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;
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;