[PATCH libevdev 1/6] Add support for uinput device creation
Benjamin Tissoires
benjamin.tissoires at gmail.com
Wed Aug 14 05:45:31 PDT 2013
On Tue, Aug 13, 2013 at 12:39 PM, Peter Hutterer
<peter.hutterer at who-t.net> wrote:
> 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)
hmm, it looks like either this function should be prefixed with
libevdev_uinput, or it should be static.
> +{
> + 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)
ditto
> +{
> + 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)
The code looks good, but I don't really like the parameter "fd". To
me, it looks like this parameter can only be a fresh open of
/dev/uinput node, with the right permissions and parameters. Besides,
having this as a parameter, would allow a user to use it twice for two
different uinput devices.
To my mind, the parameter should be omitted and the open called in
libevdev_uinput_create_from_device(). If the user wants to have a
handle to it, it can call libevdev_uinput_get_fd(), and it will also
allows us to close the fd in libevdev_uinput_destroy().
Cheers,
Benjamin
> +{
> + 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
>
> _______________________________________________
> 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