]> git.alsa-project.org Git - alsa-gobject.git/commitdiff
utils: add utilities to request control ioctl
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Sat, 2 Apr 2022 01:46:22 +0000 (10:46 +0900)
committer坂本 貴史 <o-takashi@sakamocchi.jp>
Sat, 2 Apr 2022 13:19:28 +0000 (22:19 +0900)
In ALSA HwDep and RawMidi interface, some functions are implemented via
ALSA control character device.

This commit adds utility to perform ioctl in ALSA control character device
for the purpose.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
src/hwdep/query.c
src/rawmidi/query.c
src/utils/ioctl.c [new file with mode: 0644]
src/utils/meson.build
src/utils/utils.h

index f2e61c3934974047c4d2f7bc2f13240730090760..5793467292fbce4095fe8813c314531dd4eb92e2 100644 (file)
@@ -3,11 +3,7 @@
 
 #include <utils.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <sys/ioctl.h>
-#include <unistd.h>
 
 /**
  * SECTION: query
@@ -96,35 +92,6 @@ void alsahwdep_get_hwdep_devnode(guint card_id, guint device_id,
         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)
-{
-    char *devname;
-    int fd;
-    int err;
-
-    g_return_if_fail(error == NULL || *error == NULL);
-
-    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(devname, O_RDONLY | O_NONBLOCK);
-    if (fd < 0) {
-        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);
-
-       close(fd);
-end:
-    free(devname);
-}
-
 /**
  * alsahwdep_get_device_info:
  * @card_id: The numberical value for sound card to query.
@@ -142,6 +109,7 @@ void alsahwdep_get_device_info(guint card_id, guint device_id,
                                GError **error)
 {
     struct snd_hwdep_info *info;
+    int err;
 
     g_return_if_fail(device_info != NULL);
     g_return_if_fail(error == NULL || *error == NULL);
@@ -151,7 +119,9 @@ void alsahwdep_get_device_info(guint card_id, guint device_id,
 
     info->device = device_id;
     info->card = card_id;
-    hwdep_perform_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_HWDEP_INFO, info, "HWDEP_INFO", error);
-    if (*error != NULL)
+    err = request_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_HWDEP_INFO, info);
+    if (err < 0) {
+        generate_file_error(error, -err, "ioctl(HWDEP_INFO)");
         g_object_unref(*device_info);
+    }
 }
index 8b0e58275923fcf81d0643122b7fdae9cfd42451..0be13f2b07ae06c0a17ee186137e16b6e8d62a49 100644 (file)
@@ -3,11 +3,7 @@
 
 #include <utils.h>
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <sys/ioctl.h>
-#include <unistd.h>
 
 /**
  * SECTION: query
@@ -96,37 +92,6 @@ void alsarawmidi_get_rawmidi_devnode(guint card_id, guint device_id,
         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)
-{
-    char *devname;
-    int fd;
-    int err;
-
-    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(devname, O_RDONLY);
-    if (fd < 0) {
-        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);
-
-    // The caller is responsible for closing the file descriptor.
-    if (ctl_fd != NULL)
-        *ctl_fd = fd;
-    else
-        close(fd);
-end:
-    free(devname);
-}
-
 /**
  * alsarawmidi_get_subdevice_id_list:
  * @card_id: The numberical value for sound card to query.
@@ -155,14 +120,17 @@ void alsarawmidi_get_subdevice_id_list(guint card_id, guint device_id,
         .subdevice = 0,
     };
     int i;
+    int err;
 
     g_return_if_fail(entries != NULL);
     g_return_if_fail(entry_count != NULL);
     g_return_if_fail(error == NULL || *error == NULL);
 
-    rawmidi_perform_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_INFO, &info, "RAWMIDI_INFO", NULL, error);
-    if (*error != NULL)
+    err = request_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_INFO, &info);
+    if (err < 0) {
+        generate_file_error(error, -err, "RAWMIDI_INFO");
         return;
+    }
 
     *entries = g_malloc0_n(info.subdevices_count, sizeof(guint));
 
@@ -193,6 +161,7 @@ void alsarawmidi_get_substream_info(guint card_id, guint device_id,
                                     GError **error)
 {
     struct snd_rawmidi_info *info;
+    int err;
 
     g_return_if_fail(substream_info != NULL);
     g_return_if_fail(error == NULL || *error == NULL);
@@ -205,14 +174,19 @@ void alsarawmidi_get_substream_info(guint card_id, guint device_id,
     info->stream = direction;
     info->card = card_id;
 
-    rawmidi_perform_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_INFO, info, "RAWMIDI_INFO", NULL, error);
-    if (*error != NULL)
+    err = request_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_INFO, info);
+    if (err < 0) {
         g_object_unref(*substream_info);
+        generate_file_error(error, -err, "RAWMIDI_INFO");
+    }
 }
 
 void rawmidi_select_subdevice(guint card_id, guint subdevice_id, int *ctl_fd, GError **error)
 {
     guint data = subdevice_id;
-    rawmidi_perform_ctl_ioctl(card_id, SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE,
-                              &data, "RAWMIDI_PREFER_SUBDEVICE", ctl_fd, error);
+    int err;
+
+    err = request_ctl_ioctl_opened(ctl_fd, card_id, SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE, &data);
+    if (err < 0)
+        generate_file_error(error, -err, "RAWMIDI_PREFER_SUBDEVICE");
 }
diff --git a/src/utils/ioctl.c b/src/utils/ioctl.c
new file mode 100644 (file)
index 0000000..f985cd6
--- /dev/null
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+#include "utils.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+int request_ctl_ioctl_opened(int *fd, unsigned int card_id, long request, void *data)
+{
+    char *devname;
+    int err;
+
+    if (fd == NULL)
+        return -EINVAL;
+
+    err = lookup_and_allocate_control_devname(&devname, card_id);
+    if (err < 0)
+        return err;
+
+    *fd = open(devname, O_RDONLY | O_NONBLOCK);
+    free(devname);
+    if (*fd < 0)
+        return -errno;
+
+    if (ioctl(*fd, request, data) < 0)
+        return -errno;
+
+    return 0;
+}
+
+int request_ctl_ioctl(unsigned int card_id, long request, void *data)
+{
+    int fd;
+    int err;
+
+    err = request_ctl_ioctl_opened(&fd, card_id, request, data);
+    close(fd);
+
+    return err;
+}
index d418eaf324eb83dec2e4459934fc725541b4c7e6..b23d8dfbbd9fb78361311dfca9d65f7c87a32ec7 100644 (file)
@@ -5,6 +5,7 @@ headers = [
 sources = [
   'string.c',
   'sysfs.c',
+  'ioctl.c',
 ]
 
 dependencies = [
index a3861d616b13098704aff4435043b9f26cddde35..67ba1cff75744666a349dd689b4eed58e409a00a 100644 (file)
@@ -28,6 +28,9 @@ int lookup_and_allocate_string_by_sysname(char **name, const char *sysname,
 int generate_sysnum_list_by_sysname_prefix(unsigned int **entries, unsigned long *entry_count,
                                            const char *prefix);
 
+int request_ctl_ioctl_opened(int *fd, unsigned int card_id, long request, void *data);
+int request_ctl_ioctl(unsigned int card_id, long request, void *data);
+
 static inline int lookup_and_allocate_name_by_sysname(char **name,
                                                       const char *(*func)(struct udev_device *),
                                                       const char *fmt, va_list ap)