[PATCH libevdev 1/6] Add libevdev_has_event_pending()

Peter Hutterer peter.hutterer at who-t.net
Sun Jul 28 22:34:32 PDT 2013


Returns non-zero if there are events avialable to be read.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 libevdev/libevdev.c         | 16 ++++++++++++++++
 libevdev/libevdev.h         | 24 ++++++++++++++++++++++++
 test/test-libevdev-events.c | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
index e474835..cd33659 100644
--- a/libevdev/libevdev.c
+++ b/libevdev/libevdev.c
@@ -22,6 +22,7 @@
 
 #include <config.h>
 #include <errno.h>
+#include <poll.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -626,6 +627,21 @@ out:
 	return rc;
 }
 
+int libevdev_has_event_pending(struct libevdev *dev)
+{
+	struct pollfd fds = { dev->fd, POLLIN, 0 };
+	int rc;
+
+	if (dev->fd < 0)
+		return -EBADF;
+
+	if (queue_num_elements(dev) != 0)
+		return 1;
+
+	rc = poll(&fds, 1, 0);
+	return (rc >= 0) ? rc : -errno;
+}
+
 const char *
 libevdev_get_name(const struct libevdev *dev)
 {
diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
index 606501b..d637c29 100644
--- a/libevdev/libevdev.h
+++ b/libevdev/libevdev.h
@@ -483,6 +483,30 @@ int libevdev_get_fd(const struct libevdev* dev);
 int libevdev_next_event(struct libevdev *dev, unsigned int flags, struct input_event *ev);
 
 /**
+ * @ingroup events
+ *
+ * Check if there are events waiting for us. This does not read an event off
+ * the fd and may not access the fd at all. If there are events queued
+ * internally this function will return non-zero. If the internal queue is empty,
+ * this function will poll the file descriptor for data.
+ *
+ * This is a convenience function for simple processes, most complex programs
+ * are expected to use select(2) or poll(2) on the file descriptor. The kernel
+ * guarantees that if data is available, it is a multiple of sizeof(struct
+ * input_event), and thus calling libevdev_next_event() when select(2) or
+ * poll(2) return is safe. You do not need libevdev_has_event_pending() if
+ * you're using select(2) or poll(2).
+ *
+ * @param dev The evdev device, already initialized with libevdev_set_fd()
+ * @return On failure, a negative errno is returned.
+ * @retval 0 No event is currently available
+ * @retval 1 One or more events are available on the fd
+ *
+ * @note This function is signal-safe.
+ */
+int libevdev_has_event_pending(struct libevdev *dev);
+
+/**
  * @ingroup bits
  *
  * @param dev The evdev device, already initialized with libevdev_set_fd()
diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c
index 65eb1fa..40f94dd 100644
--- a/test/test-libevdev-events.c
+++ b/test/test-libevdev-events.c
@@ -199,6 +199,45 @@ START_TEST(test_event_code_filtered)
 }
 END_TEST
 
+START_TEST(test_has_event_pending)
+{
+	struct uinput_device* uidev;
+	struct libevdev *dev;
+	int rc;
+	struct input_event ev;
+
+	rc = test_create_device(&uidev, &dev,
+				EV_REL, REL_X,
+				EV_REL, REL_Y,
+				EV_KEY, BTN_LEFT,
+				-1);
+	ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
+
+	ck_assert_int_eq(libevdev_has_event_pending(dev), 0);
+
+	uinput_device_event(uidev, EV_REL, REL_X, 1);
+	uinput_device_event(uidev, EV_REL, REL_Y, 1);
+	uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
+
+	ck_assert_int_eq(libevdev_has_event_pending(dev), 1);
+
+	libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, &ev);
+
+	ck_assert_int_eq(libevdev_has_event_pending(dev), 1);
+
+	while ((rc = libevdev_next_event(dev, LIBEVDEV_READ_NORMAL, &ev)) != -EAGAIN)
+			;
+
+	ck_assert_int_eq(libevdev_has_event_pending(dev), 0);
+
+	libevdev_change_fd(dev, -1);
+	ck_assert_int_eq(libevdev_has_event_pending(dev), -EBADF);
+
+	libevdev_free(dev);
+	uinput_device_free(uidev);
+
+}
+END_TEST
 START_TEST(test_syn_delta_button)
 {
 	struct uinput_device* uidev;
@@ -777,6 +816,7 @@ libevdev_events(void)
 	tcase_add_test(tc, test_syn_event);
 	tcase_add_test(tc, test_event_type_filtered);
 	tcase_add_test(tc, test_event_code_filtered);
+	tcase_add_test(tc, test_has_event_pending);
 	suite_add_tcase(s, tc);
 
 	tc = tcase_create("SYN_DROPPED deltas");
-- 
1.8.2.1



More information about the Input-tools mailing list