diff options
| author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-07-25 15:56:11 +1000 |
|---|---|---|
| committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-08-29 13:54:46 +1000 |
| commit | 1acbfb35799485326f5d76280282f320828aec38 (patch) | |
| tree | fb7de085ba8996a043e5f801fb50bae073dccebe /libevdev/libevdev-uinput.h | |
| parent | 1b7c46b2f16f22bb87e76e55c28a717f5f8f248f (diff) | |
| download | libevdev-1acbfb35799485326f5d76280282f320828aec38.tar.gz | |
Add support for uinput device creation
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).
Device node is guessed based on the sysfs path:
The sysfs path contains a eventN file, that corresponds to our
/dev/input/eventN number. Use it so clients can quickly get the device
node, without a libudev dependency.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'libevdev/libevdev-uinput.h')
| -rw-r--r-- | libevdev/libevdev-uinput.h | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/libevdev/libevdev-uinput.h b/libevdev/libevdev-uinput.h new file mode 100644 index 0000000..45b8a18 --- /dev/null +++ b/libevdev/libevdev-uinput.h @@ -0,0 +1,230 @@ +/* + * 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 */ |
