From 01d4559362c3849d1a04b67c2a7c4d22e901317e Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sat, 2 Apr 2022 10:46:22 +0900 Subject: [PATCH] utils: add utilities to allocate string information for device It's typically used to look for string information over sysfs according to sysname. This commit adds utilities for it. Signed-off-by: Takashi Sakamoto --- src/ctl/query.c | 115 +++++---------------------------------- src/hwdep/query.c | 123 ++++++++---------------------------------- src/rawmidi/query.c | 117 +++++++--------------------------------- src/seq/query.c | 82 ++++++---------------------- src/timer/query.c | 85 +++++------------------------ src/utils/meson.build | 2 + src/utils/string.c | 31 ++++++++++- src/utils/sysfs.c | 45 ++++++++++++++++ src/utils/utils.h | 117 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 277 insertions(+), 440 deletions(-) create mode 100644 src/utils/sysfs.c diff --git a/src/ctl/query.c b/src/ctl/query.c index 373b69d..a06b8dc 100644 --- a/src/ctl/query.c +++ b/src/ctl/query.c @@ -17,9 +17,6 @@ * descriptor */ -#define CARD_SYSNAME_TEMPLATE "card%u" -#define CONTROL_SYSNAME_TEMPLATE "controlC%u" - #define generate_file_error(exception, errno, msg) \ g_set_error_literal(exception, G_FILE_ERROR, g_file_error_from_errno(errno), msg) @@ -173,52 +170,6 @@ end: release_udev_enum(enumerator); } -static void allocate_sysname(char **sysname ,const char *template, - guint card_id, GError **error) -{ - unsigned int digits; - unsigned int number; - unsigned int length; - - digits = 0; - number = card_id; - while (number > 0) { - number /= 10; - ++digits; - } - - length = strlen(template) + digits; - *sysname = g_malloc0(length + 1); - - snprintf(*sysname, length, template, card_id); -} - -static bool check_existence(char *sysname, GError **error) -{ - struct udev *ctx; - struct udev_device *dev; - bool result; - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - return false; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); - if (dev == NULL) { - generate_file_error(error, errno, "udev_device_new_from_subsystem_sysname()"); - result = false; - } else { - result = true; - } - udev_device_unref(dev); - - udev_unref(ctx); - - return result; -} - /** * alsactl_get_card_sysname: * @card_id: The numeridcal ID of sound card. @@ -231,21 +182,14 @@ static bool check_existence(char *sysname, GError **error) */ void alsactl_get_card_sysname(guint card_id, char **sysname, GError **error) { - char *name; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - allocate_sysname(&name, CARD_SYSNAME_TEMPLATE, card_id, error); - if (*error != NULL) - return; - - if (!check_existence(name, error)) { - g_free(name); - return; - } - - *sysname = name; + err = lookup_and_allocate_card_sysname(sysname, card_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate card sysname"); } /** @@ -261,21 +205,14 @@ void alsactl_get_card_sysname(guint card_id, char **sysname, GError **error) */ void alsactl_get_control_sysname(guint card_id, char **sysname, GError **error) { - char *name; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - allocate_sysname(&name, CONTROL_SYSNAME_TEMPLATE, card_id, error); - if (*error != NULL) - return; - - if (!check_existence(name, error)) { - g_free(name); - return; - } - - *sysname = name; + err = lookup_and_allocate_control_sysname(sysname, card_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate control sysname"); } /** @@ -291,40 +228,12 @@ void alsactl_get_control_sysname(guint card_id, char **sysname, GError **error) */ void alsactl_get_control_devnode(guint card_id, char **devnode, GError **error) { - char *sysname; - struct udev *ctx; - struct udev_device *dev; - const char *node; + int err; g_return_if_fail(devnode != NULL); g_return_if_fail(error == NULL || *error == NULL); - allocate_sysname(&sysname, CONTROL_SYSNAME_TEMPLATE, card_id, error); - if (*error != NULL) - return; - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - g_free(sysname); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - g_free(sysname); - udev_unref(ctx); - return; - } - g_free(sysname); - - node = udev_device_get_devnode(dev); - if (node != NULL) - *devnode = g_strdup(node); - else - generate_file_error(error, ENODEV, "udev_device_get_devnode()"); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_control_devname(devnode, card_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate control devname"); } diff --git a/src/hwdep/query.c b/src/hwdep/query.c index c345a87..942c18c 100644 --- a/src/hwdep/query.c +++ b/src/hwdep/query.c @@ -23,8 +23,6 @@ // 'C' is required apart from emulation of Open Sound System. #define PREFIX_SYSNAME_TEMPLATE "hwC%u" -#define HWDEP_SYSNAME_TEMPLATE "hwC%uD%u" -#define CTL_SYSNAME_TEMPLATE "controlC%u" #define generate_file_error(error, errno, msg) \ g_set_error_literal(error, G_FILE_ERROR, g_file_error_from_errno(errno), msg) @@ -218,37 +216,14 @@ end: void alsahwdep_get_hwdep_sysname(guint card_id, guint device_id, char **sysname, GError **error) { - unsigned int length; - char *name; - struct udev *ctx; - struct udev_device *dev; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - length = strlen(HWDEP_SYSNAME_TEMPLATE) + calculate_digits(card_id) + - calculate_digits(device_id) + 1; - name = g_malloc0(length); - - snprintf(name, length, HWDEP_SYSNAME_TEMPLATE, card_id, device_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - g_free(name); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", name); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - g_free(name); - } else { - *sysname = name; - udev_device_unref(dev); - } - - udev_unref(ctx); + err = lookup_and_allocate_hwdep_sysname(sysname, card_id, device_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate hwdep sysname"); } /** @@ -265,95 +240,43 @@ void alsahwdep_get_hwdep_sysname(guint card_id, guint device_id, void alsahwdep_get_hwdep_devnode(guint card_id, guint device_id, char **devnode, GError **error) { - unsigned int length; - char *name; - struct udev *ctx; - struct udev_device *dev; - const char *node; + int err; g_return_if_fail(devnode != NULL); g_return_if_fail(error == NULL || *error == NULL); - length = strlen(HWDEP_SYSNAME_TEMPLATE) + calculate_digits(card_id) + - calculate_digits(device_id) + 1; - name = g_malloc0(length); - - snprintf(name, length, HWDEP_SYSNAME_TEMPLATE, card_id, device_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - g_free(name); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", name); - g_free(name); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - udev_unref(ctx); - return; - } - - node = udev_device_get_devnode(dev); - if (node == NULL) - generate_file_error(error, ENOENT, "udev_device_get_devnode()"); - else - *devnode = g_strdup(node); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_hwdep_devname(devnode, card_id, device_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate hwdep devname"); } static void hwdep_perform_ctl_ioctl(guint card_id, long request, void *data, const char *req_label, GError **error) { - unsigned int length; - char *sysname; - struct udev *ctx; - struct udev_device *dev; - const char *devnode; + char *devname; int fd; + int err; - length = strlen(CTL_SYSNAME_TEMPLATE) + calculate_digits(card_id) + 1; - sysname = g_malloc0(length); - - snprintf(sysname, length, CTL_SYSNAME_TEMPLATE, card_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - goto err_sysname; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); - if (dev == NULL) { - generate_file_error(error, errno, "udev_device_new_from_subsystem_sysname()"); - goto err_ctx; - } + g_return_if_fail(error == NULL || *error == NULL); - devnode = udev_device_get_devnode(dev); - if (devnode == NULL) { - generate_file_error(error, ENODEV, "udev_device_get_devnode()"); - goto err_device; + err = lookup_and_allocate_control_devname(&devname, card_id); + if (err < 0) { + generate_file_error(error, -err, "Fail to generate control devname"); + return; } - fd = open(devnode, O_RDONLY | O_NONBLOCK); + fd = open(devname, O_RDONLY | O_NONBLOCK); if (fd < 0) { - generate_file_error_fmt(error, errno, "open(%s)", devnode); - goto err_device; + generate_file_error_fmt(error, errno, "open(%s)", devname); + goto end; } - if (ioctl(fd, request, data) < 0) - generate_file_error_fmt(error, errno, "ioctl(%s)", req_label); + if (ioctl(fd, request, data) < 0) + generate_file_error_fmt(error, errno, "ioctl(%s)", req_label); - close(fd); -err_device: - udev_device_unref(dev); -err_ctx: - udev_unref(ctx); -err_sysname: - g_free(sysname); + close(fd); +end: + free(devname); } /** diff --git a/src/rawmidi/query.c b/src/rawmidi/query.c index e078b39..a4db8c1 100644 --- a/src/rawmidi/query.c +++ b/src/rawmidi/query.c @@ -23,8 +23,6 @@ // 'C' is required apart from emulation of Open Sound System. #define PREFIX_SYSNAME_TEMPLATE "midiC%u" -#define RAWMIDI_SYSNAME_TEMPLATE "midiC%uD%u" -#define CTL_SYSNAME_TEMPLATE "controlC%u" #define generate_file_error(error, errno, msg) \ g_set_error_literal(error, G_FILE_ERROR, g_file_error_from_errno(errno), msg) @@ -218,37 +216,14 @@ end: void alsarawmidi_get_rawmidi_sysname(guint card_id, guint device_id, char **sysname, GError **error) { - unsigned int length; - char *name; - struct udev *ctx; - struct udev_device *dev; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - length = strlen(RAWMIDI_SYSNAME_TEMPLATE) + calculate_digits(card_id) + - calculate_digits(device_id) + 1; - name = g_malloc0(length); - - snprintf(name, length, RAWMIDI_SYSNAME_TEMPLATE, card_id, device_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - g_free(name); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", name); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - g_free(name); - } else { - *sysname = name; - udev_device_unref(dev); - } - - udev_unref(ctx); + err = lookup_and_allocate_rawmidi_sysname(sysname, card_id, device_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate rawmidi sysname"); } /** @@ -265,83 +240,33 @@ void alsarawmidi_get_rawmidi_sysname(guint card_id, guint device_id, void alsarawmidi_get_rawmidi_devnode(guint card_id, guint device_id, char **devnode, GError **error) { - unsigned int length; - char *name; - struct udev *ctx; - struct udev_device *dev; - const char *node; + int err; g_return_if_fail(devnode != NULL); g_return_if_fail(error == NULL || *error == NULL); - length = strlen(RAWMIDI_SYSNAME_TEMPLATE) + calculate_digits(card_id) + - calculate_digits(device_id) + 1; - name = g_malloc0(length); - - snprintf(name, length, RAWMIDI_SYSNAME_TEMPLATE, card_id, device_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - g_free(name); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", name); - g_free(name); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - udev_unref(ctx); - return; - } - - node = udev_device_get_devnode(dev); - if (node == NULL) - generate_file_error(error, ENOENT, "udev_device_get_devnode()"); - else - *devnode = g_strdup(node); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_rawmidi_devname(devnode, card_id, device_id); + if (err < 0) + generate_file_error(error, -err, "Fail to generate rawmidi devname"); } static void rawmidi_perform_ctl_ioctl(guint card_id, long request, void *data, const char *req_label, int *ctl_fd, GError **error) { - unsigned int length; - char *sysname; - struct udev *ctx; - struct udev_device *dev; - const char *devnode; + char *devname; int fd; + int err; - length = strlen(CTL_SYSNAME_TEMPLATE) + calculate_digits(card_id) + 1; - sysname = g_malloc0(length); - - snprintf(sysname, length, CTL_SYSNAME_TEMPLATE, card_id); - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - goto err_sysname; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); - if (dev == NULL) { - generate_file_error(error, errno, "udev_device_new_from_subsystem_sysname()"); - goto err_ctx; - } - - devnode = udev_device_get_devnode(dev); - if (devnode == NULL) { - generate_file_error(error, ENODEV, "udev_device_get_devnode()"); - goto err_device; + err = lookup_and_allocate_control_devname(&devname, card_id); + if (err < 0) { + generate_file_error(error, -err, "Fail to generate control devname"); + return; } - fd = open(devnode, O_RDONLY); + fd = open(devname, O_RDONLY); if (fd < 0) { - generate_file_error_fmt(error, errno, "open(%s)", devnode); - goto err_device; + generate_file_error_fmt(error, errno, "open(%s)", devname); + goto end; } if (ioctl(fd, request, data) < 0) @@ -352,12 +277,8 @@ static void rawmidi_perform_ctl_ioctl(guint card_id, long request, void *data, *ctl_fd = fd; else close(fd); -err_device: - udev_device_unref(dev); -err_ctx: - udev_unref(ctx); -err_sysname: - g_free(sysname); +end: + free(devname); } /** diff --git a/src/seq/query.c b/src/seq/query.c index da95689..09b640b 100644 --- a/src/seq/query.c +++ b/src/seq/query.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #include "privates.h" +#include "utils.h" #include #include @@ -18,8 +19,6 @@ * descriptor */ -#define SEQ_SYSNAME "seq" - #define generate_file_error(exception, errno, msg) \ g_set_error_literal(exception, G_FILE_ERROR, g_file_error_from_errno(errno), msg) @@ -37,38 +36,14 @@ */ void alsaseq_get_seq_sysname(gchar **sysname, GError **error) { - struct udev *ctx; - struct udev_device *dev; - const char *name; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", SEQ_SYSNAME); - if (dev == NULL) { - generate_file_error(error, errno, "udev_enumerate_new()"); - udev_unref(ctx); - return; - } - - name = udev_device_get_sysname(dev); - if (name == NULL) { - generate_file_error(error, errno, "udev_enumerate_add_match_subsystem()"); - udev_device_unref(dev); - udev_unref(ctx); - return; - } - - *sysname = g_strdup(name); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_seq_sysname(sysname); + if (err < 0) + generate_file_error(error, -err, "Fail to generate seq sysname"); } /** @@ -82,56 +57,29 @@ void alsaseq_get_seq_sysname(gchar **sysname, GError **error) */ void alsaseq_get_seq_devnode(gchar **devnode, GError **error) { - struct udev *ctx; - struct udev_device *dev; - const char *node; + int err; g_return_if_fail(devnode != NULL); g_return_if_fail(error == NULL || *error == NULL); - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", SEQ_SYSNAME); - if (dev == NULL) { - generate_file_error(error, errno, "udev_device_new_from_subsystem_sysname()"); - udev_unref(ctx); - return; - } - - node = udev_device_get_devnode(dev); - if (node == NULL) { - generate_file_error(error, ENODEV, "udev_device_get_devnode()"); - udev_device_unref(dev); - udev_unref(ctx); - return; - } - - *devnode = g_strdup(node); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_seq_devname(devnode); + if (err < 0) + generate_file_error(error, -err, "Fail to generate seq devname"); } static int open_fd(GError **error) { - char *devnode; + char *devname; int fd; - alsaseq_get_seq_devnode(&devnode, error); + alsaseq_get_seq_devnode(&devname, error); if (*error != NULL) return -1; - fd = open(devnode, O_RDONLY); - if (fd < 0) { - generate_file_error_fmt(error, errno, "open(%s)", devnode); - g_free(devnode); - return -1; - } - g_free(devnode); + fd = open(devname, O_RDONLY); + if (fd < 0) + generate_file_error_fmt(error, errno, "open(%s)", devname); + g_free(devname); return fd; } diff --git a/src/timer/query.c b/src/timer/query.c index 38904e9..d7e80bf 100644 --- a/src/timer/query.c +++ b/src/timer/query.c @@ -24,7 +24,6 @@ * file descriptor */ -#define TIMER_SYSNAME_TEMPLATE "timer" #define SYSFS_SND_TIMER_NODE "/sys/module/snd_timer/" #define generate_file_error(exception, errno, msg) \ @@ -33,32 +32,6 @@ #define generate_file_error_fmt(exception, errno, fmt, msg) \ g_set_error(exception, G_FILE_ERROR, g_file_error_from_errno(errno), fmt, msg) -static bool check_existence(char *sysname, GError **error) -{ - struct udev *ctx; - struct udev_device *dev; - bool result; - - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - return false; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", sysname); - if (dev == NULL) { - generate_file_error(error, errno, "udev_device_new_from_subsystem_sysname()"); - result = false; - } else { - result = true; - } - udev_device_unref(dev); - - udev_unref(ctx); - - return result; -} - /** * alsatimer_get_sysname: * @sysname: (out): The string for sysname of ALSA Timer. @@ -70,19 +43,14 @@ static bool check_existence(char *sysname, GError **error) */ void alsatimer_get_sysname(char **sysname, GError **error) { - char *name; + int err; g_return_if_fail(sysname != NULL); g_return_if_fail(error == NULL || *error == NULL); - name = g_strdup(TIMER_SYSNAME_TEMPLATE); - - if (!check_existence(name, error)) { - g_free(name); - return; - } - - *sysname = name; + err = lookup_and_allocate_timer_sysname(sysname); + if (err < 0) + generate_file_error(error, -err, "Fail to generate timer sysname"); } /** @@ -96,54 +64,29 @@ void alsatimer_get_sysname(char **sysname, GError **error) */ void alsatimer_get_devnode(char **devnode, GError **error) { - struct udev *ctx; - struct udev_device *dev; - const char *node; + int err; g_return_if_fail(devnode != NULL); g_return_if_fail(error == NULL || *error == NULL); - ctx = udev_new(); - if (ctx == NULL) { - generate_file_error(error, errno, "udev_new()"); - return; - } - - dev = udev_device_new_from_subsystem_sysname(ctx, "sound", - TIMER_SYSNAME_TEMPLATE); - if (dev == NULL) { - generate_file_error(error, ENODEV, "udev_device_new_from_subsystem_sysname()"); - udev_unref(ctx); - return; - } - - node = udev_device_get_devnode(dev); - if (node != NULL) - *devnode = g_strdup(node); - else - generate_file_error(error, ENODEV, "udev_device_get_devnode()"); - - udev_device_unref(dev); - udev_unref(ctx); + err = lookup_and_allocate_timer_devname(devnode); + if (err < 0) + generate_file_error(error, -err, "Fail to generate timer devname"); } static int open_fd(GError **error) { - char *devnode; + char *devname; int fd; - alsatimer_get_devnode(&devnode, error); + alsatimer_get_devnode(&devname, error); if (*error != NULL) return -1; - fd = open(devnode, O_RDONLY); - if (fd < 0) { - generate_file_error_fmt(error, errno, "open(%s)", devnode); - g_free(devnode); - return -1; - } - - g_free(devnode); + fd = open(devname, O_RDONLY); + if (fd < 0) + generate_file_error_fmt(error, errno, "open(%s)", devname); + g_free(devname); return fd; } diff --git a/src/utils/meson.build b/src/utils/meson.build index 20cf8d0..d418eaf 100644 --- a/src/utils/meson.build +++ b/src/utils/meson.build @@ -4,9 +4,11 @@ headers = [ sources = [ 'string.c', + 'sysfs.c', ] dependencies = [ + dependency('libudev'), ] static_library = static_library('utils', diff --git a/src/utils/string.c b/src/utils/string.c index 72689de..fe0ab13 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -#include +#include "utils.h" + #include +#include long long_from_string(const char *literal, long *number) { @@ -16,3 +18,30 @@ long long_from_string(const char *literal, long *number) *number = val; return 0; } + +int allocate_string(char **dst, const char *template, va_list ap) +{ + char *label; + int size; + va_list aq; + + va_copy(aq, ap); + size = vsnprintf(NULL, 0, template, aq); + va_end(aq); + + if (size < 0) + return -EINVAL; + size += 1; + + label = malloc(size); + if (label == NULL) + return -ENOMEM; + + va_copy(aq, ap); + vsnprintf(label, size, template, aq); + va_end(aq); + + *dst = label; + + return 0; +} diff --git a/src/utils/sysfs.c b/src/utils/sysfs.c new file mode 100644 index 0000000..d7d8306 --- /dev/null +++ b/src/utils/sysfs.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "utils.h" + +#include +#include +#include + +#define SOUND_SUBSYSTEM "sound" + +int lookup_and_allocate_string_by_sysname(char **name, const char *sysname, + const char *(*func)(struct udev_device *)) +{ + struct udev *ctx; + struct udev_device *device; + const char *n; + int err = 0; + + if (name == NULL || sysname == NULL || func == NULL) + return -EINVAL; + + ctx = udev_new(); + if (ctx == NULL) + return -errno; + + device = udev_device_new_from_subsystem_sysname(ctx, SOUND_SUBSYSTEM, sysname); + if (device == NULL) { + err = -errno; + goto err_ctx; + } + + n = func(device); + if (n == NULL) { + err = -errno; + goto err_dev; + } + + *name = strdup(n); + if (*name == NULL) + err = -ENOMEM; +err_dev: + udev_device_unref(device); +err_ctx: + udev_unref(ctx); + return err; +} diff --git a/src/utils/utils.h b/src/utils/utils.h index 4325785..051e30d 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -2,6 +2,123 @@ #ifndef __ALSA_GOBJECT_UTILS_H__ #define __ALSA_GOBJECT_UTILS_H__ +#include +#include +#include + +#define CARD_SYSNAME_TEMPLATE "card%u" +#define CONTROL_SYSNAME_TEMPLATE "controlC%u" +#define RAWMIDI_SYSNAME_TEMPLATE "midiC%uD%u" +#define HWDEP_SYSNAME_TEMPLATE "hwC%uD%u" +#define TIMER_SYSNAME "timer" +#define SEQ_SYSNAME "seq" + long long_from_string(const char *literal, long *number); +int allocate_string(char **dst, const char *template, va_list ap); + +int lookup_and_allocate_string_by_sysname(char **name, const char *sysname, + const char *(*func)(struct udev_device *)); + +static inline int lookup_and_allocate_name_by_sysname(char **name, + const char *(*func)(struct udev_device *), + const char *fmt, va_list ap) +{ + char *sysname; + int err; + + err = allocate_string(&sysname, fmt, ap); + if (err >= 0) + err = lookup_and_allocate_string_by_sysname(name, sysname, func); + free(sysname); + return err; +} + +static inline int lookup_and_allocate_sysname_by_sysname(char **sysname, const char *fmt, ...) +{ + va_list ap; + int err; + + va_start(ap, fmt); + err = lookup_and_allocate_name_by_sysname(sysname, udev_device_get_sysname, fmt, ap); + va_end(ap); + + return err; +} + +static inline int lookup_and_allocate_devname_by_sysname(char **devname, const char *fmt, ...) +{ + va_list ap; + int err; + + va_start(ap, fmt); + err = lookup_and_allocate_name_by_sysname(devname, udev_device_get_devnode, fmt, ap); + va_end(ap); + + return err; +} + +static inline int lookup_and_allocate_card_sysname(char **sysname, unsigned int card_id) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, CARD_SYSNAME_TEMPLATE, card_id); +} + +static inline int lookup_and_allocate_control_sysname(char **sysname, unsigned int card_id) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, CONTROL_SYSNAME_TEMPLATE, card_id); +} + +static inline int lookup_and_allocate_control_devname(char **devname, unsigned int card_id) +{ + return lookup_and_allocate_devname_by_sysname(devname, CONTROL_SYSNAME_TEMPLATE, card_id); +} + +static inline int lookup_and_allocate_hwdep_sysname(char **sysname, unsigned int card_id, + unsigned int device_id) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, HWDEP_SYSNAME_TEMPLATE, card_id, + device_id); +} + +static inline int lookup_and_allocate_hwdep_devname(char **devname, unsigned int card_id, + unsigned int device_id) +{ + return lookup_and_allocate_devname_by_sysname(devname, HWDEP_SYSNAME_TEMPLATE, card_id, + device_id); +} + +static inline int lookup_and_allocate_rawmidi_sysname(char **sysname, unsigned int card_id, + unsigned int device_id) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, RAWMIDI_SYSNAME_TEMPLATE, card_id, + device_id); +} + +static inline int lookup_and_allocate_rawmidi_devname(char **devname, unsigned int card_id, + unsigned int device_id) +{ + return lookup_and_allocate_devname_by_sysname(devname, RAWMIDI_SYSNAME_TEMPLATE, card_id, + device_id); +} + +static inline int lookup_and_allocate_timer_sysname(char **sysname) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, TIMER_SYSNAME); +} + +static inline int lookup_and_allocate_timer_devname(char **devname) +{ + return lookup_and_allocate_devname_by_sysname(devname, TIMER_SYSNAME); +} + +static inline int lookup_and_allocate_seq_sysname(char **sysname) +{ + return lookup_and_allocate_sysname_by_sysname(sysname, SEQ_SYSNAME); +} + +static inline int lookup_and_allocate_seq_devname(char **devname) +{ + return lookup_and_allocate_devname_by_sysname(devname, SEQ_SYSNAME); +} + #endif -- 2.47.3