aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am7
-rw-r--r--configure.ac16
-rw-r--r--test/Makefile.am35
-rw-r--r--test/abs.c84
-rw-r--r--test/absrel.c91
-rw-r--r--test/btn0.c87
-rw-r--r--test/fakedev.c199
-rw-r--r--test/fakedev.h51
8 files changed, 569 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 99f7160..d8397f8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,12 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AUTOMAKE_OPTIONS = foreign
-SUBDIRS = src man include
+
+if BUILD_TEST
+test_dir=test
+endif
+
+SUBDIRS = src man include $(test_dir)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = xorg-evdev.pc
diff --git a/configure.ac b/configure.ac
index 4233a22..4ba5a8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,21 @@ AC_ARG_WITH(xorg-module-dir,
inputdir=${moduledir}/input
AC_SUBST(inputdir)
+# Enable building everything in the test/ directory. These are uinput-based
+# devices that resemble random hardware that may or may not look like a mouse,
+# keyboard, etc.
+AC_ARG_ENABLE(testdevices,
+ AC_HELP_STRING([--enable-testdevices], [Build uinput-based test devices]),
+ [BUILD_TEST="yes"],
+ [BUILD_TEST="no"])
+AM_CONDITIONAL([BUILD_TEST], [test "x$BUILD_TEST" = "xyes"])
+
+if test "x$BUILD_TEST" = "xyes"; then
+ AC_CHECK_FUNC([dlopen], [],
+ AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl"))
+ AC_SUBST([DLOPEN_LIBS])
+fi
+
# Checks for extensions
XORG_DRIVER_CHECK_EXT(XINPUT, inputproto)
@@ -75,4 +90,5 @@ AC_OUTPUT([Makefile
src/Makefile
man/Makefile
include/Makefile
+ test/Makefile
xorg-evdev.pc])
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..4b417b8
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,35 @@
+# Copyright 2008 Red Hat, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+noinst_PROGRAMS=fakedev btn0 absrel abs
+
+fakedev_SOURCES=fakedev.c fakedev.h
+fakedev_LDFLAGS=$(DLOPEN_LIBS) -rdynamic
+
+LFLAGS=-shared -fPIC
+
+btn0_SOURCES=btn0.c
+btn0_LDFLAGS=$(LFLAGS)
+
+absrel_SOURCES=absrel.c
+absrel_LDFLAGS=$(LFLAGS)
+
+abs_SOURCES=abs.c
+abs_LDFLAGS=$(LFLAGS)
diff --git a/test/abs.c b/test/abs.c
new file mode 100644
index 0000000..8529190
--- /dev/null
+++ b/test/abs.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2008 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ *
+ * Authors:
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+
+/* creates a device with ABS_X, ABS_Y, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+
+#include "fakedev.h"
+
+int abs_setup(struct uinput_user_dev* dev, int fd)
+{
+ if (ioctl(fd, UI_SET_EVBIT, EV_ABS) == -1) goto error;
+ if (ioctl(fd, UI_SET_EVBIT, EV_SYN) == -1) goto error;
+
+ /* buttons */
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT) == -1) goto error;
+
+ /* axes */
+ if (ioctl(fd, UI_SET_ABSBIT, ABS_X) == -1) goto error;
+ if (ioctl(fd, UI_SET_ABSBIT, ABS_Y) == -1) goto error;
+
+
+ dev->absmin[ABS_X] = 0;
+ dev->absmax[ABS_X] = 120;
+
+ dev->absmin[ABS_Y] = 0;
+ dev->absmax[ABS_Y] = 120;
+
+ return 0;
+
+error:
+ perror("ioctl failed.");
+ return -1;
+}
+
+int abs_run(int fd)
+{
+ absmove(fd, 100, 100);
+ sleep(1);
+ absmove(fd, 120, 120);
+ sleep(1);
+ return 0;
+}
+
+struct test_device abs_dev = {
+ .name = "Abs test device",
+ .setup = abs_setup,
+ .run = abs_run,
+};
+
+
+struct test_device* get_device()
+{
+ return &abs_dev;
+}
diff --git a/test/absrel.c b/test/absrel.c
new file mode 100644
index 0000000..3ae2a1c
--- /dev/null
+++ b/test/absrel.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2008 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ *
+ * Authors:
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+
+/* creates a device with ABS_X, ABS_Y, REL_X, REL_Y, BTN_LEFT, BTN_MIDDLE,
+ BTN_RIGHT. */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+
+#include "fakedev.h"
+
+int absrel_setup(struct uinput_user_dev* dev, int fd)
+{
+ if (ioctl(fd, UI_SET_EVBIT, EV_REL) == -1) goto error;
+ if (ioctl(fd, UI_SET_EVBIT, EV_ABS) == -1) goto error;
+ if (ioctl(fd, UI_SET_EVBIT, EV_SYN) == -1) goto error;
+
+ /* buttons */
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_LEFT) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT) == -1) goto error;
+
+ /* axes */
+ if (ioctl(fd, UI_SET_RELBIT, REL_X) == -1) goto error;
+ if (ioctl(fd, UI_SET_RELBIT, REL_Y) == -1) goto error;
+
+ if (ioctl(fd, UI_SET_ABSBIT, ABS_X) == -1) goto error;
+ if (ioctl(fd, UI_SET_ABSBIT, ABS_Y) == -1) goto error;
+
+
+ dev->absmin[ABS_X] = 0;
+ dev->absmax[ABS_X] = 1000;
+
+ dev->absmin[ABS_Y] = 0;
+ dev->absmax[ABS_Y] = 1000;
+
+ return 0;
+
+error:
+ perror("ioctl failed.");
+ return -1;
+}
+
+int absrel_run(int fd)
+{
+ absmove(fd, 100, 100);
+ sleep(1);
+ absmove(fd, 120, 120);
+ sleep(1);
+ move(fd, 10, 10);
+ return 0;
+}
+
+struct test_device absrel_dev = {
+ .name = "Abs/Rel test device",
+ .setup = absrel_setup,
+ .run = absrel_run,
+};
+
+
+struct test_device* get_device()
+{
+ return &absrel_dev;
+}
+
diff --git a/test/btn0.c b/test/btn0.c
new file mode 100644
index 0000000..f6572a5
--- /dev/null
+++ b/test/btn0.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2008 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ *
+ * Authors:
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+/* Creates a device that has REL_X REL_Y BTN_0 BTN_1 BTN_2
+ *
+ * Moves the device around in a 10px square and clicks after each completed
+ * circle.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+
+#include "fakedev.h"
+
+int btn0_setup(struct uinput_user_dev *dev, int fd)
+{
+ if (ioctl(fd, UI_SET_EVBIT, EV_KEY) == -1) goto error;
+ if (ioctl(fd, UI_SET_EVBIT, EV_REL) == -1) goto error;
+ if (ioctl(fd, UI_SET_EVBIT, EV_SYN) == -1) goto error;
+
+ /* buttons */
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_0) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_1) == -1) goto error;
+ if (ioctl(fd, UI_SET_KEYBIT, BTN_2) == -1) goto error;
+
+ /* axes */
+ if (ioctl(fd, UI_SET_RELBIT, REL_X) == -1) goto error;
+ if (ioctl(fd, UI_SET_RELBIT, REL_Y) == -1) goto error;
+
+ return 0;
+error:
+ perror("ioctl failed.");
+ return -1;
+}
+
+int btn0_run(int fd)
+{
+ move(fd, -10, 0);
+ usleep(1000);
+ move(fd, 0, -10);
+ usleep(1000);
+ move(fd, 10, 0);
+ usleep(1000);
+ move(fd, 0, 10);
+ usleep(1000);
+ click(fd, BTN_0, 1);
+ usleep(1000);
+ click(fd, BTN_0, 0);
+ return 0;
+}
+
+struct test_device btn0_dev = {
+ .name = "BTN_0 test device",
+ .setup = btn0_setup,
+ .run = btn0_run,
+};
+
+
+struct test_device* get_device()
+{
+ return &btn0_dev;
+}
diff --git a/test/fakedev.c b/test/fakedev.c
new file mode 100644
index 0000000..a3a1b81
--- /dev/null
+++ b/test/fakedev.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2008 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ *
+ * Authors:
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <dlfcn.h>
+
+#include "fakedev.h"
+
+/* "public interfaces" */
+
+void send_event(int fd, int type, int code, int value)
+{
+ struct input_event event;
+
+ event.type = type;
+ event.code = code;
+ event.value = value;
+ gettimeofday(&event.time, NULL);
+
+ if (write(fd, &event, sizeof(event)) < sizeof(event))
+ perror("Send event failed.");
+}
+
+
+void move(int fd, int x, int y)
+{
+ if (!x && !y)
+ return;
+
+ send_event(fd, EV_REL, REL_X, x);
+ send_event(fd, EV_REL, REL_Y, y);
+ send_event(fd, EV_SYN, SYN_REPORT, 0);
+}
+
+void absmove(int fd, int x, int y)
+{
+ send_event(fd, EV_ABS, ABS_X, x);
+ send_event(fd, EV_ABS, ABS_Y, y);
+ send_event(fd, EV_SYN, SYN_REPORT, 0);
+}
+
+void click(int fd, int btn, int down)
+{
+ send_event(fd, EV_KEY, btn, down);
+ send_event(fd, EV_SYN, SYN_REPORT, 0);
+}
+
+
+
+/* end public interfaces */
+
+static int fd = -1;
+static int stop = 0;
+
+static void sighandler(int signum)
+{
+ printf("Stopping.\n");
+ stop = 1;
+}
+
+static void init_signal(void)
+{
+ struct sigaction action;
+ sigset_t mask;
+
+ sigfillset(&mask);
+
+ action.sa_handler = sighandler;
+ action.sa_mask = mask;
+ action.sa_flags = 0;
+
+ sigaction(SIGTERM, &action, NULL);
+ sigaction(SIGINT, &action, NULL);
+ sigprocmask(SIG_UNBLOCK, &mask, 0);
+}
+
+
+static int init_uinput(struct test_device* test_dev)
+{
+ struct uinput_user_dev dev;
+
+ fd = open("/dev/input/uinput", O_RDWR);
+ if (fd < 0)
+ goto error;
+
+ memset(&dev, 0, sizeof(dev));
+ strcpy(dev.name, test_dev->name);
+ dev.id.bustype = 0;
+ dev.id.vendor = 0x1F;
+ dev.id.product = 0x1F;
+ dev.id.version = 0;
+
+
+ test_dev->setup(&dev, fd);
+
+ if (write(fd, &dev, sizeof(dev)) < sizeof(dev))
+ goto error;
+ if (ioctl(fd, UI_DEV_CREATE, NULL) == -1) goto error;
+
+ return 0;
+
+error:
+ fprintf(stderr, "Error: %s\n", strerror(errno));
+
+ if (fd != -1)
+ close(fd);
+
+ return -1;
+}
+
+static void cleanup_uinput(void)
+{
+ if (fd == -1)
+ return;
+
+ ioctl(fd, UI_DEV_DESTROY, NULL);
+ close(fd);
+ fd = -1;
+}
+
+
+int main (int argc, char **argv)
+{
+ struct test_device *dev;
+ void *dlhandle = NULL;
+ struct test_device* (*get_device)(void);
+
+ if (argc <= 1)
+ {
+ fprintf(stderr, "Usage: %s test_dev\n", argv[0]);
+ return -1;
+ }
+
+ printf("Loading %s.\n", argv[1]);
+
+ dlhandle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+ if (!dlhandle)
+ {
+ fprintf(stderr, "Error: %s\n", dlerror());
+ return -1;
+ }
+
+ *(void**)(&get_device) = dlsym(dlhandle, "get_device");
+ if (!get_device)
+ {
+ fprintf(stderr, "Error getting the symbol: %s.\n", dlerror());
+ return -1;
+ }
+
+ dev = (*get_device)();
+
+ if (init_uinput(dev) < 0) {
+ fprintf(stderr, "Failed to initialize /dev/uinput. Exiting.\n");
+ return -1;
+ }
+
+ init_signal();
+
+ printf("Device created. Press CTRL+C to terminate.\n");
+ while (!stop) {
+ if (dev->run(fd))
+ break;
+ }
+
+ cleanup_uinput();
+
+ return 0;
+}
+
diff --git a/test/fakedev.h b/test/fakedev.h
new file mode 100644
index 0000000..465722a
--- /dev/null
+++ b/test/fakedev.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2008 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 Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission. Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS 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.
+ *
+ * Authors:
+ * Peter Hutterer (peter.hutterer@redhat.com)
+ */
+
+#ifndef _EVDEV_TEST_H
+#define _EVDEV_TEST_H
+#include <linux/uinput.h>
+
+struct test_device {
+ char *name; /* device name */
+ /**
+ * Called to setup the device. Call ioctls to set your EVBITs, KEYBITs,
+ * etc. here. Return 0 on success or non-zero to exit.
+ */
+ int (*setup)(struct uinput_user_dev* dev, int fd);
+
+ /**
+ * Called during each run of the main loop. Generate events by calling
+ * move(), click(), etc.
+ * Return 0 on success, or non-zero to stop the main loop.
+ */
+ int (*run)(int fd);
+};
+
+extern void move (int fd, int x, int y);
+extern void absmove (int fd, int x, int y);
+extern void click (int fd, int btn, int down);
+
+#endif