[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