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

Peter Hutterer peter.hutterer at who-t.net
Thu Aug 15 23:44:30 PDT 2013


On Thu, Aug 15, 2013 at 03:02:24PM +0200, David Herrmann wrote:
> 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.

good point. I'll fix that up asap.

btw, in one of your emails when this branch was new you mentioned you didn't
want to block on udev for retrieving the devnode. AIUI, with this
implementation the syspath and the devnode don't rely on udev anymore, so we
could fetch this data during create and then make the API calls a simple
(and signal-safe) getter. Sound like a plan?

Cheers,
   Peter

> > +               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