[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