[PATCH libevdev 3/4] Guess the device node based on the sysfs path
David Herrmann
dh.herrmann at gmail.com
Thu Aug 15 06:02:24 PDT 2013
Hi
On Thu, Aug 15, 2013 at 6:12 AM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> 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))) {
readdir is not re-entrant. I know readdir_r is ugly as we need to
allocate "dirent" on the heap, but this way libevdev stays re-entrant.
Regards
David
> + 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
>
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/input-tools
More information about the Input-tools
mailing list