[PATCH libevdev 1/6] Add support for uinput device creation

Peter Hutterer peter.hutterer at who-t.net
Tue Aug 13 03:39:50 PDT 2013


This lets libevdev provide a relatively generic interface for the
creation of uinput devices so we don't need to duplicate this across
multiple projects.

Most of this is lifted from the current test implementation, with a
couple of minor changes.

EV_REP needs special handling:
Kernel allows to set the EV_REP bit, it doesn't set REP_* bits (which we
wrap anyway) but it will also set the default values (500, 33).

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 doc/libevdev.doxygen.in        |   3 +-
 libevdev/Makefile.am           |   5 +-
 libevdev/libevdev-uinput-int.h |  29 +++++
 libevdev/libevdev-uinput.c     | 285 +++++++++++++++++++++++++++++++++++++++++
 libevdev/libevdev-uinput.h     | 232 +++++++++++++++++++++++++++++++++
 libevdev/libevdev.c            |   1 -
 test/Makefile.am               |   3 +
 7 files changed, 555 insertions(+), 3 deletions(-)
 create mode 100644 libevdev/libevdev-uinput-int.h
 create mode 100644 libevdev/libevdev-uinput.c
 create mode 100644 libevdev/libevdev-uinput.h

diff --git a/doc/libevdev.doxygen.in b/doc/libevdev.doxygen.in
index 4511ae8..855b317 100644
--- a/doc/libevdev.doxygen.in
+++ b/doc/libevdev.doxygen.in
@@ -668,7 +668,8 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = @top_srcdir@/libevdev/libevdev.h
+INPUT                  = @top_srcdir@/libevdev/libevdev.h \
+			 @top_srcdir@/libevdev/libevdev-uinput.h
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/libevdev/Makefile.am b/libevdev/Makefile.am
index 9879c0e..2e99c2a 100644
--- a/libevdev/Makefile.am
+++ b/libevdev/Makefile.am
@@ -6,12 +6,15 @@ libevdev_la_SOURCES = \
                    libevdev.h \
                    libevdev-int.h \
                    libevdev-util.h \
+                   libevdev-uinput.c \
+                   libevdev-uinput.h \
+                   libevdev-uinput-int.h \
                    libevdev.c
 
 libevdev_la_LDFLAGS = -version-info $(LIBEVDEV_LT_VERSION) -export-symbols-regex '^libevdev_' $(GCOV_LDFLAGS)
 
 libevdevincludedir = $(includedir)/libevdev-1.0/libevdev
-libevdevinclude_HEADERS = libevdev.h
+libevdevinclude_HEADERS = libevdev.h libevdev-uinput.h
 
 event-names.h: Makefile make-event-names.py
 	        $(srcdir)/make-event-names.py --output=c > $@
diff --git a/libevdev/libevdev-uinput-int.h b/libevdev/libevdev-uinput-int.h
new file mode 100644
index 0000000..70fa1e1
--- /dev/null
+++ b/libevdev/libevdev-uinput-int.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+
+struct libevdev_uinput {
+	int fd; /**< file descriptor to uinput */
+	char *name; /**< device name */
+	char *syspath; /**< /sys path */
+	time_t ctime[2]; /**< before/after UI_DEV_CREATE */
+};
diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c
new file mode 100644
index 0000000..3009fba
--- /dev/null
+++ b/libevdev/libevdev-uinput.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+#include <config.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <linux/uinput.h>
+
+#include "libevdev.h"
+#include "libevdev-int.h"
+#include "libevdev-uinput.h"
+#include "libevdev-uinput-int.h"
+#include "libevdev-util.h"
+
+#define SYS_INPUT_DIR "/sys/devices/virtual/input/"
+
+static struct libevdev_uinput *
+alloc_uinput_device(const char *name)
+{
+	struct libevdev_uinput *uinput_dev;
+
+	uinput_dev = calloc(1, sizeof(struct libevdev_uinput));
+	if (uinput_dev)
+		uinput_dev->name = strdup(name);
+
+	return uinput_dev;
+}
+
+int set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
+{
+	int rc = 0;
+	unsigned int type;
+
+	for (type = 0; type < EV_MAX; type++) {
+		unsigned int code;
+		int max;
+		int uinput_bit;
+		const unsigned long *mask;
+
+		if (!libevdev_has_event_type(dev, type))
+			continue;
+
+		rc = ioctl(fd, UI_SET_EVBIT, type);
+		if (rc == -1)
+			break;
+
+		/* uinput can't set EV_REP */
+		if (type == EV_REP)
+			continue;
+
+		max = type_to_mask_const(dev, 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:
+				    rc = -1;
+				    errno = EINVAL;
+				    goto out;
+		}
+
+		for (code = 0; code < max; code++) {
+			if (!libevdev_has_event_code(dev, type, code))
+				continue;
+
+			rc = ioctl(fd, uinput_bit, code);
+			if (rc == -1)
+				goto out;
+
+			if (type == EV_ABS) {
+				const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
+				uidev->absmin[code] = abs->minimum;
+				uidev->absmax[code] = abs->maximum;
+				uidev->absfuzz[code] = abs->fuzz;
+				uidev->absflat[code] = abs->flat;
+				/* uinput has no resolution in the device struct, this needs
+				 * to be fixed in the kernel */
+			}
+		}
+
+	}
+
+out:
+	return rc;
+}
+
+int set_props(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
+{
+	unsigned int prop;
+	int rc = 0;
+
+	for (prop = 0; prop < INPUT_PROP_MAX; prop++) {
+		if (!libevdev_has_property(dev, prop))
+			continue;
+
+		rc = ioctl(fd, UI_SET_PROPBIT, prop);
+		if (rc == -1)
+			break;
+	}
+	return rc;
+}
+
+int
+libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct libevdev_uinput** uinput_dev)
+{
+	int rc;
+	struct uinput_user_dev uidev;
+	struct libevdev_uinput *new_device;
+
+	new_device = alloc_uinput_device(libevdev_get_name(dev));
+	if (!new_device)
+		return -ENOMEM;
+
+	memset(&uidev, 0, sizeof(uidev));
+
+	strncpy(uidev.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
+	uidev.id.vendor = libevdev_get_id_vendor(dev);
+	uidev.id.product = libevdev_get_id_product(dev);
+	uidev.id.bustype = libevdev_get_id_bustype(dev);
+	uidev.id.version = libevdev_get_id_version(dev);
+
+	if (set_evbits(dev, fd, &uidev) != 0)
+		goto error;
+	if (set_props(dev, fd, &uidev) != 0)
+		goto error;
+
+	rc = write(fd, &uidev, sizeof(uidev));
+	if (rc < 0)
+		goto error;
+	else if (rc < sizeof(uidev)) {
+		errno = EINVAL;
+		goto error;
+	}
+
+	/* ctime notes before/after ioctl to help us filter out devices
+	   when traversing /sys/devices/virtual/input inl
+	   libevdev_uinput_get_syspath.
+
+	   this is in seconds, so ctime[0]/[1] will almost always be
+	   identical but /sys doesn't give us sub-second ctime so...
+	 */
+	new_device->ctime[0] = time(NULL);
+
+	rc = ioctl(fd, UI_DEV_CREATE, NULL);
+	if (rc == -1)
+		goto error;
+
+	new_device->ctime[1] = time(NULL);
+	new_device->fd = fd;
+
+	*uinput_dev = new_device;
+
+	return 0;
+
+error:
+	return -errno;
+}
+
+void libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev)
+{
+	ioctl(uinput_dev->fd, UI_DEV_DESTROY, NULL);
+	free(uinput_dev->name);
+	free(uinput_dev);
+}
+
+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)
+{
+	DIR *dir;
+	struct dirent *dent;
+
+	if (uinput_dev->syspath != NULL)
+		return uinput_dev->syspath;
+
+	/* FIXME: use new ioctl() here once kernel supports it */
+
+	dir = opendir(SYS_INPUT_DIR);
+	if (!dir)
+		return NULL;
+
+	while((dent = readdir(dir))) {
+		struct stat st;
+		int fd;
+		char path[sizeof(SYS_INPUT_DIR) + 64];
+		char buf[256];
+		int len;
+
+		if (strncmp("input", dent->d_name, 5) != 0)
+			continue;
+
+		strcpy(path, SYS_INPUT_DIR);
+		strcat(path, dent->d_name);
+
+		if (stat(path, &st) == -1)
+			continue;
+
+		/* created before/after UI_DEV_CREATE */
+		if (st.st_ctime < uinput_dev->ctime[0] ||
+		    st.st_ctime > uinput_dev->ctime[1])
+			continue;
+
+		/* created after UI_DEV_CREATE */
+		strcat(path, "/name");
+		fd = open(path, O_RDONLY);
+		if (fd < 0)
+			continue;
+
+		len = read(fd, buf, sizeof(buf));
+		if (len > 1) {
+			buf[len - 1] = '\0'; /* file contains \n */
+			if (strcmp(buf, uinput_dev->name) == 0) {
+				strcpy(path, SYS_INPUT_DIR);
+				strcat(path, dent->d_name);
+				uinput_dev->syspath = strdup(path);
+				close(fd);
+				break;
+			}
+		}
+
+		close(fd);
+	}
+
+	closedir(dir);
+
+	return uinput_dev->syspath;
+}
+
+int libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
+				unsigned int type,
+				unsigned int code,
+				int value)
+{
+	struct input_event ev = { {0,0}, type, code, value };
+	int fd = libevdev_uinput_get_fd(uinput_dev);
+	int rc;
+
+	if (type > EV_MAX)
+		return -EINVAL;
+
+	if (code > libevdev_get_event_type_max(type))
+		return -EINVAL;
+
+	rc = write(fd, &ev, sizeof(ev));
+
+	return rc < 0 ? -errno : 0;
+}
diff --git a/libevdev/libevdev-uinput.h b/libevdev/libevdev-uinput.h
new file mode 100644
index 0000000..9e19ad2
--- /dev/null
+++ b/libevdev/libevdev-uinput.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef libevdev_uinput_H
+#define libevdev_uinput_H
+
+#include <libevdev/libevdev.h>
+
+struct libevdev_uinput;
+
+/**
+ * @defgroup uinput uinput device creation
+ *
+ * Creation of uinput devices based on existing libevdev devices. These functions
+ * help to create uinput devices that emulate libevdev devices. In the simplest
+ * form it serves to duplicate an existing device:
+ *
+ * @code
+ * int err;
+ * int new_fd;
+ * struct libevdev *dev;
+ * struct libevdev_uinput *uidev;
+ * struct input_event ev[2];
+ *
+ * err = libevdev_new_from_fd(&dev, fd);
+ * if (err != 0)
+ *     return err;
+ *
+ * uifd = open("/dev/uinput", O_RDWR);
+ * if (uidev < 0)
+ *     return -errno;
+ *
+ * err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
+ * if (err != 0)
+ *     return err;
+ *
+ * // post a REL_X event
+ * err = libevdev_uinput_write(event(uidev, EV_REL, REL_X, -1);
+ * if (err != 0)
+ *     return err;
+ * libevdev_uinput_write(event(uidev, EV_SYN, SYN_REPORT, 0);
+ * if (err != 0)
+ *     return err;
+ *
+ * libevdev_uinput_destroy(uidev);
+ * close(uifd);
+ *
+ * @endcode
+ *
+ * Alternatively, a device can be constructed from scratch:
+ *
+ * @code
+ * int err;
+ * struct libevdev *dev;
+ * struct libevdev_uinput *uidev;
+ *
+ * dev = libevdev_new();
+ * libevdev_set_name(dev, "test device");
+ * libevdev_enable_event_type(dev, EV_REL);
+ * libevdev_enable_event_code(dev, EV_REL, REL_X);
+ * libevdev_enable_event_code(dev, EV_REL, REL_Y);
+ * libevdev_enable_event_type(dev, EV_KEY);
+ * libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT);
+ * libevdev_enable_event_code(dev, EV_KEY, BTN_MIDDLE);
+ * libevdev_enable_event_code(dev, EV_KEY, BTN_RIGHT);
+ *
+ * uifd = open("/dev/uinput", O_RDWR);
+ * if (uidev < 0)
+ *     return -errno;
+ *
+ * err = libevdev_uinput_create_from_device(dev, uifd, &uidev);
+ * if (err != 0)
+ *     return err;
+ *
+ * // ... do something ...
+ *
+ * libevdev_uinput_destroy(uidev);
+ * close(uifd);
+ *
+ * @endcode
+ */
+
+/**
+ * @ingroup uinput
+ *
+ * Create a uinput device based on the libevdev device given. The uinput device
+ * will be an exact copy of the libevdev device, minus the bits that uinput doesn't
+ * allow to be set.
+ *
+ * The device's lifetime is tied to the uinput file descriptor, closing it will
+ * destroy the uinput device. You should call libevdev_uinput_destroy() before
+ * closing the file descriptor to free allocated resources.
+ * A file descriptor can only create one uinput device at a time; the second device
+ * will fail with -EINVAL.
+ *
+ * You don't need to keep the file descriptor variable around,
+ * libevdev_uinput_get_fd() will return it when needed.
+ *
+ * @note Due to limitations in the uinput kernel module, REP_DELAY and
+ * REP_PERIOD will default to the kernel defaults, not to the ones set in the
+ * source device.
+ *
+ * @param dev The device to duplicate
+ * @param uinput_fd A file descriptor to @c /dev/uinput, opened with the required
+ * permissions to create a device. This fd may only be used once to create a
+ * uinput device.
+ * @param[out] uinput_dev The newly created libevdev device.
+ *
+ * @return 0 on success or a negative errno on failure. On failure, the value of
+ * uinput_dev is unmodified.
+ *
+ * @see libevdev_uinput_destroy
+ */
+int libevdev_uinput_create_from_device(const struct libevdev *dev,
+				       int uinput_fd,
+				       struct libevdev_uinput **uinput_dev);
+
+/**
+ * @ingroup uinput
+ *
+ * Destroy a previously created uinput device and free associated memory.
+ *
+ * @note libevdev_uinput_destroy() does not close the fd.
+ *
+ * @param uinput_dev A previously created uinput device.
+ *
+ * @return 0 on success or a negative errno on failure
+ */
+void libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev);
+
+/**
+ * @ingroup uinput
+ *
+ * Return the file descriptor used to create this uinput device. This is the
+ * fd pointing to <strong>/dev/uinput</strong>. This file descriptor may be used to write
+ * events that are emitted by the uinput device.
+ * Closing this file descriptor will destroy the uinput device, you should
+ * call libevdev_uinput_destroy() first to free allocated resources.
+ *
+ * @param uinput_dev A previously created uinput device.
+ *
+ * @return The file descriptor used to create this device
+ */
+int libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev);
+
+/**
+ * @ingroup uinput
+ *
+ * Return the syspath representing this uinput device.
+ * As of 3.11, the uinput kernel device does not
+ * provide a way to get the syspath directly through uinput so libevdev must guess.
+ * In some cases libevdev is unable to derive the syspath. If the running kernel
+ * supports the UI_GET_SYSPATH ioctl, the syspath is retrieved through that and will
+ * be reliable and not be NULL.
+ *
+ * To obtain a /dev/input/eventX device node from this path use the following code:
+ *
+ * @code
+ * DIR *dir;
+ * const char *syspath;
+ * struct dirent *dp;
+ * struct udev *udev;
+ * struct udev_device *udev_device;
+ *
+ * syspath = libevdev_uinput_get_syspath(uidev);
+ * udev = udev_new();
+ * dir = opendir(syspath);
+ * while ((dp = readdir(dir))) {
+ *      char *path;
+ *
+ *      if (strncmp(dp->d_name, "event", 5) != 0)
+ *          continue;
+ *
+ *      asprintf(&path, "%s/%s", syspath, dp->d_name);
+ *      udev_device = udev_device_new_from_syspath(udev, path);
+ *      printf("device node: %s\n", udev_device_get_devnode(udev_device));
+ *      udev_device_unref(udev_device);
+ *      free(path);
+ * }
+ *
+ * closedir(dir);
+ * udev_unref(udev);
+ * @endcode
+ *
+ *
+ * @note This function may return NULL. libevdev currently uses ctime and
+ * the device name to guess devices. To avoid false positives, wait at least
+ * wait at least 1.5s between creating devices that have the same name.
+ * @param uinput_dev A previously created uinput device.
+ * @return The syspath for this device, including preceding /sys.
+ */
+const char*libevdev_uinput_get_syspath(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
+ * next EV_SYN event is posted.
+ *
+ * @param uinput_dev A previously created uinput device.
+ * @param type Event type (EV_ABS, EV_REL, etc.)
+ * @param code Event code (ABS_X, REL_Y, etc.)
+ * @param value The event value
+ * @return 0 on success or a negative errno on error
+ */
+int libevdev_uinput_write_event(const struct libevdev_uinput *uinput_dev,
+				unsigned int type,
+				unsigned int code,
+				int value);
+
+#endif /* libevdev_uinput_H */
diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
index 5883447..9448f1c 100644
--- a/libevdev/libevdev.c
+++ b/libevdev/libevdev.c
@@ -27,7 +27,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdarg.h>
-#include <linux/uinput.h>
 
 #include "libevdev.h"
 #include "libevdev-int.h"
diff --git a/test/Makefile.am b/test/Makefile.am
index 12f7176..8cad6c7 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -5,8 +5,11 @@ TESTS = $(noinst_PROGRAMS)
 
 libevdev_sources = $(top_srcdir)/libevdev/libevdev.c \
 		   $(top_srcdir)/libevdev/libevdev.h \
+		   $(top_srcdir)/libevdev/libevdev-uinput.h \
+		   $(top_srcdir)/libevdev/libevdev-uinput.c \
 		   $(top_srcdir)/libevdev/libevdev-util.h \
 		   $(top_srcdir)/libevdev/libevdev-int.h
+		   $(top_srcdir)/libevdev/libevdev-uinput-int.h
 common_sources = $(libevdev_sources) \
 		 test-common-uinput.c \
 		 test-common-uinput.h \
-- 
1.8.2.1



More information about the Input-tools mailing list