# 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
lib_LTLIBRARIES=libevdev.la
-AM_CPPFLAGS = $(GCC_CFLAGS) $(GCOV_CFLAGS)
+AM_CPPFLAGS = $(GCC_CFLAGS) $(GCOV_CFLAGS) -I$(top_srcdir)
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 > $@
--- /dev/null
+/*
+ * 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 */
+ 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 */
+};
--- /dev/null
+/*
+ * 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);
+ uinput_dev->fd = -1;
+ }
+
+ return uinput_dev;
+}
+
+static 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 < (unsigned int)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;
+}
+
+static 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;
+}
+
+static int
+open_uinput(void)
+{
+ int fd = open("/dev/uinput", O_RDWR|O_CLOEXEC);
+ if (fd < 0)
+ return -errno;
+
+ return fd;
+}
+
+LIBEVDEV_EXPORT int
+libevdev_uinput_get_fd(const struct libevdev_uinput *uinput_dev)
+{
+ return uinput_dev->fd;
+}
+
+static int is_event_device(const struct dirent *dent) {
+ return strncmp("event", dent->d_name, 5) == 0;
+}
+
+static char *
+fetch_device_node(const char *path)
+{
+ char *devnode = NULL;
+ struct dirent **namelist;
+ int ndev, i;
+
+ ndev = scandir(path, &namelist, is_event_device, alphasort);
+ if (ndev <= 0)
+ return NULL;
+
+ /* ndev should only ever be 1 */
+
+ for (i = 0; i < ndev; i++) {
+ asprintf(&devnode, "/dev/input/%s", namelist[i]->d_name);
+ free(namelist[i]);
+ }
+
+ free(namelist);
+
+ return devnode;
+}
+
+static int is_input_device(const struct dirent *dent) {
+ return strncmp("input", dent->d_name, 5) == 0;
+}
+
+static int
+fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
+{
+ struct dirent **namelist;
+ int ndev, i;
+
+ /* FIXME: use new ioctl() here once kernel supports it */
+
+ ndev = scandir(SYS_INPUT_DIR, &namelist, is_input_device, alphasort);
+ if (ndev <= 0)
+ return -1;
+
+ for (i = 0; i < ndev; i++) {
+ int fd, len;
+ char buf[sizeof(SYS_INPUT_DIR) + 64];
+ struct stat st;
+
+ strcpy(buf, SYS_INPUT_DIR);
+ strcat(buf, namelist[i]->d_name);
+
+ if (stat(buf, &st) == -1)
+ continue;
+
+ /* created before UI_DEV_CREATE, or after it finished */
+ if (st.st_ctime < uinput_dev->ctime[0] ||
+ st.st_ctime > uinput_dev->ctime[1])
+ continue;
+
+ /* created within time frame */
+ strcat(buf, "/name");
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ len = read(fd, buf, sizeof(buf));
+ close(fd);
+ if (len <= 0)
+ continue;
+
+ buf[len - 1] = '\0'; /* file contains \n */
+ if (strcmp(buf, uinput_dev->name) == 0) {
+ strcpy(buf, SYS_INPUT_DIR);
+ strcat(buf, namelist[i]->d_name);
+ uinput_dev->syspath = strdup(buf);
+ uinput_dev->devnode = fetch_device_node(buf);
+ }
+ }
+
+ for (i = 0; i < ndev; i++)
+ free(namelist[i]);
+ free(namelist);
+
+ return uinput_dev->devnode ? 0 : -1;
+}
+
+
+
+LIBEVDEV_EXPORT 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;
+
+ if (fd == LIBEVDEV_UINPUT_OPEN_MANAGED) {
+ fd = open_uinput();
+ if (fd < 0)
+ return fd;
+
+ new_device->fd_is_managed = 1;
+ } else if (fd < 0)
+ return -EBADF;
+
+ 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 ((size_t)rc < sizeof(uidev)) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ /* ctime notes time before/after ioctl to help us filter out devices
+ when traversing /sys/devices/virtual/input to find the device
+ node.
+
+ 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;
+
+ if (fetch_syspath_and_devnode(new_device) == -1) {
+ errno = ENODEV;
+ goto error;
+ }
+
+ *uinput_dev = new_device;
+
+ return 0;
+
+error:
+ libevdev_uinput_destroy(new_device);
+ return -errno;
+}
+
+LIBEVDEV_EXPORT void
+libevdev_uinput_destroy(struct libevdev_uinput *uinput_dev)
+{
+ ioctl(uinput_dev->fd, UI_DEV_DESTROY, NULL);
+ 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);
+}
+
+LIBEVDEV_EXPORT const char*
+libevdev_uinput_get_syspath(struct libevdev_uinput *uinput_dev)
+{
+ return uinput_dev->syspath;
+}
+
+LIBEVDEV_EXPORT const char*
+libevdev_uinput_get_devnode(struct libevdev_uinput *uinput_dev)
+{
+ return uinput_dev->devnode;
+}
+
+LIBEVDEV_EXPORT 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, max;
+
+ if (type > EV_MAX)
+ return -EINVAL;
+
+ max = libevdev_get_event_type_max(type);
+ if (max == -1 || code > (unsigned int)max)
+ return -EINVAL;
+
+ rc = write(fd, &ev, sizeof(ev));
+
+ return rc < 0 ? -errno : 0;
+}
--- /dev/null
+/*
+ * 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);
+ *
+ * err = libevdev_uinput_create_from_device(dev,
+ * LIBEVDEV_UINPUT_OPEN_MANAGED,
+ * &uidev);
+ * if (err != 0)
+ * return err;
+ *
+ * // ... do something ...
+ *
+ * libevdev_uinput_destroy(uidev);
+ *
+ * @endcode
+ */
+
+enum libevdev_uinput_open_mode {
+ /* intentionally -2 to avoid to avoid code like the below from accidentally working:
+ fd = open("/dev/uinput", O_RDWR); // fails, fd is -1
+ libevdev_uinput_create_from_device(dev, fd, &uidev); // may hide the error */
+ LIBEVDEV_UINPUT_OPEN_MANAGED = -2, /**< let libevdev open and close @c /dev/uinput */
+};
+
+/**
+ * @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.
+ *
+ * If uinput_fd is LIBEVDEV_UINPUT_OPEN_MANAGED, libevdev_uinput_create_from_device()
+ * will open @c /dev/uinput in read/write mode and manage the file descriptor.
+ * Otherwise, uinput_fd must be opened by the caller and opened with the
+ * appropriate permissions.
+ *
+ * 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 LIBEVDEV_UINPUT_OPEN_MANAGED or a file descriptor to @c /dev/uinput,
+ * @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.
+ *
+ * If the device was opened with LIBEVDEV_UINPUT_OPEN_MANAGED, libevdev_uinput_destroy()
+ * also closes the file descriptor. Otherwise, the fd is left as-is and
+ * must be closed by the caller.
+ *
+ * @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.
+ *
+ * @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.
+ *
+ * @see libevdev_uinput_get_devnode
+ */
+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
+ *
+ * @see libevdev_uinput_get_syspath
+ */
+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
+ * 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 */
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-uinput-int.h \
$(top_srcdir)/libevdev/libevdev-util.h \
$(top_srcdir)/libevdev/libevdev-int.h
common_sources = $(libevdev_sources) \