[PATCH libevdev 2/2] wrap EVIOCSCLOCKID into an API call

Peter Hutterer peter.hutterer at who-t.net
Thu Sep 12 16:53:57 PDT 2013


Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 libevdev/libevdev.c       |  11 +++++
 libevdev/libevdev.h       |  16 +++++++
 test/test-libevdev-init.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 135 insertions(+)

diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
index 6f7e2a6..e1bb6d0 100644
--- a/libevdev/libevdev.c
+++ b/libevdev/libevdev.c
@@ -1422,3 +1422,14 @@ libevdev_kernel_set_led_values(struct libevdev *dev, ...)
 
 	return rc;
 }
+
+LIBEVDEV_EXPORT int
+libevdev_set_clock_id(struct libevdev *dev, int clockid)
+{
+	if (dev->fd < 0) {
+		log_bug("device not initialized. call libevdev_set_fd() first\n");
+		return -EBADF;
+	}
+
+	return ioctl(dev->fd, EVIOCSCLOCKID, &clockid) ? -errno : 0;
+}
diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
index 704f85e..bfb0f37 100644
--- a/libevdev/libevdev.h
+++ b/libevdev/libevdev.h
@@ -1278,6 +1278,22 @@ int libevdev_kernel_set_led_value(struct libevdev *dev, unsigned int code, enum
 int libevdev_kernel_set_led_values(struct libevdev *dev, ...);
 
 /**
+ * @ingroup kernel
+ *
+ * Set the clock ID to be used for timestamps. Further events from this device
+ * will report an event time based on the given clock.
+ *
+ * This is a modification only affecting this representation of
+ * this device.
+ *
+ * @param dev The evdev device, already initialized with libevdev_set_fd()
+ * @param clockid The clock to use for future events. Permitted values
+ * are CLOCK_MONOTONIC and CLOCK_REALTIME (the default).
+ * @return zero on success, or a negative errno on failure
+ */
+int libevdev_set_clock_id(struct libevdev *dev, int clockid);
+
+/**
  * @ingroup misc
  *
  * Helper function to check if an event is of a specific type. This is
diff --git a/test/test-libevdev-init.c b/test/test-libevdev-init.c
index 243da23..7d4376d 100644
--- a/test/test-libevdev-init.c
+++ b/test/test-libevdev-init.c
@@ -23,7 +23,12 @@
 #include <config.h>
 #include <errno.h>
 #include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
+#include <libevdev/libevdev-uinput.h>
 #include "test-common.h"
 
 START_TEST(test_new_device)
@@ -260,6 +265,104 @@ START_TEST(test_device_grab)
 }
 END_TEST
 
+START_TEST(test_set_clock_id)
+{
+	struct uinput_device* uidev;
+	struct libevdev *dev;
+	int rc;
+
+	rc = test_create_device(&uidev, &dev,
+				EV_SYN, SYN_REPORT,
+				EV_REL, REL_X,
+				EV_REL, REL_Y,
+				EV_REL, REL_WHEEL,
+				EV_KEY, BTN_LEFT,
+				EV_KEY, BTN_MIDDLE,
+				EV_KEY, BTN_RIGHT,
+				-1);
+	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+	rc = libevdev_set_clock_id(dev, CLOCK_REALTIME);
+	ck_assert_int_eq(rc, 0);
+
+	rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
+	ck_assert_int_eq(rc, 0);
+
+	rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC_RAW);
+	ck_assert_int_eq(rc, -EINVAL);
+
+	uinput_device_free(uidev);
+	libevdev_free(dev);
+}
+END_TEST
+
+START_TEST(test_clock_id_events)
+{
+	struct uinput_device* uidev;
+	struct libevdev *dev, *dev2;
+	int rc, fd;
+	struct input_event ev1, ev2;
+	struct timespec t1_real, t2_real;
+	struct timespec t1_mono, t2_mono;
+
+	rc = test_create_device(&uidev, &dev,
+				EV_SYN, SYN_REPORT,
+				EV_REL, REL_X,
+				EV_REL, REL_Y,
+				EV_REL, REL_WHEEL,
+				EV_KEY, BTN_LEFT,
+				EV_KEY, BTN_MIDDLE,
+				EV_KEY, BTN_RIGHT,
+				-1);
+	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+	fd = open(uinput_device_get_devnode(uidev), O_RDONLY);
+	ck_assert_int_gt(fd, -1);
+
+	rc = libevdev_new_from_fd(fd, &dev2);
+	ck_assert_msg(rc == 0, "Failed to create second device: %s", strerror(-rc));
+
+	rc = libevdev_set_clock_id(dev2, CLOCK_MONOTONIC);
+	ck_assert_int_eq(rc, 0);
+
+	clock_gettime(CLOCK_REALTIME, &t1_real);
+	clock_gettime(CLOCK_MONOTONIC, &t1_mono);
+	uinput_device_event(uidev, EV_REL, REL_X, 1);
+	uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
+	clock_gettime(CLOCK_REALTIME, &t2_real);
+	clock_gettime(CLOCK_MONOTONIC, &t2_mono);
+
+	rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1);
+	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
+
+	rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2);
+	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
+
+	ck_assert_int_eq(ev1.type, ev2.type);
+	ck_assert_int_eq(ev1.code, ev2.code);
+	ck_assert_int_eq(ev1.value, ev2.value);
+
+	ck_assert_int_ne(ev1.time.tv_sec, ev2.time.tv_sec);
+	ck_assert_int_ne(ev1.time.tv_usec, ev2.time.tv_usec);
+
+	ck_assert_int_ge(ev1.time.tv_sec, t1_real.tv_sec);
+	ck_assert_int_ge(ev1.time.tv_usec, t1_real.tv_nsec/1000);
+	ck_assert_int_le(ev1.time.tv_sec, t2_real.tv_sec);
+	ck_assert_int_le(ev1.time.tv_usec, t2_real.tv_nsec/1000);
+
+	ck_assert_int_ge(ev2.time.tv_sec, t1_mono.tv_sec);
+	ck_assert_int_ge(ev2.time.tv_usec, t1_mono.tv_nsec/1000);
+	ck_assert_int_le(ev2.time.tv_sec, t2_mono.tv_sec);
+	ck_assert_int_le(ev2.time.tv_usec, t2_mono.tv_nsec/1000);
+
+	uinput_device_free(uidev);
+	libevdev_free(dev);
+	libevdev_free(dev2);
+	close(fd);
+}
+END_TEST
+
+
 Suite *
 libevdev_init_test(void)
 {
@@ -286,5 +389,10 @@ libevdev_init_test(void)
 	tcase_add_test(tc, test_device_grab);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("clock id");
+	tcase_add_test(tc, test_set_clock_id);
+	tcase_add_test(tc, test_clock_id_events);
+	suite_add_tcase(s, tc);
+
 	return s;
 }
-- 
1.8.3.1



More information about the Input-tools mailing list