aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--TODO1
-rw-r--r--common.h1
-rw-r--r--libgamepad.h9
-rw-r--r--libgamepad_find_sound_devices.c92
-rw-r--r--test-list.c11
6 files changed, 113 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 36e7dcc..a35fd79 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,7 @@ OBJ =\
libgamepad_create_attachment_monitor.o\
libgamepad_destroy_attachment_monitor.o\
libgamepad_disable_force_feedback_autocenter.o\
+ libgamepad_find_sound_devices.o\
libgamepad_get_absolute_axis_info.o\
libgamepad_get_absolute_axis_name.o\
libgamepad_get_attachment_event.o\
diff --git a/TODO b/TODO
index c0f54a0..fd8cdc5 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,5 @@
Add support for quirks
Add support for leds
-Add support for audio
Add support for accelerometer
Add support for creating instance from a file descriptor
Add man pages
diff --git a/common.h b/common.h
index 88acdf0..3cbe4ac 100644
--- a/common.h
+++ b/common.h
@@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include "libgamepad.h"
+#include <sys/stat.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
diff --git a/libgamepad.h b/libgamepad.h
index 5b6c46c..46a09e2 100644
--- a/libgamepad.h
+++ b/libgamepad.h
@@ -339,6 +339,15 @@ int libgamepad_open_superdevice(struct libgamepad_superdevice *, const char *);
*/
void libgamepad_close_superdevice(struct libgamepad_superdevice *);
+/**
+ * Search for sound devices built into or attached a device
+ *
+ * @param syspath The superdevice's path in /sys
+ * @param cardsp Output parameter for a list of sound card indices
+ * @return The number of found sound cards, -1 on failure
+ */
+ssize_t libgamepad_find_sound_devices(const char *, size_t **);
+
/**
* Create a device attachment monitor
diff --git a/libgamepad_find_sound_devices.c b/libgamepad_find_sound_devices.c
new file mode 100644
index 0000000..1688106
--- /dev/null
+++ b/libgamepad_find_sound_devices.c
@@ -0,0 +1,92 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+static int
+search(int dirfd, const char *file, size_t **cardsp, size_t *countp, struct stat *st_buf)
+{
+ int fd;
+ DIR *dir;
+ struct dirent *f;
+ unsigned long num;
+ char *end;
+ void *new;
+
+ fd = openat(dirfd, file, O_DIRECTORY);
+ if (fd < 0)
+ return -1;
+ dir = fdopendir(fd);
+ if (!dir) {
+ close(fd);
+ return -1;
+ }
+
+ if (!strcmp(file, "sound")) {
+ while (errno = 0, (f = readdir(dir))) {
+ if (strncmp(f->d_name, "card", 4) || !isdigit(f->d_name[4]))
+ continue;
+ num = strtoul(&f->d_name[4], &end, 10);
+ if (errno || *end)
+ continue;
+ if (*countp == (size_t)SSIZE_MAX)
+ break;
+ new = realloc(*cardsp, (*countp + 1) * sizeof(**cardsp));
+ if (!new)
+ goto fail;
+ *cardsp = new;
+ (*cardsp)[(*countp)++] = (size_t)num;
+ }
+ } else {
+ while (errno = 0, (f = readdir(dir))) {
+ if (f->d_name[0] == '.')
+ continue;
+ if (fstatat(fd, f->d_name, st_buf, AT_SYMLINK_NOFOLLOW))
+ goto fail;
+ if (S_ISLNK(st_buf->st_mode))
+ continue;
+ search(fd, f->d_name, cardsp, countp, st_buf);
+ }
+ }
+
+ closedir(dir);
+ return errno ? -1 : 0;
+
+fail:
+ closedir(dir);
+ return -1;
+}
+
+
+ssize_t
+libgamepad_find_sound_devices(const char *syspath, size_t **cardsp)
+{
+ int fd, i, saved_errno = errno;
+ size_t count = 0;
+ struct stat st;
+ const char *p = syspath;
+
+ *cardsp = NULL;
+
+ if (*p != '/')
+ return 0;
+ for (i = 0; i < 5; i++) {
+ p = strchr(&p[1], '/');
+ if (!p)
+ return 0;
+ }
+
+ fd = open(syspath, O_DIRECTORY);
+ if (fd < 0)
+ return -1;
+
+ if (search(fd, "../..", cardsp, &count, &st)) {
+ close(fd);
+ free(*cardsp);
+ *cardsp = NULL;
+ return -1;
+ }
+
+ close(fd);
+ errno = saved_errno;
+ return (ssize_t)count;
+}
diff --git a/test-list.c b/test-list.c
index f604dd9..51ef13b 100644
--- a/test-list.c
+++ b/test-list.c
@@ -9,7 +9,8 @@ int
main(void)
{
char **devices;
- size_t ndevices, i, j;
+ size_t ndevices, i, j, *sound_cards;
+ ssize_t nsound_cards;
struct libgamepad_superdevice device;
if (libgamepad_list_superdevices(&devices, &ndevices)) {
@@ -32,6 +33,14 @@ main(void)
printf("\t%s (LED)\n", device.leds[j]);
for (j = 0; j < device.npower_supplies; j++)
printf("\t%s (PSU)\n", device.power_supplies[j]);
+ nsound_cards = libgamepad_find_sound_devices(device.syspath, &sound_cards);
+ if (nsound_cards < 0) {
+ perror("libgamepad_find_sound_devices");
+ } else {
+ for (j = 0; j < (size_t)nsound_cards; j++)
+ printf("\t%zu (SND)\n", sound_cards[j]);
+ free(sound_cards);
+ }
libgamepad_close_superdevice(&device);
}