mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-20 05:40:05 +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>
704 lines
18 KiB
C
704 lines
18 KiB
C
// SPDX-License-Identifier: MIT
|
|
/*
|
|
* Copyright © 2013 Red Hat, Inc.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <errno.h>
|
|
#include <inttypes.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)
|
|
{
|
|
struct libevdev *dev;
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_free_device)
|
|
{
|
|
libevdev_free(NULL);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_init_from_invalid_fd)
|
|
{
|
|
int rc;
|
|
struct libevdev *dev = NULL;
|
|
|
|
rc = libevdev_new_from_fd(-1, &dev);
|
|
|
|
ck_assert(dev == NULL);
|
|
ck_assert_int_eq(rc, -EBADF);
|
|
|
|
rc = libevdev_new_from_fd(STDIN_FILENO, &dev);
|
|
ck_assert(dev == NULL);
|
|
ck_assert_int_eq(rc, -ENOTTY);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_init_and_change_fd)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int rc;
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
ck_assert_int_eq(libevdev_set_fd(dev, -1), -EBADF);
|
|
|
|
libevdev_set_log_function(test_logfunc_ignore_error, NULL);
|
|
ck_assert_int_eq(libevdev_change_fd(dev, -1), -1);
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
rc = uinput_device_new_with_events(&uidev,
|
|
TEST_DEVICE_NAME, DEFAULT_IDS,
|
|
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 uinput device: %s", strerror(-rc));
|
|
ck_assert_int_eq(libevdev_set_fd(dev, uinput_device_get_fd(uidev)), 0);
|
|
|
|
libevdev_set_log_function(test_logfunc_ignore_error, NULL);
|
|
ck_assert_int_eq(libevdev_set_fd(dev, 0), -EBADF);
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
ck_assert_int_eq(libevdev_get_fd(dev), uinput_device_get_fd(uidev));
|
|
|
|
ck_assert_int_eq(libevdev_change_fd(dev, 0), 0);
|
|
ck_assert_int_eq(libevdev_get_fd(dev), 0);
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
static int log_fn_called = 0;
|
|
static char *logdata = "test";
|
|
static void logfunc(enum libevdev_log_priority priority,
|
|
void *data,
|
|
const char *file, int line, const char *func,
|
|
const char *f, va_list args) {
|
|
ck_assert_int_eq(strcmp(logdata, data), 0);
|
|
log_fn_called++;
|
|
}
|
|
|
|
START_TEST(test_log_init)
|
|
{
|
|
struct libevdev *dev = NULL;
|
|
enum libevdev_log_priority old;
|
|
|
|
old = libevdev_get_log_priority();
|
|
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_DEBUG);
|
|
|
|
libevdev_set_log_function(logfunc, NULL);
|
|
libevdev_set_log_function(NULL, NULL);
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
|
|
libevdev_set_log_function(logfunc, logdata);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
libevdev_set_log_function(NULL, NULL);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
libevdev_set_log_function(logfunc, logdata);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
/* libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL) should
|
|
trigger a log message. We called it three times, but only twice
|
|
with the logfunc set, thus, ensure we only called the logfunc
|
|
twice */
|
|
ck_assert_int_eq(log_fn_called, 2);
|
|
|
|
libevdev_free(dev);
|
|
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
log_fn_called = 0;
|
|
|
|
libevdev_set_log_priority(old);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_log_default_priority)
|
|
{
|
|
ck_assert_int_eq(libevdev_get_log_priority(), LIBEVDEV_LOG_INFO);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_log_set_get_priority)
|
|
{
|
|
enum libevdev_log_priority pri;
|
|
enum libevdev_log_priority old;
|
|
|
|
old = libevdev_get_log_priority();
|
|
|
|
pri = LIBEVDEV_LOG_DEBUG;
|
|
libevdev_set_log_priority(pri);
|
|
ck_assert_int_eq(libevdev_get_log_priority(), pri);
|
|
|
|
pri = LIBEVDEV_LOG_INFO;
|
|
libevdev_set_log_priority(pri);
|
|
ck_assert_int_eq(libevdev_get_log_priority(), pri);
|
|
|
|
pri = LIBEVDEV_LOG_ERROR;
|
|
libevdev_set_log_priority(pri);
|
|
ck_assert_int_eq(libevdev_get_log_priority(), pri);
|
|
|
|
/* debug and above is clamped */
|
|
pri = LIBEVDEV_LOG_DEBUG + 1;
|
|
libevdev_set_log_priority(pri);
|
|
ck_assert_int_eq(libevdev_get_log_priority(), LIBEVDEV_LOG_DEBUG);
|
|
|
|
/* error and below is not clamped, we need this for another test */
|
|
pri = LIBEVDEV_LOG_ERROR - 1;
|
|
libevdev_set_log_priority(pri);
|
|
ck_assert_int_eq(libevdev_get_log_priority(), pri);
|
|
|
|
libevdev_set_log_priority(old);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_log_priority)
|
|
{
|
|
struct libevdev *dev = NULL;
|
|
enum libevdev_log_priority old;
|
|
|
|
old = libevdev_get_log_priority();
|
|
|
|
libevdev_set_log_function(logfunc, logdata);
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_DEBUG);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 1);
|
|
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_INFO);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 2);
|
|
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_ERROR);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 3);
|
|
|
|
/* we don't have any log msgs > ERROR at the moment, so test it by
|
|
setting an invalid priority. */
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_ERROR - 1);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 3);
|
|
|
|
libevdev_free(dev);
|
|
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
log_fn_called = 0;
|
|
|
|
libevdev_set_log_priority(old);
|
|
}
|
|
END_TEST
|
|
|
|
static char *logdata_1 = "foo";
|
|
static char *logdata_2 = "bar";
|
|
static int log_data_fn_called = 0;
|
|
static void logfunc_data(enum libevdev_log_priority priority,
|
|
void *data,
|
|
const char *file, int line, const char *func,
|
|
const char *f, va_list args) {
|
|
switch(log_data_fn_called) {
|
|
case 0: ck_assert(data == logdata_1); break;
|
|
case 1: ck_assert(data == logdata_2); break;
|
|
case 2: ck_assert(data == NULL); break;
|
|
default:
|
|
ck_abort();
|
|
}
|
|
log_data_fn_called++;
|
|
}
|
|
|
|
START_TEST(test_log_data)
|
|
{
|
|
struct libevdev *dev = NULL;
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
|
|
libevdev_set_log_function(logfunc_data, logdata_1);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
libevdev_set_log_function(logfunc_data, logdata_2);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
libevdev_set_log_function(logfunc_data, NULL);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
struct libevdev *devlogdata;
|
|
static int dev_log_fn_called = 0;
|
|
static void devlogfunc(const struct libevdev *dev,
|
|
enum libevdev_log_priority priority,
|
|
void *data,
|
|
const char *file, int line, const char *func,
|
|
const char *f, va_list args)
|
|
{
|
|
ck_assert(dev == data);
|
|
dev_log_fn_called++;
|
|
}
|
|
|
|
START_TEST(test_device_log_init)
|
|
{
|
|
struct libevdev *dev = NULL;
|
|
enum libevdev_log_priority old;
|
|
|
|
old = libevdev_get_log_priority();
|
|
libevdev_set_log_priority(LIBEVDEV_LOG_DEBUG);
|
|
libevdev_set_log_function(logfunc, logdata);
|
|
|
|
/* error for NULL device */
|
|
libevdev_set_device_log_function(NULL, NULL,
|
|
LIBEVDEV_LOG_ERROR, NULL);
|
|
ck_assert_int_eq(log_fn_called, 1);
|
|
|
|
/* error for NULL device */
|
|
libevdev_set_device_log_function(NULL, devlogfunc,
|
|
LIBEVDEV_LOG_ERROR, NULL);
|
|
ck_assert_int_eq(log_fn_called, 2);
|
|
|
|
log_fn_called = 0;
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
|
|
libevdev_set_device_log_function(dev, NULL,
|
|
LIBEVDEV_LOG_ERROR, NULL);
|
|
|
|
/* libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL) should
|
|
trigger a log message. */
|
|
|
|
/* expect global handler triggered */
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 1);
|
|
ck_assert_int_eq(dev_log_fn_called, 0);
|
|
|
|
/* expect device handler triggered */
|
|
libevdev_set_device_log_function(dev, devlogfunc,
|
|
LIBEVDEV_LOG_ERROR, dev);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 1);
|
|
ck_assert_int_eq(dev_log_fn_called, 1);
|
|
|
|
/* device handler set, but priority filters. don't expect any log
|
|
handler to be called.
|
|
we don't have any log msgs > ERROR at the moment, so test it by
|
|
setting an invalid priority. */
|
|
libevdev_set_device_log_function(dev, devlogfunc,
|
|
LIBEVDEV_LOG_ERROR - 1, dev);
|
|
libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, NULL);
|
|
ck_assert_int_eq(log_fn_called, 1);
|
|
ck_assert_int_eq(dev_log_fn_called, 1);
|
|
|
|
libevdev_free(dev);
|
|
|
|
log_fn_called = 0;
|
|
libevdev_set_log_priority(old);
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_device_init)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int rc;
|
|
|
|
rc = uinput_device_new_with_events(&uidev,
|
|
TEST_DEVICE_NAME, DEFAULT_IDS,
|
|
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 uinput device: %s", strerror(-rc));
|
|
|
|
dev = libevdev_new();
|
|
ck_assert(dev != NULL);
|
|
rc = libevdev_set_fd(dev, uinput_device_get_fd(uidev));
|
|
ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_device_init_from_fd)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int rc;
|
|
|
|
rc = uinput_device_new_with_events(&uidev,
|
|
TEST_DEVICE_NAME, DEFAULT_IDS,
|
|
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 uinput device: %s", strerror(-rc));
|
|
|
|
rc = libevdev_new_from_fd(uinput_device_get_fd(uidev), &dev);
|
|
ck_assert_msg(rc == 0, "Failed to init device: %s", strerror(-rc));;
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_device_grab)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int 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);
|
|
|
|
libevdev_set_log_function(test_logfunc_ignore_error, NULL);
|
|
rc = libevdev_grab(dev, 0);
|
|
ck_assert_int_eq(rc, -EINVAL);
|
|
rc = libevdev_grab(dev, 1);
|
|
ck_assert_int_eq(rc, -EINVAL);
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
rc = libevdev_grab(dev, LIBEVDEV_UNGRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
rc = libevdev_grab(dev, LIBEVDEV_UNGRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_device_grab_invalid_fd)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int rc;
|
|
|
|
libevdev_set_log_function(test_logfunc_ignore_error, NULL);
|
|
|
|
dev = libevdev_new();
|
|
rc = libevdev_grab(dev, 0);
|
|
ck_assert_int_eq(rc, -EBADF);
|
|
libevdev_free(dev);
|
|
|
|
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);
|
|
libevdev_change_fd(dev, -2);
|
|
rc = libevdev_grab(dev, 0);
|
|
ck_assert_int_eq(rc, -EBADF);
|
|
|
|
libevdev_set_log_function(test_logfunc_abort_on_error, NULL);
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_device_grab_change_fd)
|
|
{
|
|
struct libevdev_uinput *uidev;
|
|
struct libevdev *dev, *other;
|
|
struct input_event e;
|
|
int rc;
|
|
int other_fd;
|
|
int dev_fd;
|
|
|
|
dev = libevdev_new();
|
|
libevdev_set_name(dev, "libevdev test device");
|
|
libevdev_enable_event_code(dev, EV_REL, REL_X, NULL);
|
|
libevdev_enable_event_code(dev, EV_REL, REL_Y, NULL);
|
|
libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
|
|
|
|
rc = libevdev_uinput_create_from_device(dev,
|
|
LIBEVDEV_UINPUT_OPEN_MANAGED,
|
|
&uidev);
|
|
ck_assert_int_eq(rc, 0);
|
|
libevdev_free(dev);
|
|
|
|
dev_fd = open(libevdev_uinput_get_devnode(uidev),
|
|
O_RDONLY|O_NONBLOCK);
|
|
ck_assert_int_ne(dev_fd, -1);
|
|
rc = libevdev_new_from_fd(dev_fd, &dev);
|
|
ck_assert_int_eq(rc, 0);
|
|
|
|
other_fd = open(libevdev_uinput_get_devnode(uidev),
|
|
O_RDONLY|O_NONBLOCK);
|
|
ck_assert_int_ne(other_fd, -1);
|
|
rc = libevdev_new_from_fd(other_fd, &other);
|
|
ck_assert_int_eq(rc, 0);
|
|
|
|
/* check we're getting the events before the grab */
|
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, -EAGAIN);
|
|
|
|
/* no events after the grab */
|
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, -EAGAIN);
|
|
|
|
/* swapping the fd removes the grab */
|
|
close(dev_fd);
|
|
dev_fd = open(libevdev_uinput_get_devnode(uidev),
|
|
O_RDONLY|O_NONBLOCK);
|
|
ck_assert_int_ne(dev_fd, -1);
|
|
rc = libevdev_change_fd(dev, dev_fd);
|
|
ck_assert_int_eq(rc, 0);
|
|
|
|
/* check we're getting the events again */
|
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, -EAGAIN);
|
|
|
|
/* no events after the grab */
|
|
rc = libevdev_grab(dev, LIBEVDEV_GRAB);
|
|
ck_assert_int_eq(rc, 0);
|
|
libevdev_uinput_write_event(uidev, EV_REL, REL_X, -1);
|
|
libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
|
|
rc = libevdev_next_event(other, LIBEVDEV_READ_FLAG_NORMAL, &e);
|
|
ck_assert_int_eq(rc, -EAGAIN);
|
|
|
|
libevdev_uinput_destroy(uidev);
|
|
libevdev_free(dev);
|
|
libevdev_free(other);
|
|
close(dev_fd);
|
|
close(other_fd);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_set_clock_id)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int clockid;
|
|
int 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);
|
|
|
|
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);
|
|
|
|
#ifdef __FreeBSD__
|
|
clockid = CLOCK_MONOTONIC_FAST;
|
|
#else
|
|
clockid = CLOCK_MONOTONIC_RAW;
|
|
#endif
|
|
|
|
rc = libevdev_set_clock_id(dev, clockid);
|
|
ck_assert_int_eq(rc, -EINVAL);
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
}
|
|
END_TEST
|
|
|
|
START_TEST(test_set_clock_id_invalid_fd)
|
|
{
|
|
struct uinput_device* uidev;
|
|
struct libevdev *dev;
|
|
int rc;
|
|
|
|
libevdev_set_log_function(test_logfunc_ignore_error, NULL);
|
|
|
|
dev = libevdev_new();
|
|
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
|
|
ck_assert_int_eq(rc, -EBADF);
|
|
libevdev_free(dev);
|
|
|
|
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);
|
|
libevdev_change_fd(dev, -2);
|
|
rc = libevdev_set_clock_id(dev, CLOCK_MONOTONIC);
|
|
ck_assert_int_eq(rc, -EBADF);
|
|
|
|
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;
|
|
int64_t t1, t2;
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
t1 = ev1.input_event_sec * 1000000LL + ev1.input_event_usec;
|
|
t2 = ev2.input_event_sec * 1000000LL + ev2.input_event_usec;
|
|
ck_assert_int_ne(t1, t2);
|
|
|
|
ck_assert_int_ge(ev1.input_event_sec, t1_real.tv_sec);
|
|
ck_assert_int_ge(ev1.input_event_usec, t1_real.tv_nsec/1000);
|
|
ck_assert_int_le(ev1.input_event_sec, t2_real.tv_sec);
|
|
ck_assert_int_le(ev1.input_event_usec, t2_real.tv_nsec/1000);
|
|
|
|
ck_assert_int_ge(ev2.input_event_sec, t1_mono.tv_sec);
|
|
ck_assert_int_ge(ev2.input_event_usec, t1_mono.tv_nsec/1000);
|
|
ck_assert_int_le(ev2.input_event_sec, t2_mono.tv_sec);
|
|
ck_assert_int_le(ev2.input_event_usec, t2_mono.tv_nsec/1000);
|
|
|
|
uinput_device_free(uidev);
|
|
libevdev_free(dev);
|
|
libevdev_free(dev2);
|
|
close(fd);
|
|
}
|
|
END_TEST
|
|
|
|
TEST_SUITE_ROOT_PRIVILEGES(libevdev_init_test)
|
|
{
|
|
Suite *s = suite_create("libevdev init tests");
|
|
|
|
add_test(s, test_new_device);
|
|
add_test(s, test_free_device);
|
|
add_test(s, test_init_from_invalid_fd);
|
|
add_test(s, test_init_and_change_fd);
|
|
|
|
add_test(s, test_log_init);
|
|
add_test(s, test_log_priority);
|
|
add_test(s, test_log_set_get_priority);
|
|
add_test(s, test_log_default_priority);
|
|
add_test(s, test_log_data);
|
|
add_test(s, test_device_log_init);
|
|
|
|
add_test(s, test_device_init);
|
|
add_test(s, test_device_init_from_fd);
|
|
|
|
add_test(s, test_device_grab);
|
|
add_test(s, test_device_grab_invalid_fd);
|
|
add_test(s, test_device_grab_change_fd);
|
|
|
|
add_test(s, test_set_clock_id);
|
|
add_test(s, test_set_clock_id_invalid_fd);
|
|
add_test(s, test_clock_id_events);
|
|
|
|
return s;
|
|
}
|