[PATCH libevdev 3/4] Guess the device node based on the sysfs path

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 14 21:12:39 PDT 2013


The sysfs path contains a eventN file, that corresponds to our
/dev/input/eventN number. Use it so clients can quickly get the device
node, without a libudev dependency.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 libevdev/libevdev-uinput-int.h |  1 +
 libevdev/libevdev-uinput.c     | 45 ++++++++++++++++++++++++++++++++++++++----
 libevdev/libevdev-uinput.h     | 15 ++++++++++++++
 3 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/libevdev/libevdev-uinput-int.h b/libevdev/libevdev-uinput-int.h
index f443984..fbc1c29 100644
--- a/libevdev/libevdev-uinput-int.h
+++ b/libevdev/libevdev-uinput-int.h
@@ -26,5 +26,6 @@ struct libevdev_uinput {
 	int fd_is_managed; /**< do we need to close it? */
 	char *name; /**< device name */
 	char *syspath; /**< /sys path */
+	char *devnode; /**< device node */
 	time_t ctime[2]; /**< before/after UI_DEV_CREATE */
 };
diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c
index 830d681..2cb9121 100644
--- a/libevdev/libevdev-uinput.c
+++ b/libevdev/libevdev-uinput.c
@@ -220,6 +220,7 @@ void libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev)
 	if (uinput_dev->fd_is_managed)
 		close(uinput_dev->fd);
 	free(uinput_dev->syspath);
+	free(uinput_dev->devnode);
 	free(uinput_dev->name);
 	free(uinput_dev);
 }
@@ -229,19 +230,41 @@ int libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev)
 	return uinput_dev->fd;
 }
 
-const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
+static char *
+fetch_device_node(const char *path)
 {
 	DIR *dir;
 	struct dirent *dent;
+	char *devnode = NULL;
 
-	if (uinput_dev->syspath != NULL)
-		return uinput_dev->syspath;
+	dir = opendir(path);
+	if (!dir)
+		return NULL;
+
+	while ((dent = readdir(dir))) {
+		if (strncmp("event", dent->d_name, 5) != 0)
+			continue;
+
+		asprintf(&devnode, "/dev/input/%s", dent->d_name);
+		break;
+	}
+
+	closedir(dir);
+
+	return devnode;
+}
+
+static void
+fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
+{
+	DIR *dir;
+	struct dirent *dent;
 
 	/* FIXME: use new ioctl() here once kernel supports it */
 
 	dir = opendir(SYS_INPUT_DIR);
 	if (!dir)
-		return NULL;
+		return;
 
 	while((dent = readdir(dir))) {
 		struct stat st;
@@ -277,6 +300,7 @@ const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
 				strcpy(path, SYS_INPUT_DIR);
 				strcat(path, dent->d_name);
 				uinput_dev->syspath = strdup(path);
+				uinput_dev->devnode = fetch_device_node(path);
 				close(fd);
 				break;
 			}
@@ -286,10 +310,23 @@ const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
 	}
 
 	closedir(dir);
+}
 
+
+const char* libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
+{
+	if (!uinput_dev->syspath)
+		fetch_syspath_and_devnode(uinput_dev);
 	return uinput_dev->syspath;
 }
 
+const char* libevdev_uinput_get_devnode(struct libevdev_uinput *uinput_dev)
+{
+	if (!uinput_dev->devnode)
+		fetch_syspath_and_devnode(uinput_dev);
+	return uinput_dev->devnode;
+}
+
 int libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
 				unsigned int type,
 				unsigned int code,
diff --git a/libevdev/libevdev-uinput.h b/libevdev/libevdev-uinput.h
index c22c013..edcecb8 100644
--- a/libevdev/libevdev-uinput.h
+++ b/libevdev/libevdev-uinput.h
@@ -222,6 +222,21 @@ const char*libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev);
 /**
  * @ingroup uinput
  *
+ * Return the device node representing this uinput device.
+ *
+ * This relies on libevdev_uinput_get_syspath() to provide a valid syspath.
+ * See libevdev_uinput_get_syspath() for more details.
+ *
+ * @note This function may return NULL. libevdev currently has to guess the
+ * syspath and the device node. See libevdev_uinput_get_syspath() for details.
+ * @param uinput_dev A previously created uinput device.
+ * @return The device node for this device, in the form of /dev/input/eventN
+ */
+const char* libevdev_uinput_get_devnode(struct libevdev_uinput *uinput_dev);
+
+/**
+ * @ingroup uinput
+ *
  * Post an event through the uinput device. It is the caller's responsibility
  * that any event sequence is terminated with an EV_SYN/SYN_REPORT/0 event.
  * Otherwise, listeners on the device node will not see the events until the
-- 
1.8.2.1



More information about the Input-tools mailing list