OSDN Git Service

ucm: implement sysset sequence command
authorJaroslav Kysela <perex@perex.cz>
Fri, 5 Mar 2021 18:55:06 +0000 (19:55 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 11 Mar 2021 08:26:07 +0000 (09:26 +0100)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/ucm/main.c
src/ucm/parser.c
src/ucm/ucm_local.h
src/ucm/ucm_subs.c
src/ucm/utils.c

index f9f78e0..e2a268d 100644 (file)
@@ -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;
index 55781f8..e1ff1c1 100644 (file)
@@ -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);
index c3e5a07..9474950 100644 (file)
 #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);
index 7e745bc..08de526 100644 (file)
@@ -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);
index 24d0631..e5fbb42 100644 (file)
@@ -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;