[PATCH libevdev 3/6] test: switch udev backend over to new libevdev-uinput bits

Benjamin Tissoires benjamin.tissoires at gmail.com
Wed Aug 14 06:12:21 PDT 2013


On Tue, Aug 13, 2013 at 12:39 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  configure.ac              |   9 +-
>  test/Makefile.am          |   2 +-
>  test/test-common-uinput.c | 265 ++++++++++------------------------------------
>  test/test-common-uinput.h |   2 +
>  4 files changed, 66 insertions(+), 212 deletions(-)

Hehe, I like when patches remove more code than they add :)

>
> diff --git a/configure.ac b/configure.ac
> index 68df538..7e17291 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -34,10 +34,13 @@ LT_INIT
>
>  PKG_PROG_PKG_CONFIG()
>  PKG_CHECK_MODULES(CHECK, [check], [HAVE_CHECK="yes"], [HAVE_CHECK="no"])
> -if test "x$HAVE_CHECK" != "xyes"; then
> -       AC_MSG_WARN([check not found - skipping building unit tests])
> +PKG_CHECK_MODULES(LIBUDEV, [libudev], [HAVE_LIBUDEV="yes"], [HAVE_LIBUDEV="no"])
> +if test "x$HAVE_CHECK" != "xyes" -o "x$HAVE_LIBUDEV" != "xyes"; then
> +       AC_MSG_WARN([check or libudev not found - skipping building unit tests])
>  fi
> -AM_CONDITIONAL(BUILD_TESTS, [test "x$HAVE_CHECK" = "xyes"])
> +AM_CONDITIONAL(BUILD_TESTS, [test "x$HAVE_CHECK" = "xyes" -a "x$HAVE_LIBUDEV" = "xyes"])
> +
> +
>
>  if test "x$GCC" = "xyes"; then
>         GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden"
> diff --git a/test/Makefile.am b/test/Makefile.am
> index cabd1bf..3ba2e7f 100644
> --- a/test/Makefile.am
> +++ b/test/Makefile.am
> @@ -29,7 +29,7 @@ test_libevdev_SOURCES = \
>                         test-uinput.c \
>                         $(common_sources)
>
> -test_libevdev_LDADD =  $(CHECK_LIBS) $(GCOV_LDFLAGS)
> +test_libevdev_LDADD =  $(CHECK_LIBS) $(GCOV_LDFLAGS) $(LIBUDEV_LIBS)
>
>  if GCOV_ENABLED
>
> diff --git a/test/test-common-uinput.c b/test/test-common-uinput.c
> index b99bfa8..fe1bfb0 100644
> --- a/test/test-common-uinput.c
> +++ b/test/test-common-uinput.c
> @@ -30,10 +30,13 @@
>  #include <errno.h>
>  #include <linux/uinput.h>

Couldn't we remove this?

>  #include <sys/inotify.h>

Same here? I hope the inotify hack can be removed

> +#include <libudev.h>

It looks like udev is not completely required (you use it just to get
the dev node, which will always be under /dev/input).

> +#include <dirent.h>
>
>  #include <libevdev/libevdev.h>
>  #include <libevdev/libevdev-int.h>
>  #include <libevdev/libevdev-util.h>
> +#include <libevdev/libevdev-uinput.h>
>
>  #include "test-common-uinput.h"
>
> @@ -42,9 +45,11 @@
>
>  struct uinput_device
>  {
> -       struct libevdev d; /* lazy, it has all the accessors */
> +       struct libevdev *d; /* lazy, it has all the accessors */
> +       struct libevdev_uinput *uidev;
>         char *devnode; /* path after creation */
>         int dev_fd; /* open fd to the devnode */
> +       int uinput_fd;
>  };
>
>  struct uinput_device*
> @@ -56,11 +61,12 @@ uinput_device_new(const char *name)
>         if (!dev)
>                 return NULL;
>
> -       dev->d.fd = -1;
> +       dev->d = libevdev_new();
>         dev->dev_fd = -1;
> +       dev->uinput_fd = -1;
>
>         if (name)
> -               dev->d.name = strdup(name);
> +               libevdev_set_name(dev->d, name);
>
>         return dev;
>  }
> @@ -110,14 +116,13 @@ uinput_device_free(struct uinput_device *dev)
>         if (!dev)
>                 return;
>
> -       if (dev->d.fd != -1) {
> -               ioctl(dev->d.fd, UI_DEV_DESTROY, NULL);
> -               close(dev->d.fd);
> +       if (dev->uinput_fd != -1) {
> +               ioctl(dev->uinput_fd, UI_DEV_DESTROY, NULL);
> +               close(dev->uinput_fd);
>         }
>         if (dev->dev_fd != -1)
>                 close(dev->dev_fd);
> -       free(dev->d.name);
> -       free(dev->devnode);
> +       libevdev_free(dev->d);
>         free(dev);
>  }
>
> @@ -127,155 +132,52 @@ uinput_device_get_fd(const struct uinput_device *dev)
>         return dev->dev_fd;
>  }
>
> -
> -static char*
> -wait_for_inotify(int fd)
> +char* uinput_devnode_from_syspath(const char *syspath)
>  {
> +       DIR *dir;
> +       struct dirent *dp;
> +       struct udev *udev;
> +       struct udev_device *udev_device;
>         char *devnode = NULL;
> -       int found = 0;
> -       char buf[1024];
> -       size_t bufidx = 0;
> -       struct pollfd pfd;
>
> -       pfd.fd = fd;
> -       pfd.events = POLLIN;
> +       udev = udev_new();
> +       dir = opendir(syspath);
> +       while ((dp = readdir(dir)) && devnode == NULL) {
> +               char *path;
>
> -       while (!found && poll(&pfd, 1, 2000) > 0) {
> -               struct inotify_event *e;
> -               ssize_t r;
> +               if (strncmp(dp->d_name, "event", 5) != 0)
> +                       continue;
>
> -               r = read(fd, buf + bufidx, sizeof(buf) - bufidx);
> -               if (r == -1 && errno != EAGAIN)
> -                       return NULL;
> -
> -               bufidx += r;
> -
> -               e = (struct inotify_event*)buf;
> -
> -               while (bufidx > sizeof(*e) && bufidx >= sizeof(*e) + e->len) {
> -                       if (strncmp(e->name, "event", 5) == 0) {
> -                               asprintf(&devnode, "%s%s", DEV_INPUT_DIR, e->name);
> -                               found = 1;
> -                               break;
> -                       }
> -
> -                       /* this packet didn't contain what we're looking for */
> -                       int len = sizeof(*e) + e->len;
> -                       memmove(buf, buf + len, bufidx - len);
> -                       bufidx -= len;
> -               }
> +               asprintf(&path, "%s/%s", syspath, dp->d_name);
> +               udev_device = udev_device_new_from_syspath(udev, path);
> +               devnode = strdup(udev_device_get_devnode(udev_device));
> +               udev_device_unref(udev_device);

As mentioned above, I think a simple
asprintf(&devnode, "/dev/input/%s", dp->d_name);
is enough and removes the need for udev.

Cheers,
Benjamin

> +               free(path);
>         }
>
> +       closedir(dir);
> +       udev_unref(udev);
> +
>         return devnode;
>  }
>
> -static int
> -inotify_setup()
> -{
> -       int ifd = inotify_init1(IN_NONBLOCK);
> -       if (ifd == -1 || inotify_add_watch(ifd, DEV_INPUT_DIR, IN_CREATE) == -1) {
> -               if (ifd != -1)
> -                       close(ifd);
> -               ifd = -1;
> -       }
> -
> -       return ifd;
> -}
> -
>  int
>  uinput_device_create(struct uinput_device* d)
>  {
> -       int type, code, prop;
> -       struct uinput_user_dev dev;
>         int rc;
>         int fd;
> -       int ifd = -1; /* inotify fd */
>
>         fd = open("/dev/uinput", O_RDWR);
>         if (fd < 0)
>                 goto error;
>
> -       d->d.fd = fd;
> +       d->uinput_fd = fd;
>
> -       memset(&dev, 0, sizeof(dev));
> -       if (d->d.name)
> -               strncpy(dev.name, d->d.name, UINPUT_MAX_NAME_SIZE - 1);
> -       dev.id = d->d.ids;
> -
> -       for (type = 0; type < EV_MAX; type++) {
> -               int max;
> -               int uinput_bit;
> -               const unsigned long *mask;
> -
> -               if (!bit_is_set(d->d.bits, type))
> -                       continue;
> -
> -               rc = ioctl(fd, UI_SET_EVBIT, type);
> -               if (rc == -1)
> -                       goto error;
> -
> -               max = type_to_mask_const(&d->d, type, &mask);
> -               if (max == -1)
> -                       continue;
> -
> -               switch(type) {
> -                       case EV_KEY: uinput_bit = UI_SET_KEYBIT; break;
> -                       case EV_REL: uinput_bit = UI_SET_RELBIT; break;
> -                       case EV_ABS: uinput_bit = UI_SET_ABSBIT; break;
> -                       case EV_MSC: uinput_bit = UI_SET_MSCBIT; break;
> -                       case EV_LED: uinput_bit = UI_SET_LEDBIT; break;
> -                       case EV_SND: uinput_bit = UI_SET_SNDBIT; break;
> -                       case EV_FF: uinput_bit = UI_SET_FFBIT; break;
> -                       case EV_SW: uinput_bit = UI_SET_SWBIT; break;
> -                       default:
> -                                   errno = EINVAL;
> -                                   goto error;
> -               }
> -
> -               for (code = 0; code < max; code++) {
> -                       if (!bit_is_set(mask, code))
> -                               continue;
> -
> -                       rc = ioctl(fd, uinput_bit, code);
> -                       if (rc == -1)
> -                               goto error;
> -
> -                       if (type == EV_ABS) {
> -                               dev.absmin[code] = d->d.abs_info[code].minimum;
> -                               dev.absmax[code] = d->d.abs_info[code].maximum;
> -                               dev.absfuzz[code] = d->d.abs_info[code].fuzz;
> -                               dev.absflat[code] = d->d.abs_info[code].flat;
> -                               /* uinput has no resolution in the device struct, we use
> -                                * EVIOCSABS below */
> -                       }
> -               }
> -
> -       }
> -
> -       for (prop = 0; prop < INPUT_PROP_MAX; prop++) {
> -               if (!bit_is_set(d->d.props, prop))
> -                       continue;
> -
> -               rc = ioctl(fd, UI_SET_PROPBIT, prop);
> -               if (rc == -1)
> -                       goto error;
> -       }
> -
> -       rc = write(fd, &dev, sizeof(dev));
> -       if (rc < 0)
> -               goto error;
> -       else if (rc < sizeof(dev)) {
> -               errno = EINVAL;
> -               goto error;
> -       }
> -
> -       ifd = inotify_setup();
> -
> -       rc = ioctl(fd, UI_DEV_CREATE, NULL);
> -       if (rc == -1)
> +       rc = libevdev_uinput_create_from_device(d->d, fd, &d->uidev);
> +       if (rc != 0)
>                 goto error;
>
> -       d->devnode = wait_for_inotify(ifd);
> +       d->devnode = uinput_devnode_from_syspath(libevdev_uinput_get_syspath(d->uidev));
>         if (d->devnode == NULL)
>                 goto error;
>
> @@ -284,18 +186,19 @@ uinput_device_create(struct uinput_device* d)
>                 goto error;
>
>         /* write abs resolution now */
> -       if (bit_is_set(d->d.bits, EV_ABS)) {
> -               for (code = 0; code < ABS_MAX; code++ ) {
> -                       struct input_absinfo *abs;
> +       if (libevdev_has_event_type(d->d, EV_ABS)) {
> +               int  code;
> +               for (code = 0; code < ABS_MAX; code++) {
> +                       const struct input_absinfo *abs;
>
>                         /* can't change slots */
>                         if (code == ABS_MT_SLOT)
>                                 continue;
>
> -                       if (!bit_is_set(d->d.abs_bits, code))
> +                       abs = libevdev_get_abs_info(d->d, code);
> +                       if (!abs)
>                                 continue;
>
> -                       abs = &d->d.abs_info[code];
>                         rc = ioctl(d->dev_fd, EVIOCSABS(code), abs);
>                         if (rc < 0) {
>                                 printf("error %s for code %d\n", strerror(-rc), code);
> @@ -307,73 +210,45 @@ uinput_device_create(struct uinput_device* d)
>         return 0;
>
>  error:
> -       if (ifd != -1)
> -               close(ifd);
> -       if (d->d.fd != -1)
> -               close(fd);
> +       if (d->dev_fd != -1)
> +               close(d->dev_fd);
> +       if (d->uinput_fd != -1)
> +               close(d->uinput_fd);
>         return -errno;
>
>  }
>
>  int uinput_device_set_name(struct uinput_device *dev, const char *name)
>  {
> -       if (dev->d.name)
> -               free(dev->d.name);
> -       if (name)
> -               dev->d.name = strdup(name);
> +       libevdev_set_name(dev->d, name);
>         return 0;
>  }
>
>  int uinput_device_set_ids(struct uinput_device *dev, const struct input_id *ids)
>  {
> -       dev->d.ids = *ids;
> +       libevdev_set_id_product(dev->d, ids->product);
> +       libevdev_set_id_vendor(dev->d, ids->vendor);
> +       libevdev_set_id_bustype(dev->d, ids->bustype);
> +       libevdev_set_id_version(dev->d, ids->version);
>         return 0;
>  }
>
>  int
>  uinput_device_set_bit(struct uinput_device* dev, unsigned int bit)
>  {
> -       if (!dev)
> -               return -EINVAL;
> -
> -       if (bit > EV_MAX)
> -               return -EINVAL;
> -
> -       set_bit(dev->d.bits, bit);
> -       return 0;
> +       return libevdev_enable_event_type(dev->d, bit);
>  }
>
>  int
>  uinput_device_set_prop(struct uinput_device *dev, unsigned int prop)
>  {
> -       if (!dev)
> -               return -EINVAL;
> -
> -       if (prop > INPUT_PROP_MAX)
> -               return -EINVAL;
> -
> -       set_bit(dev->d.props, prop);
> -       return 0;
> +       return libevdev_enable_property(dev->d, prop);
>  }
>
>  int
>  uinput_device_set_event_bit(struct uinput_device* dev, unsigned int type, unsigned int code)
>  {
> -       int max;
> -       unsigned long *mask;
> -
> -       if (uinput_device_set_bit(dev, type) < 0)
> -               return -EINVAL;
> -
> -       if (type == EV_SYN)
> -               return 0;
> -
> -       max = type_to_mask(&dev->d, type, &mask);
> -       if (max == -1 || code > max)
> -               return -EINVAL;
> -
> -       set_bit(mask, code);
> -       return 0;
> +       return libevdev_enable_event_code(dev->d, type, code, NULL);
>  }
>
>  int
> @@ -389,7 +264,7 @@ uinput_device_set_event_bits_v(struct uinput_device *dev, va_list args)
>                 code = va_arg(args, int);
>                 if (code == -1)
>                         break;
> -               rc = uinput_device_set_event_bit(dev, type, code);
> +               rc = libevdev_enable_event_code(dev->d, type, code, NULL);
>         } while (rc == 0);
>
>         return rc;
> @@ -410,39 +285,13 @@ uinput_device_set_event_bits(struct uinput_device *dev, ...)
>  int
>  uinput_device_set_abs_bit(struct uinput_device* dev, unsigned int code, const struct input_absinfo *absinfo)
>  {
> -       if (uinput_device_set_event_bit(dev, EV_ABS, code) < 0)
> -               return -EINVAL;
> -
> -       dev->d.abs_info[code] = *absinfo;
> -       return 0;
> +       return libevdev_enable_event_code(dev->d, EV_ABS, code, absinfo);
>  }
>
>  int
>  uinput_device_event(const struct uinput_device *dev, unsigned int type, unsigned int code, int value)
>  {
> -       int max;
> -       int rc;
> -       const unsigned long *mask;
> -       struct input_event ev;
> -
> -       if (type > EV_MAX)
> -               return -EINVAL;
> -
> -       if (type != EV_SYN) {
> -               max = type_to_mask_const(&dev->d, type, &mask);
> -               if (max == -1 || code > max)
> -                       return -EINVAL;
> -       }
> -
> -       ev.type = type;
> -       ev.code = code;
> -       ev.value = value;
> -       ev.time.tv_sec = 0;
> -       ev.time.tv_usec = 0;
> -
> -       rc = write(dev->d.fd, &ev, sizeof(ev));
> -
> -       return (rc == -1) ? -errno : 0;
> +       return libevdev_uinput_write_event(dev->uidev, type, code, value);
>  }
>
>  int uinput_device_event_multiple_v(const struct uinput_device* dev, va_list args)
> diff --git a/test/test-common-uinput.h b/test/test-common-uinput.h
> index b50155c..c1cd5a0 100644
> --- a/test/test-common-uinput.h
> +++ b/test/test-common-uinput.h
> @@ -44,3 +44,5 @@ int uinput_device_event(const struct uinput_device* dev, unsigned int type, unsi
>  int uinput_device_event_multiple(const struct uinput_device* dev, ...);
>  int uinput_device_event_multiple_v(const struct uinput_device* dev, va_list args);
>  int uinput_device_get_fd(const struct uinput_device *dev);
> +
> +char *uinput_devnode_from_syspath(const char *syspath);
> --
> 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