[PATCH evemu 3/7] Switch to using a libevdev backend

Peter Hutterer peter.hutterer at who-t.net
Thu Nov 21 16:19:58 PST 2013


Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 configure.ac     |   2 +
 evemu.pc.in      |   1 +
 src/Makefile.am  |   4 +
 src/evemu-impl.h |  15 +-
 src/evemu.c      | 431 ++++++++++++++++++-------------------------------------
 5 files changed, 153 insertions(+), 300 deletions(-)

diff --git a/configure.ac b/configure.ac
index 577401f..75f5ad1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,6 +33,8 @@ AC_PROG_CXX
 AC_PROG_INSTALL
 AM_PATH_PYTHON([2.6])
 
+PKG_CHECK_MODULES([LIBEVDEV], [libevdev >= 0.4])
+
 # man page generation
 AC_ARG_VAR([XMLTO], [Path to xmlto command])
 AC_PATH_PROG([XMLTO], [xmlto])
diff --git a/evemu.pc.in b/evemu.pc.in
index 1ab741e..e895e8b 100644
--- a/evemu.pc.in
+++ b/evemu.pc.in
@@ -6,5 +6,6 @@ includedir=@includedir@
 Name: evemu
 Description: Kernel device emulation
 Version: @PACKAGE_VERSION@
+Requires.private: libevdev
 Libs: -L${libdir} -levemu
 Cflags: -I${includedir}
diff --git a/src/Makefile.am b/src/Makefile.am
index a90b431..f8ddb80 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,6 +16,10 @@ libevemu_la_SOURCES = \
 	evemu.h \
 	version.h
 
+libevemu_la_LIBADD = $(LIBEVDEV_LIBS)
+
+AM_CPPFLAGS = -I$(top_srcdir)/include/ $(LIBEVDEV_CFLAGS)
+
 libevemuincludedir = $(includedir)
 libevemuinclude_HEADERS = evemu.h
 
diff --git a/src/evemu-impl.h b/src/evemu-impl.h
index 9844c60..1f2aacb 100644
--- a/src/evemu-impl.h
+++ b/src/evemu-impl.h
@@ -19,18 +19,17 @@
 
 #include <evemu.h>
 #include <linux/uinput.h>
-
-#define EVPLAY_NBITS	KEY_CNT
-#define EVPLAY_NBYTES	((EVPLAY_NBITS + 7) / 8)
+#include <libevdev/libevdev.h>
+#include <libevdev/libevdev-uinput.h>
 
 struct evemu_device {
 	unsigned int version;
-	char name[UINPUT_MAX_NAME_SIZE];
-	struct input_id id;
-	unsigned char prop[EVPLAY_NBYTES];
-	unsigned char mask[EV_CNT][EVPLAY_NBYTES];
+	struct libevdev *evdev;
+	struct libevdev_uinput *uidev;
+	/* we read in properties and bits 8 at a time, but the file format
+	 * has no hint which byte we're up to. So we count what we've read
+	 * already to know where the next one tacks onto */
 	int pbytes, mbytes[EV_CNT];
-	struct input_absinfo abs[ABS_CNT];
 };
 
 #endif
diff --git a/src/evemu.c b/src/evemu.c
index 67b7645..39d66f9 100644
--- a/src/evemu.c
+++ b/src/evemu.c
@@ -54,18 +54,12 @@
 #include <unistd.h>
 
 #include "version.h"
-#include "event-names.h"
 
 /* File format version we write out
    NOTE: if you bump the version number, make sure you update README */
 #define EVEMU_FILE_MAJOR 1
 #define EVEMU_FILE_MINOR 2
 
-#ifndef UI_SET_PROPBIT
-#define UI_SET_PROPBIT		_IOW(UINPUT_IOCTL_BASE, 110, int)
-#define EVIOCGPROP(len)		_IOC(_IOC_READ, 'E', 0x09, len)
-#endif
-
 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
 
 enum error_level {
@@ -120,20 +114,17 @@ static int next_line(FILE *fp, char **line, size_t *sz)
 	return 0;
 }
 
-static void copy_bits(unsigned char *mask, const unsigned long *bits, int bytes)
-{
-	int i;
-	for (i = 0; i < bytes; i++) {
-		int pos = 8 * (i % sizeof(long));
-		mask[i] = (bits[i / sizeof(long)] >> pos) & 0xff;
-	}
-}
 
 struct evemu_device *evemu_new(const char *name)
 {
 	struct evemu_device *dev = calloc(1, sizeof(struct evemu_device));
 
 	if (dev) {
+		dev->evdev = libevdev_new();
+		if (!dev->evdev) {
+			free(dev);
+			return NULL;
+		}
 		dev->version = EVEMU_VERSION;
 		evemu_set_name(dev, name);
 	}
@@ -143,6 +134,9 @@ struct evemu_device *evemu_new(const char *name)
 
 void evemu_delete(struct evemu_device *dev)
 {
+	if (dev->uidev)
+		evemu_destroy(dev, libevdev_uinput_get_fd(dev->uidev));
+	libevdev_free(dev->evdev);
 	free(dev);
 }
 
@@ -153,186 +147,148 @@ unsigned int evemu_get_version(const struct evemu_device *dev)
 
 const char *evemu_get_name(const struct evemu_device *dev)
 {
-	return dev->name;
+	return libevdev_get_name(dev->evdev);
 }
 
 void evemu_set_name(struct evemu_device *dev, const char *name)
 {
-	if (name && strlen(name) < sizeof(dev->name))
-		strcpy(dev->name, name);
+	if (name)
+		libevdev_set_name(dev->evdev, name);
 }
 
-unsigned int evemu_get_id_bustype(const struct evemu_device *dev)
-{
-	return dev->id.bustype;
+#define ID_GETTER(field) \
+unsigned int evemu_get_id_##field(const struct evemu_device *dev) { \
+	return libevdev_get_id_##field(dev->evdev); \
 }
 
-void evemu_set_id_bustype(struct evemu_device *dev,
-			  unsigned int bustype)
-{
-	dev->id.bustype = bustype;
-}
-
-unsigned int evemu_get_id_vendor(const struct evemu_device *dev)
-{
-	return dev->id.vendor;
-}
-
-void evemu_set_id_vendor(struct evemu_device *dev,
-			 unsigned int vendor)
-{
-	dev->id.vendor = vendor;
-}
+ID_GETTER(bustype)
+ID_GETTER(version)
+ID_GETTER(product)
+ID_GETTER(vendor)
 
-unsigned int evemu_get_id_product(const struct evemu_device *dev)
-{
-	return dev->id.product;
+#define ID_SETTER(field) \
+void evemu_set_id_##field(struct evemu_device *dev, unsigned int value) { \
+	libevdev_set_id_##field(dev->evdev, value); \
 }
 
-void evemu_set_id_product(struct evemu_device *dev,
-			  unsigned int product)
-{
-	dev->id.product = product;
-}
+ID_SETTER(bustype)
+ID_SETTER(version)
+ID_SETTER(product)
+ID_SETTER(vendor)
 
-unsigned int evemu_get_id_version(const struct evemu_device *dev)
-{
-	return dev->id.version;
+#define ABS_GETTER(field) \
+int evemu_get_abs_##field(const struct evemu_device *dev, int code) { \
+	return libevdev_get_abs_##field(dev->evdev, code); \
 }
 
-void evemu_set_id_version(struct evemu_device *dev,
-			  unsigned int version)
-{
-	dev->id.version = version;
-}
+ABS_GETTER(minimum)
+ABS_GETTER(maximum)
+ABS_GETTER(fuzz)
+ABS_GETTER(flat)
+ABS_GETTER(resolution)
 
-int evemu_get_abs_minimum(const struct evemu_device *dev, int code)
-{
-	return dev->abs[code].minimum;
+#define ABS_SETTER(field) \
+void evemu_set_abs_##field(struct evemu_device *dev, int code, int value) { \
+	libevdev_set_abs_##field(dev->evdev, code, value); \
 }
 
-void evemu_set_abs_minimum(struct evemu_device *dev, int code, int min)
-{
-	dev->abs[code].minimum = min;
-}
-
-int evemu_get_abs_maximum(const struct evemu_device *dev, int code)
-{
-	return dev->abs[code].maximum;
-}
+ABS_SETTER(minimum)
+ABS_SETTER(maximum)
+ABS_SETTER(fuzz)
+ABS_SETTER(flat)
+ABS_SETTER(resolution)
 
 int evemu_get_abs_current_value(const struct evemu_device *dev, int code)
 {
-	return dev->abs[code].value;
-}
-
-void evemu_set_abs_maximum(struct evemu_device *dev, int code, int max)
-{
-	dev->abs[code].maximum = max;
-}
-
-int evemu_get_abs_fuzz(const struct evemu_device *dev, int code)
-{
-	return dev->abs[code].fuzz;
-}
-
-void evemu_set_abs_fuzz(struct evemu_device *dev, int code, int fuzz)
-{
-	dev->abs[code].fuzz = fuzz;
-}
-
-int evemu_get_abs_flat(const struct evemu_device *dev, int code)
-{
-	return dev->abs[code].flat;
-}
-
-void evemu_set_abs_flat(struct evemu_device *dev, int code, int flat)
-{
-	dev->abs[code].flat = flat;
-}
-
-int evemu_get_abs_resolution(const struct evemu_device *dev, int code)
-{
-	return dev->abs[code].resolution;
-}
-
-void evemu_set_abs_resolution(struct evemu_device *dev, int code, int res)
-{
-	dev->abs[code].resolution = res;
+	return libevdev_get_event_value(dev->evdev, EV_ABS, code);
 }
 
 int evemu_has_prop(const struct evemu_device *dev, int code)
 {
-	return (dev->prop[code >> 3] >> (code & 7)) & 1;
+	return libevdev_has_property(dev->evdev, code);
 }
 
 int evemu_has_event(const struct evemu_device *dev, int type, int code)
 {
-	return (dev->mask[type][code >> 3] >> (code & 7)) & 1;
+	return libevdev_has_event_code(dev->evdev, type, code);
 }
 
 int evemu_has_bit(const struct evemu_device *dev, int type)
 {
-	return (dev->mask[0][type >> 3] >> (type & 7)) & 1;
+	return libevdev_has_event_type(dev->evdev, type);
 }
 
 int evemu_extract(struct evemu_device *dev, int fd)
 {
-	unsigned long bits[64];
-	int rc, i;
-
-	memset(dev, 0, sizeof(*dev));
-
-	SYSCALL(rc = ioctl(fd, EVIOCGNAME(sizeof(dev->name)-1), dev->name));
-	if (rc < 0)
-		return rc;
-
-	SYSCALL(rc = ioctl(fd, EVIOCGID, &dev->id));
-	if (rc < 0)
-		return rc;
-
-	SYSCALL(rc = ioctl(fd, EVIOCGPROP(sizeof(bits)), bits));
-	if (rc >= 0) {
-		copy_bits(dev->prop, bits, rc);
-		dev->pbytes = rc;
-	}
-
-	for (i = 0; i < EV_CNT; i++) {
-		SYSCALL(rc = ioctl(fd, EVIOCGBIT(i, sizeof(bits)), bits));
-		if (rc < 0)
-			continue;
-		copy_bits(dev->mask[i], bits, rc);
-		dev->mbytes[i] = rc;
+	if (libevdev_get_fd(dev->evdev) != -1) {
+		libevdev_free(dev->evdev);
+		dev->evdev = libevdev_new();
+		if (!dev->evdev)
+			return -ENOMEM;
 	}
+	return libevdev_set_fd(dev->evdev, fd);
+}
 
-	for (i = 0; i < ABS_CNT; i++) {
-		if (!evemu_has_event(dev, EV_ABS, i))
-			continue;
-		SYSCALL(rc = ioctl(fd, EVIOCGABS(i), &dev->abs[i]));
-		if (rc < 0)
-			return rc;
-	}
+static inline int bit_is_set(unsigned char *mask, int bit)
+{
+	return !!(mask[bit/8] & (1 << (bit & 0x7)));
+}
 
-	return 0;
+static inline void set_bit(unsigned char *mask, int bit)
+{
+	mask[bit/8] |= 1 << (bit & 0x7);
 }
 
-static void write_prop(FILE * fp, const unsigned char *mask, int bytes)
+#define max(a, b) (a > b) ? a : b
+
+static void write_prop(FILE * fp, const struct evemu_device *dev)
 {
+#ifdef INPUT_PROP_MAX
 	int i;
-	for (i = 0; i < bytes; i += 8)
+	unsigned char mask[max(8, (INPUT_PROP_MAX + 7)/8)] = {0};
+
+	for (i = 0; i < INPUT_PROP_MAX; i ++) {
+		if (evemu_has_prop(dev, i)) {
+		printf("prop bit set for %d\n", i);
+			set_bit(mask, i);
+			}
+	}
+
+	for (i = 0; i < (INPUT_PROP_MAX + 7)/8; i +=8) {
 		fprintf(fp, "P: %02x %02x %02x %02x %02x %02x %02x %02x\n",
 			mask[i], mask[i + 1], mask[i + 2], mask[i + 3],
 			mask[i + 4], mask[i + 5], mask[i + 6], mask[i + 7]);
+	}
+#endif
 }
 
-static void write_mask(FILE * fp, int index,
-		       const unsigned char *mask, int bytes)
+static void write_mask(FILE * fp, const struct evemu_device *dev)
 {
-	int i;
-	for (i = 0; i < bytes; i += 8)
-		fprintf(fp, "B: %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
-			index, mask[i], mask[i + 1], mask[i + 2], mask[i + 3],
-			mask[i + 4], mask[i + 5], mask[i + 6], mask[i + 7]);
+	unsigned int type;
+
+	/* Write EV_SYN/SYN_REPORT only. Just because older versions
+	   printed out exactly that */
+	fprintf(fp, "B: 00 0b 00 00 00 00 00 00 00\n");
+
+	for (type = 1 /* don't write EV_SYN */; type < EV_CNT; type++) {
+		int i;
+		int max = libevdev_event_type_get_max(type);
+		unsigned char mask[KEY_CNT] = {0};
+		unsigned int code;
+
+		if (max == -1)
+			continue;
+
+		for (code = 0; code < max; code++)
+			if (evemu_has_event(dev, type, code))
+				set_bit(mask, code);
+
+		for (i = 0; i < (max + 7)/8; i += 8) {
+			fprintf(fp, "B: %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+				type, mask[i], mask[i + 1], mask[i + 2], mask[i + 3],
+				mask[i + 4], mask[i + 5], mask[i + 6], mask[i + 7]);
+		}
+	}
 }
 
 static void write_abs(FILE *fp, int index, const struct input_absinfo *abs)
@@ -354,13 +310,13 @@ static void write_desc(const struct evemu_device *dev, FILE *fp)
 		if (!evemu_has_bit(dev, i))
 			continue;
 
-		fprintf(fp, "#   Event type %d (%s)\n", i, event_get_type_name(i));
-		for (j = 0; j < KEY_MAX; j++) {
+		fprintf(fp, "#   Event type %d (%s)\n", i, libevdev_event_type_get_name(i));
+		for (j = 0; j < libevdev_event_type_get_max(i); j++) {
 			if (!evemu_has_event(dev, i, j))
 				continue;
 
 			fprintf(fp, "#     Event code %d (%s)\n",
-				    j, event_get_code_name(i, j));
+				    j, libevdev_event_code_get_name(i, j));
 			if (i == EV_ABS) {
 				fprintf(fp, "#       Value %6d\n"
 					    "#       Min   %6d\n"
@@ -383,7 +339,8 @@ static void write_desc(const struct evemu_device *dev, FILE *fp)
 	for (i = 0; i < INPUT_PROP_MAX; i++) {
 		if (!evemu_has_prop(dev, i))
 			continue;
-		fprintf(fp, "#   Property  type %d (%s)\n", i, input_prop_map[i]);
+		fprintf(fp, "#   Property  type %d (%s)\n", i,
+				libevdev_property_get_name(i));
 	}
 #endif
 }
@@ -404,14 +361,12 @@ int evemu_write(const struct evemu_device *dev, FILE *fp)
 		evemu_get_id_product(dev),
 		evemu_get_id_version(dev));
 
-	write_prop(fp, dev->prop, dev->pbytes);
-
-	for (i = 0; i < EV_CNT; i++)
-		write_mask(fp, i, dev->mask[i], dev->mbytes[i]);
+	write_prop(fp, dev);
+	write_mask(fp, dev);
 
 	for (i = 0; i < ABS_CNT; i++)
 		if (evemu_has_event(dev, EV_ABS, i))
-			write_abs(fp, i, &dev->abs[i]);
+			write_abs(fp, i, libevdev_get_abs_info(dev->evdev, i));
 
 	return 0;
 }
@@ -457,7 +412,7 @@ static int parse_bus_vid_pid_ver(struct evemu_device *dev, const char *line, str
 static int parse_prop(struct evemu_device *dev, const char *line, struct version *fversion)
 {
 	int matched;
-	unsigned int mask[8];
+	unsigned char mask[8];
 	int i;
 
 	if (strlen(line) <= 2 || strncmp(line, "P:", 2) != 0)
@@ -472,8 +427,12 @@ static int parse_prop(struct evemu_device *dev, const char *line, struct version
 		return -1;
 	}
 
-	for (i = 0; i < 8; i++)
-		dev->prop[dev->pbytes++] = mask[i];
+	for (i = 0; i < sizeof(mask) * 8; i++) {
+		if (bit_is_set(mask, i))
+			libevdev_enable_property(dev->evdev, dev->pbytes * 8 + i);
+	}
+
+	dev->pbytes += 8;
 
 	return 1;
 }
@@ -481,7 +440,7 @@ static int parse_prop(struct evemu_device *dev, const char *line, struct version
 static int parse_mask(struct evemu_device *dev, const char *line, struct version *fversion)
 {
 	int matched;
-	unsigned int mask[8];
+	unsigned char mask[8];
 	unsigned int index, i;
 
 	if (strlen(line) <= 2 || strncmp(line, "B:", 2) != 0)
@@ -496,8 +455,15 @@ static int parse_mask(struct evemu_device *dev, const char *line, struct version
 		return -1;
 	}
 
-	for (i = 0; i < 8; i++)
-		dev->mask[index][dev->mbytes[index]++] = mask[i];
+	for (i = 0; i < sizeof(mask) * 8; i++) {
+		const struct input_absinfo abs = {0, 0, 1}; /* dummy */
+		if (bit_is_set(mask, i)) {
+			unsigned int code = dev->mbytes[index] * 8 + i;
+			libevdev_enable_event_code(dev->evdev, index, code, (index == EV_ABS) ? &abs : NULL);
+		}
+	}
+
+	dev->mbytes[index] += 8;
 
 	return 1;
 }
@@ -560,16 +526,10 @@ int evemu_read(struct evemu_device *dev, FILE *fp)
 	struct version file_version; /* file format version */
 	size_t size = 0;
 	char *line = NULL;
-	char *name = NULL;
 
-	if (strlen(evemu_get_name(dev)) > 0)
-		name = strdup(evemu_get_name(dev));
-	memset(dev, 0, sizeof(*dev));
+	memset(dev->mbytes, 0, sizeof(*dev->mbytes));
+	dev->pbytes = 0;
 	dev->version = EVEMU_VERSION;
-	if (name) {
-		evemu_set_name(dev, name);
-		free(name);
-	}
 
 	/* first line _may_ be version */
 	if (!first_line(fp, &line, &size)) {
@@ -629,16 +589,16 @@ static void write_event_desc(FILE *fp, const struct input_event *ev)
 	if (ev->type == EV_SYN) {
 		if (ev->code == SYN_MT_REPORT)
 			fprintf(fp, "# ++++++++++++ %s (%d) ++++++++++\n",
-				event_get_code_name(ev->type, ev->code),
+				libevdev_event_code_get_name(ev->type, ev->code),
 				ev->value);
 		else
 			fprintf(fp, "# ------------ %s (%d) ----------\n",
-				event_get_code_name(ev->type, ev->code),
+				libevdev_event_code_get_name(ev->type, ev->code),
 				ev->value);
 	} else {
 		fprintf(fp, "# %s / %-20s %d\n",
-			event_get_type_name(ev->type),
-			event_get_code_name(ev->type, ev->code),
+			libevdev_event_type_get_name(ev->type),
+			libevdev_event_code_get_name(ev->type, ev->code),
 			ev->value);
 	}
 }
@@ -775,8 +735,8 @@ static void evemu_warn_about_incompatible_event(struct input_event *ev)
 			error(WARNING, "You are trying to play events incompatbile with this device. "
 					"Is this the right device/recordings file?\n");
 		error(WARNING, "%s %s is not supported by this device.\n",
-				event_get_type_name(ev->type),
-				event_get_code_name(ev->type, ev->code));
+				libevdev_event_type_get_name(ev->type),
+				libevdev_event_code_get_name(ev->type, ev->code));
 	} else if (warned == max_warnings + 1) {
 		error(INFO, "warned about incompatible events %d times. Will be quiet now.\n",
 				warned - 1);
@@ -812,128 +772,15 @@ int evemu_play(FILE *fp, int fd)
 	return 0;
 }
 
-static int set_prop_bit(int fd, int code)
-{
-	int ret;
-	SYSCALL(ret = ioctl(fd, UI_SET_PROPBIT, code));
-	return ret;
-}
-
-static int set_event_bit(int fd, int type, int code)
-{
-	int ret = 0;
-
-	switch(type) {
-	case EV_SYN:
-		SYSCALL(ret = ioctl(fd, UI_SET_EVBIT, code));
-		break;
-	case EV_KEY:
-		SYSCALL(ret = ioctl(fd, UI_SET_KEYBIT, code));
-		break;
-	case EV_REL:
-		SYSCALL(ret = ioctl(fd, UI_SET_RELBIT, code));
-		break;
-	case EV_ABS:
-		SYSCALL(ret = ioctl(fd, UI_SET_ABSBIT, code));
-		break;
-	case EV_MSC:
-		SYSCALL(ret = ioctl(fd, UI_SET_MSCBIT, code));
-		break;
-	case EV_LED:
-		SYSCALL(ret = ioctl(fd, UI_SET_LEDBIT, code));
-		break;
-	case EV_SND:
-		SYSCALL(ret = ioctl(fd, UI_SET_SNDBIT, code));
-		break;
-	case EV_FF:
-		SYSCALL(ret = ioctl(fd, UI_SET_FFBIT, code));
-		break;
-	case EV_SW:
-		SYSCALL(ret = ioctl(fd, UI_SET_SWBIT, code));
-		break;
-	}
-
-	return ret;
-}
-
-static int set_prop(const struct evemu_device *dev, int fd)
-{
-	int bits = 8 * dev->pbytes;
-	int ret, i;
-	int success = 0;
-	for (i = 0; i < bits; i++) {
-		if (!evemu_has_prop(dev, i))
-			continue;
-		ret = set_prop_bit(fd, i);
-		/* Older kernels aways return errors on UI_SET_PROPBIT.
-		   Assume that if we only get failures, it may be an older
-		   kernel and report success anyway. */
-		if (ret < 0) {
-			if (success)
-				return ret;
-		} else if (!success)
-			success = 1;
-	}
-	return 0;
-}
-
-static int set_mask(const struct evemu_device *dev, int type, int fd)
-{
-	int bits = 8 * dev->mbytes[type];
-	int ret, i;
-	for (i = 0; i < bits; i++) {
-		if (!evemu_has_event(dev, type, i))
-			continue;
-
-		/* kernel doesn't like those */
-		if (type == EV_ABS &&
-			evemu_get_abs_maximum(dev, i) == 0 && evemu_get_abs_minimum(dev, i) == 0)
-			continue;
-
-		ret = set_event_bit(fd, type, i);
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
 int evemu_create(struct evemu_device *dev, int fd)
 {
-	struct uinput_user_dev udev;
-	int ret, i;
-
-	memset(&udev, 0, sizeof(udev));
-	memcpy(udev.name, dev->name, sizeof(udev.name));
-	udev.id = dev->id;
-	for (i = 0; i < ABS_CNT; i++) {
-		if (!evemu_has_event(dev, EV_ABS, i))
-			continue;
-		udev.absmax[i] = evemu_get_abs_maximum(dev, i);
-		udev.absmin[i] = evemu_get_abs_minimum(dev, i);
-		udev.absfuzz[i] = evemu_get_abs_fuzz(dev, i);
-		udev.absflat[i] = evemu_get_abs_flat(dev, i);
-	}
-
-	ret = set_prop(dev, fd);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < EV_CNT; i++) {
-		ret = set_mask(dev, i, fd);
-		if (ret < 0)
-			return ret;
-	}
-
-	SYSCALL(ret = write(fd, &udev, sizeof(udev)));
-	if (ret < 0)
-		return ret;
-
-	SYSCALL(ret = ioctl(fd, UI_DEV_CREATE, NULL));
-	return ret;
+	return libevdev_uinput_create_from_device(dev->evdev, fd, &dev->uidev);
 }
 
 void evemu_destroy(struct evemu_device *dev, int fd)
 {
-	int ret;
-	SYSCALL(ret = ioctl(fd, UI_DEV_DESTROY, NULL));
+	if (dev->uidev) {
+		libevdev_uinput_destroy(dev->uidev);
+		dev->uidev = NULL;
+	}
 }
-- 
1.8.3.1



More information about the Input-tools mailing list