summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2020-06-07 18:25:41 +0200
committerTanu Kaskinen <tanuk@iki.fi>2020-09-17 14:52:50 +0000
commitc1a7e3c59d5e2dcb6ca95c66d74c0ca7a45395d9 (patch)
tree08b448e956feaa7e1094e0badbdd2396848e6b17
parentb72724369b8d04057c53720969678a168c449d70 (diff)
downloadpulseaudio-c1a7e3c59d5e2dcb6ca95c66d74c0ca7a45395d9.tar.gz
ucm: add possibility to skip the UCM card completely (Linked)
We have a requirement to "hide" some hardware drivers, because other (main) UCM configuration will refer them. This patch use special error codes to notify the upper layers to skip the module loading. BugLink: https://github.com/alsa-project/alsa-ucm-conf/issues/30 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--src/modules/alsa/alsa-ucm.c20
-rw-r--r--src/modules/alsa/alsa-util.h7
-rw-r--r--src/modules/alsa/module-alsa-card.c10
-rw-r--r--src/modules/module-udev-detect.c14
-rw-r--r--src/pulsecore/module.c8
-rw-r--r--src/pulsecore/module.h5
6 files changed, 54 insertions, 10 deletions
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index b63ae364f..18925b792 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -757,13 +757,11 @@ static void append_lost_relationship(pa_alsa_ucm_device *dev) {
int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
char *card_name;
- const char **verb_list;
+ const char **verb_list, *value;
int num_verbs, i, err = 0;
/* support multiple card instances, address card directly by index */
card_name = pa_sprintf_malloc("hw:%i", card_index);
- if (card_name == NULL)
- return -ENOMEM;
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
if (err < 0) {
/* fallback longname: is UCM available for this card ? */
@@ -771,22 +769,36 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
err = snd_card_get_name(card_index, &card_name);
if (err < 0) {
pa_log("Card can't get card_name from card_index %d", card_index);
+ err = -PA_ALSA_ERR_UNSPECIFIED;
goto name_fail;
}
err = snd_use_case_mgr_open(&ucm->ucm_mgr, card_name);
if (err < 0) {
pa_log_info("UCM not available for card %s", card_name);
+ err = -PA_ALSA_ERR_UCM_OPEN;
goto ucm_mgr_fail;
}
}
+ err = snd_use_case_get(ucm->ucm_mgr, "=Linked", &value);
+ if (err >= 0) {
+ if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
+ free((void *)value);
+ pa_log_info("Empty (linked) UCM for card %s", card_name);
+ err = -PA_ALSA_ERR_UCM_LINKED;
+ goto ucm_verb_fail;
+ }
+ free((void *)value);
+ }
+
pa_log_info("UCM available for card %s", card_name);
/* get a list of all UCM verbs (profiles) for this card */
num_verbs = snd_use_case_verb_list(ucm->ucm_mgr, &verb_list);
if (num_verbs < 0) {
pa_log("UCM verb list not found for %s", card_name);
+ err = -PA_ALSA_ERR_UNSPECIFIED;
goto ucm_verb_fail;
}
@@ -806,7 +818,7 @@ int pa_alsa_ucm_query_profiles(pa_alsa_ucm_config *ucm, int card_index) {
if (!ucm->verbs) {
pa_log("No UCM verb is valid for %s", card_name);
- err = -1;
+ err = -PA_ALSA_ERR_UCM_NO_VERB;
}
snd_use_case_free_list(verb_list, num_verbs);
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 0d3d5af13..cb8be22fb 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -33,6 +33,13 @@
#include "alsa-mixer.h"
+enum {
+ PA_ALSA_ERR_UNSPECIFIED = 1,
+ PA_ALSA_ERR_UCM_OPEN = 1000,
+ PA_ALSA_ERR_UCM_NO_VERB = 1001,
+ PA_ALSA_ERR_UCM_LINKED = 1002
+};
+
int pa_alsa_set_hw_params(
snd_pcm_t *pcm_handle,
pa_sample_spec *ss, /* modified at return */
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index d312fb5d9..267d30c3b 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -785,6 +785,7 @@ int pa__init(pa_module *m) {
const char *profile_str = NULL;
char *fn = NULL;
bool namereg_fail = false;
+ int err = -PA_MODULE_ERR_UNSPECIFIED, rval;
pa_alsa_refcnt_inc();
@@ -841,7 +842,12 @@ int pa__init(pa_module *m) {
snd_config_update_free_global();
- if (u->use_ucm && !pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index)) {
+ rval = u->use_ucm ? pa_alsa_ucm_query_profiles(&u->ucm, u->alsa_card_index) : -1;
+ if (rval == -PA_ALSA_ERR_UCM_LINKED) {
+ err = -PA_MODULE_ERR_SKIP;
+ goto fail;
+ }
+ if (rval == 0) {
pa_log_info("Found UCM profiles");
u->profile_set = pa_alsa_ucm_add_profile_set(&u->ucm, &u->core->default_channel_map);
@@ -1009,7 +1015,7 @@ fail:
pa__done(m);
- return -1;
+ return err;
}
int pa__get_n_used(pa_module *m) {
diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index d119f96ae..7a107c44d 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -52,6 +52,7 @@ PA_MODULE_USAGE(
struct device {
char *path;
bool need_verify;
+ bool ignore;
char *card_name;
char *args;
uint32_t module;
@@ -286,6 +287,9 @@ static void verify_access(struct userdata *u, struct device *d) {
pa_assert(u);
pa_assert(d);
+ if (d->ignore)
+ return;
+
cd = pa_sprintf_malloc("/dev/snd/controlC%s", path_get_card_id(d->path));
accessible = access(cd, R_OK|W_OK) >= 0;
pa_log_debug("%s is accessible: %s", cd, pa_yes_no(accessible));
@@ -332,14 +336,20 @@ static void verify_access(struct userdata *u, struct device *d) {
* failure or a "fatal" failure. */
if (pa_ratelimit_test(&d->ratelimit, PA_LOG_DEBUG)) {
+ int err;
+
pa_log_debug("Loading module-alsa-card with arguments '%s'", d->args);
- pa_module_load(&m, u->core, "module-alsa-card", d->args);
+ err = pa_module_load(&m, u->core, "module-alsa-card", d->args);
if (m) {
d->module = m->index;
pa_log_info("Card %s (%s) module loaded.", d->path, d->card_name);
- } else
+ } else if (err == -PA_ERR_NOENTITY) {
+ pa_log_info("Card %s (%s) module skipped.", d->path, d->card_name);
+ d->ignore = true;
+ } else {
pa_log_info("Card %s (%s) failed to load module.", d->path, d->card_name);
+ }
} else
pa_log_warn("Tried to configure %s (%s) more often than %u times in %llus",
d->path,
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index 70b816072..15a54b6ec 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -116,7 +116,7 @@ int pa_module_load(pa_module** module, pa_core *c, const char *name, const char
bool (*load_once)(void);
const char* (*get_deprecated)(void);
pa_modinfo *mi;
- int errcode;
+ int errcode, rval;
pa_assert(module);
pa_assert(c);
@@ -188,7 +188,11 @@ int pa_module_load(pa_module** module, pa_core *c, const char *name, const char
pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0);
pa_assert(m->index != PA_IDXSET_INVALID);
- if (m->init(m) < 0) {
+ if ((rval = m->init(m)) < 0) {
+ if (rval == -PA_MODULE_ERR_SKIP) {
+ errcode = -PA_ERR_NOENTITY;
+ goto fail;
+ }
pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
errcode = -PA_ERR_IO;
goto fail;
diff --git a/src/pulsecore/module.h b/src/pulsecore/module.h
index b5a7fad77..f918ea605 100644
--- a/src/pulsecore/module.h
+++ b/src/pulsecore/module.h
@@ -30,6 +30,11 @@ typedef struct pa_module pa_module;
#include <pulsecore/core.h>
+enum {
+ PA_MODULE_ERR_UNSPECIFIED = 1,
+ PA_MODULE_ERR_SKIP = 2
+};
+
struct pa_module {
pa_core *core;
char *name, *argument;