mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-20 22:00:07 +01:00
Due to what must've been a copy/paste error many years ago, the license text for libevdev wasn't actually the MIT license. Let's rectify this, it was always MIT intended anyway. To make this more obvious and reduce the chance of copy/paste mistakes, use the SPDX license identifier in the various source files. The two installed public header files have the full license text. All contributors with copyrightable contributions have ACKed the license change to MIT, either in the MR directly [1] or privately in reply to an email. [1] https://gitlab.freedesktop.org/libevdev/libevdev/-/merge_requests/69 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Acked-by: Alexander Dahl <ada@thorsis.com> Acked-by: Andreas Pokorny <andreas.pokorny@canonical.com> Acked-by: Armin K <krejzi@email.com> Acked-by: Benjamin Tissoires <btissoir@redhat.com> Acked-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Deepa Dinamani <deepa.kernel@gmail.com> Acked-by: Emmanuele Bassi <ebassi@gnome.org> Acked-by: Gaetan Nadon <memsize@videotron.ca> Acked-by: George Thomas <georgefsthomas@gmail.com> Acked-by: Michael Forney <mforney@mforney.org> Acked-by: Nayan Deshmukh <nayan26deshmukh@gmail.com> Acked-by: Niclas Zeising <zeising@daemonic.se> Acked-by: Owen W. Taylor <otaylor@fishsoup.net> Acked-by: Peter Seiderer <ps.report@gmx.net> Acked-by: Ran Benita <ran234@gmail.com> Acked-by: Rosen Penev <rosenp@gmail.com> Acked-by: Scott Jann <sjann@knight-rider.org> Acked-by: Thilo Schulz <thilo@tjps.eu> Acked-by: polyphemus <rolfmorel@gmail.com>
282 lines
5.4 KiB
C
282 lines
5.4 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2013 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <fcntl.h>
|
|
#include <poll.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <linux/uinput.h>
|
|
#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"
|
|
|
|
#define SYS_INPUT_DIR "/sys/class/input"
|
|
#define DEV_INPUT_DIR "/dev/input/"
|
|
|
|
struct uinput_device
|
|
{
|
|
struct libevdev *d; /* lazy, it has all the accessors */
|
|
struct libevdev_uinput *uidev;
|
|
int dev_fd; /* open fd to the devnode */
|
|
int uinput_fd;
|
|
};
|
|
|
|
struct uinput_device*
|
|
uinput_device_new(const char *name)
|
|
{
|
|
struct uinput_device *dev;
|
|
|
|
dev = calloc(1, sizeof(*dev));
|
|
if (!dev)
|
|
return NULL;
|
|
|
|
dev->d = libevdev_new();
|
|
dev->dev_fd = -1;
|
|
dev->uinput_fd = -1;
|
|
|
|
if (name)
|
|
libevdev_set_name(dev->d, name);
|
|
|
|
return dev;
|
|
}
|
|
|
|
int
|
|
uinput_device_new_with_events_v(struct uinput_device **d, const char *name, const struct input_id *id, va_list args)
|
|
{
|
|
int rc;
|
|
struct uinput_device *dev;
|
|
|
|
dev = uinput_device_new(name);
|
|
if (!dev)
|
|
return -ENOMEM;
|
|
if (id != DEFAULT_IDS)
|
|
uinput_device_set_ids(dev, id);
|
|
|
|
rc = uinput_device_set_event_bits_v(dev, args);
|
|
|
|
if (rc == 0)
|
|
rc = uinput_device_create(dev);
|
|
|
|
if (rc != 0) {
|
|
uinput_device_free(dev);
|
|
dev = NULL;
|
|
} else
|
|
*d = dev;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
uinput_device_new_with_events(struct uinput_device **d, const char *name, const struct input_id *id, ...)
|
|
{
|
|
int rc;
|
|
va_list args;
|
|
|
|
va_start(args, id);
|
|
rc = uinput_device_new_with_events_v(d, name, id, args);
|
|
va_end(args);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void
|
|
uinput_device_free(struct uinput_device *dev)
|
|
{
|
|
if (!dev)
|
|
return;
|
|
|
|
if (dev->uinput_fd != -1) {
|
|
(void)ioctl(dev->uinput_fd, UI_DEV_DESTROY, NULL);
|
|
close(dev->uinput_fd);
|
|
}
|
|
if (dev->dev_fd != -1)
|
|
close(dev->dev_fd);
|
|
libevdev_free(dev->d);
|
|
libevdev_uinput_destroy(dev->uidev);
|
|
free(dev);
|
|
}
|
|
|
|
int
|
|
uinput_device_get_fd(const struct uinput_device *dev)
|
|
{
|
|
return dev->dev_fd;
|
|
}
|
|
|
|
const char*
|
|
uinput_device_get_devnode(const struct uinput_device *dev)
|
|
{
|
|
return libevdev_uinput_get_devnode(dev->uidev);
|
|
}
|
|
|
|
int
|
|
uinput_device_create(struct uinput_device* d)
|
|
{
|
|
int rc;
|
|
int fd;
|
|
const char *devnode;
|
|
|
|
fd = open("/dev/uinput", O_RDWR);
|
|
if (fd < 0)
|
|
goto error;
|
|
|
|
d->uinput_fd = fd;
|
|
|
|
rc = libevdev_uinput_create_from_device(d->d, fd, &d->uidev);
|
|
if (rc != 0)
|
|
goto error;
|
|
|
|
devnode = libevdev_uinput_get_devnode(d->uidev);
|
|
if (devnode == NULL)
|
|
goto error;
|
|
|
|
d->dev_fd = open(devnode, O_RDWR);
|
|
if (d->dev_fd == -1)
|
|
goto error;
|
|
|
|
/* write abs resolution now */
|
|
if (libevdev_has_event_type(d->d, EV_ABS)) {
|
|
int code;
|
|
for (code = 0; code < ABS_CNT; code++) {
|
|
const struct input_absinfo *abs;
|
|
|
|
/* can't change slots */
|
|
if (code == ABS_MT_SLOT)
|
|
continue;
|
|
|
|
abs = libevdev_get_abs_info(d->d, code);
|
|
if (!abs)
|
|
continue;
|
|
|
|
rc = ioctl(d->dev_fd, EVIOCSABS(code), abs);
|
|
if (rc < 0) {
|
|
printf("error %s for code %d\n", strerror(-rc), code);
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
error:
|
|
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)
|
|
{
|
|
libevdev_set_name(dev->d, name);
|
|
return 0;
|
|
}
|
|
|
|
int uinput_device_set_ids(struct uinput_device *dev, const struct input_id *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)
|
|
{
|
|
return libevdev_enable_event_type(dev->d, bit);
|
|
}
|
|
|
|
int
|
|
uinput_device_set_prop(struct uinput_device *dev, unsigned int prop)
|
|
{
|
|
return libevdev_enable_property(dev->d, prop);
|
|
}
|
|
|
|
int
|
|
uinput_device_set_event_bit(struct uinput_device* dev, unsigned int type, unsigned int code)
|
|
{
|
|
return libevdev_enable_event_code(dev->d, type, code, NULL);
|
|
}
|
|
|
|
int
|
|
uinput_device_set_event_bits_v(struct uinput_device *dev, va_list args)
|
|
{
|
|
int type, code;
|
|
int rc = 0;
|
|
|
|
do {
|
|
type = va_arg(args, int);
|
|
if (type == -1)
|
|
break;
|
|
code = va_arg(args, int);
|
|
if (code == -1)
|
|
break;
|
|
rc = libevdev_enable_event_code(dev->d, type, code, NULL);
|
|
} while (rc == 0);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
uinput_device_set_event_bits(struct uinput_device *dev, ...)
|
|
{
|
|
int rc;
|
|
va_list args;
|
|
va_start(args, dev);
|
|
rc = uinput_device_set_event_bits_v(dev, args);
|
|
va_end(args);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
uinput_device_set_abs_bit(struct uinput_device* dev, unsigned int code, const struct input_absinfo *absinfo)
|
|
{
|
|
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)
|
|
{
|
|
return libevdev_uinput_write_event(dev->uidev, type, code, value);
|
|
}
|
|
|
|
int uinput_device_event_multiple_v(const struct uinput_device* dev, va_list args)
|
|
{
|
|
int type, code, value;
|
|
int rc = 0;
|
|
|
|
do {
|
|
type = va_arg(args, int);
|
|
if (type == -1)
|
|
break;
|
|
code = va_arg(args, int);
|
|
if (code == -1)
|
|
break;
|
|
value = va_arg(args, int);
|
|
rc = uinput_device_event(dev, type, code, value);
|
|
} while (rc == 0);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int uinput_device_event_multiple(const struct uinput_device* dev, ...)
|
|
{
|
|
int rc;
|
|
va_list args;
|
|
va_start(args, dev);
|
|
rc = uinput_device_event_multiple_v(dev, args);
|
|
va_end(args);
|
|
return rc;
|
|
}
|