diff options
Diffstat (limited to 'snd_utils.c')
-rw-r--r-- | snd_utils.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/snd_utils.c b/snd_utils.c new file mode 100644 index 0000000..2c244cc --- /dev/null +++ b/snd_utils.c @@ -0,0 +1,149 @@ +/* snd_utils.c +** +** Copyright (c) 2019, The Linux Foundation. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above +** copyright notice, this list of conditions and the following +** disclaimer in the documentation and/or other materials provided +** with the distribution. +** * Neither the name of The Linux Foundation nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**/ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "snd_utils.h" + +#define SND_DLSYM(h, p, s, err) \ +do { \ + err = 0; \ + p = dlsym(h, s); \ + if (!p) \ + err = -ENODEV; \ +} while(0) + +int snd_utils_get_int(struct snd_node *node, const char *prop, int *val) +{ + if (!node || !node->card_node || !node->dev_node) + return SND_NODE_TYPE_HW; + + return node->get_int(node->dev_node, prop, val); +} + +int snd_utils_get_str(struct snd_node *node, const char *prop, char **val) +{ + if (!node || !node->card_node || !node->dev_node) + return SND_NODE_TYPE_HW; + + return node->get_str(node->dev_node, prop, val); +} + +void snd_utils_put_dev_node(struct snd_node *node) +{ + if (!node) + return; + + if (node->card_node) + node->put_card(node->card_node); + + if (node->dl_hdl) + dlclose(node->dl_hdl); + + free(node); +} + +enum snd_node_type snd_utils_get_node_type(struct snd_node *node) +{ + int val = SND_NODE_TYPE_HW; + + if (!node || !node->card_node || !node->dev_node) + return SND_NODE_TYPE_HW; + + node->get_int(node->dev_node, "type", &val); + + return val; +}; + + +static int snd_utils_resolve_symbols(struct snd_node *node) +{ + void *dl = node->dl_hdl; + int err; + + SND_DLSYM(dl, node->get_card, "snd_card_def_get_card", err); + if (err) + goto done; + SND_DLSYM(dl, node->put_card, "snd_card_def_put_card", err); + if (err) + goto done; + SND_DLSYM(dl, node->get_node, "snd_card_def_get_node", err); + if (err) + goto done; + SND_DLSYM(dl, node->get_int, "snd_card_def_get_int", err); + if (err) + goto done; + SND_DLSYM(dl, node->get_str, "snd_card_def_get_str", err); + +done: + return err; +} + +struct snd_node *snd_utils_get_dev_node(unsigned int card, + unsigned int device, int dev_type) +{ + struct snd_node *node; + int rc = 0; + + node = calloc(1, sizeof(*node)); + if (!node) + return NULL; + + node->dl_hdl = dlopen("libsndcardparser.so", RTLD_NOW); + if (!node->dl_hdl) { + goto err_dl_open; + } + + rc = snd_utils_resolve_symbols(node); + if (rc < 0) + goto err_resolve_symbols; + + node->card_node = node->get_card(card); + if (!node->card_node) + goto err_resolve_symbols; + + node->dev_node = node->get_node(node->card_node, + device, dev_type); + if (!node->dev_node) + goto err_get_node; + + return node; + +err_get_node: + node->put_card(node->card_node); + +err_resolve_symbols: + dlclose(node->dl_hdl); + +err_dl_open: + free(node); + return NULL; +} |