external/alsa-lib
Revision | cb84b02702251745997c58353e2c2512219493b1 (tree) |
---|---|
Time | 2019-11-20 21:58:17 |
Author | Jaroslav Kysela <perex@pere...> |
Commiter | Jaroslav Kysela |
ucm: implement ${sys:sysfs/path} substitution
Example:
Condition {
Type String
String1 "${sys:class/dmi/id/board_vendor}"
String2 "LENOVO"
}
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
@@ -25,6 +25,8 @@ | ||
25 | 25 | */ |
26 | 26 | |
27 | 27 | #include "ucm_local.h" |
28 | +#include <sys/stat.h> | |
29 | +#include <limits.h> | |
28 | 30 | |
29 | 31 | static char *rval_conf_name(snd_use_case_mgr_t *uc_mgr) |
30 | 32 | { |
@@ -83,6 +85,56 @@ static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *i | ||
83 | 85 | return NULL; |
84 | 86 | } |
85 | 87 | |
88 | +static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id) | |
89 | +{ | |
90 | + char path[PATH_MAX], link[PATH_MAX + 1]; | |
91 | + struct stat sb; | |
92 | + ssize_t len; | |
93 | + char *e; | |
94 | + int fd; | |
95 | + | |
96 | + e = getenv("SYSFS_PATH"); | |
97 | + if (e == NULL) | |
98 | + e = "/sys"; | |
99 | + if (id[0] == '/') | |
100 | + id++; | |
101 | + snprintf(path, sizeof(path), "%s/%s", e, id); | |
102 | + if (lstat(path, &sb) != 0) | |
103 | + return NULL; | |
104 | + if (S_ISLNK(sb.st_mode)) { | |
105 | + len = readlink(path, link, sizeof(link) - 1); | |
106 | + if (len <= 0) { | |
107 | + uc_error("sysfs: cannot read link '%s' (%d)", path, errno); | |
108 | + return NULL; | |
109 | + } | |
110 | + link[len] = '\0'; | |
111 | + e = strrchr(link, '/'); | |
112 | + if (e) | |
113 | + return strdup(e + 1); | |
114 | + return NULL; | |
115 | + } | |
116 | + if (S_ISDIR(sb.st_mode)) | |
117 | + return NULL; | |
118 | + if ((sb.st_mode & S_IRUSR) == 0) | |
119 | + return NULL; | |
120 | + | |
121 | + fd = open(path, O_RDONLY); | |
122 | + if (fd < 0) { | |
123 | + uc_error("sysfs open failed for '%s' (%d)", path, errno); | |
124 | + return NULL; | |
125 | + } | |
126 | + len = read(fd, path, sizeof(path)-1); | |
127 | + close(fd); | |
128 | + if (len < 0) { | |
129 | + uc_error("sysfs unable to read value '%s' (%d)", path, errno); | |
130 | + return NULL; | |
131 | + } | |
132 | + while (len > 0 && path[len-1] == '\n') | |
133 | + len--; | |
134 | + path[len] = '\0'; | |
135 | + return strdup(path); | |
136 | +} | |
137 | + | |
86 | 138 | #define MATCH_VARIABLE(name, id, fcn) \ |
87 | 139 | if (strncmp((name), (id), sizeof(id) - 1) == 0) { \ |
88 | 140 | rval = fcn(uc_mgr); \ |
@@ -133,6 +185,7 @@ int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr, | ||
133 | 185 | MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname); |
134 | 186 | MATCH_VARIABLE(value, "${CardComponents}", rval_card_components); |
135 | 187 | MATCH_VARIABLE2(value, "${env:", rval_env); |
188 | + MATCH_VARIABLE2(value, "${sys:", rval_sysfs); | |
136 | 189 | err = -EINVAL; |
137 | 190 | tmp = strchr(value, '}'); |
138 | 191 | if (tmp) { |