1c0abf9e6Sopenharmony_ci// SPDX-License-Identifier: MIT 2c0abf9e6Sopenharmony_ci/* 3c0abf9e6Sopenharmony_ci * Copyright © 2014 Red Hat, Inc. 4c0abf9e6Sopenharmony_ci */ 5c0abf9e6Sopenharmony_ci 6c0abf9e6Sopenharmony_ci#include "config.h" 7c0abf9e6Sopenharmony_ci#include <errno.h> 8c0abf9e6Sopenharmony_ci#include <inttypes.h> 9c0abf9e6Sopenharmony_ci#include <unistd.h> 10c0abf9e6Sopenharmony_ci#include <time.h> 11c0abf9e6Sopenharmony_ci#include <sys/types.h> 12c0abf9e6Sopenharmony_ci#include <sys/stat.h> 13c0abf9e6Sopenharmony_ci#include <fcntl.h> 14c0abf9e6Sopenharmony_ci#include <stdio.h> 15c0abf9e6Sopenharmony_ci#include <linux/input.h> 16c0abf9e6Sopenharmony_ci 17c0abf9e6Sopenharmony_ci#include <libevdev/libevdev.h> 18c0abf9e6Sopenharmony_ci#include <libevdev/libevdev-uinput.h> 19c0abf9e6Sopenharmony_ci#include "test-common.h" 20c0abf9e6Sopenharmony_ci 21c0abf9e6Sopenharmony_ciSTART_TEST(test_revoke) 22c0abf9e6Sopenharmony_ci{ 23c0abf9e6Sopenharmony_ci struct uinput_device* uidev; 24c0abf9e6Sopenharmony_ci struct libevdev *dev, *dev2; 25c0abf9e6Sopenharmony_ci int rc, fd; 26c0abf9e6Sopenharmony_ci struct input_event ev1, ev2; 27c0abf9e6Sopenharmony_ci int dev_fd; 28c0abf9e6Sopenharmony_ci 29c0abf9e6Sopenharmony_ci test_create_device(&uidev, &dev, 30c0abf9e6Sopenharmony_ci EV_SYN, SYN_REPORT, 31c0abf9e6Sopenharmony_ci EV_REL, REL_X, 32c0abf9e6Sopenharmony_ci EV_REL, REL_Y, 33c0abf9e6Sopenharmony_ci EV_REL, REL_WHEEL, 34c0abf9e6Sopenharmony_ci EV_KEY, BTN_LEFT, 35c0abf9e6Sopenharmony_ci EV_KEY, BTN_MIDDLE, 36c0abf9e6Sopenharmony_ci EV_KEY, BTN_RIGHT, 37c0abf9e6Sopenharmony_ci -1); 38c0abf9e6Sopenharmony_ci 39c0abf9e6Sopenharmony_ci fd = open(uinput_device_get_devnode(uidev), O_RDONLY|O_NONBLOCK); 40c0abf9e6Sopenharmony_ci ck_assert_int_gt(fd, -1); 41c0abf9e6Sopenharmony_ci rc = libevdev_new_from_fd(fd, &dev2); 42c0abf9e6Sopenharmony_ci ck_assert_msg(rc == 0, "Failed to create second device: %s", strerror(-rc)); 43c0abf9e6Sopenharmony_ci 44c0abf9e6Sopenharmony_ci uinput_device_event(uidev, EV_REL, REL_X, 1); 45c0abf9e6Sopenharmony_ci uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); 46c0abf9e6Sopenharmony_ci 47c0abf9e6Sopenharmony_ci for (int i = 0; i < 2; i++) { 48c0abf9e6Sopenharmony_ci rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1); 49c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); 50c0abf9e6Sopenharmony_ci 51c0abf9e6Sopenharmony_ci rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2); 52c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); 53c0abf9e6Sopenharmony_ci 54c0abf9e6Sopenharmony_ci ck_assert_int_eq(ev1.type, ev2.type); 55c0abf9e6Sopenharmony_ci ck_assert_int_eq(ev1.code, ev2.code); 56c0abf9e6Sopenharmony_ci ck_assert_int_eq(ev1.value, ev2.value); 57c0abf9e6Sopenharmony_ci } 58c0abf9e6Sopenharmony_ci 59c0abf9e6Sopenharmony_ci /* revoke first device, expect it closed, second device still open */ 60c0abf9e6Sopenharmony_ci dev_fd = libevdev_get_fd(dev); 61c0abf9e6Sopenharmony_ci ck_assert_int_ge(dev_fd, 0); 62c0abf9e6Sopenharmony_ci rc = ioctl(dev_fd, EVIOCREVOKE, NULL); 63c0abf9e6Sopenharmony_ci if (rc == -1 && errno == EINVAL) { 64c0abf9e6Sopenharmony_ci fprintf(stderr, "WARNING: skipping EVIOCREVOKE test, not suported by current kernel\n"); 65c0abf9e6Sopenharmony_ci goto out; 66c0abf9e6Sopenharmony_ci } 67c0abf9e6Sopenharmony_ci ck_assert_msg(rc == 0, "Failed to revoke device: %s", strerror(errno)); 68c0abf9e6Sopenharmony_ci 69c0abf9e6Sopenharmony_ci uinput_device_event(uidev, EV_REL, REL_X, 1); 70c0abf9e6Sopenharmony_ci uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0); 71c0abf9e6Sopenharmony_ci 72c0abf9e6Sopenharmony_ci rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev1); 73c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, -ENODEV); 74c0abf9e6Sopenharmony_ci 75c0abf9e6Sopenharmony_ci rc = libevdev_next_event(dev2, LIBEVDEV_READ_FLAG_NORMAL, &ev2); 76c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS); 77c0abf9e6Sopenharmony_ci 78c0abf9e6Sopenharmony_ciout: 79c0abf9e6Sopenharmony_ci uinput_device_free(uidev); 80c0abf9e6Sopenharmony_ci libevdev_free(dev); 81c0abf9e6Sopenharmony_ci libevdev_free(dev2); 82c0abf9e6Sopenharmony_ci close(fd); 83c0abf9e6Sopenharmony_ci} 84c0abf9e6Sopenharmony_ciEND_TEST 85c0abf9e6Sopenharmony_ci 86c0abf9e6Sopenharmony_ciSTART_TEST(test_revoke_invalid) 87c0abf9e6Sopenharmony_ci{ 88c0abf9e6Sopenharmony_ci struct uinput_device* uidev; 89c0abf9e6Sopenharmony_ci struct libevdev *dev; 90c0abf9e6Sopenharmony_ci int rc; 91c0abf9e6Sopenharmony_ci int dev_fd; 92c0abf9e6Sopenharmony_ci 93c0abf9e6Sopenharmony_ci test_create_device(&uidev, &dev, 94c0abf9e6Sopenharmony_ci EV_SYN, SYN_REPORT, 95c0abf9e6Sopenharmony_ci EV_REL, REL_X, 96c0abf9e6Sopenharmony_ci EV_REL, REL_Y, 97c0abf9e6Sopenharmony_ci EV_REL, REL_WHEEL, 98c0abf9e6Sopenharmony_ci EV_KEY, BTN_LEFT, 99c0abf9e6Sopenharmony_ci EV_KEY, BTN_MIDDLE, 100c0abf9e6Sopenharmony_ci EV_KEY, BTN_RIGHT, 101c0abf9e6Sopenharmony_ci -1); 102c0abf9e6Sopenharmony_ci 103c0abf9e6Sopenharmony_ci dev_fd = libevdev_get_fd(dev); 104c0abf9e6Sopenharmony_ci ck_assert_int_ge(dev_fd, 0); 105c0abf9e6Sopenharmony_ci /* ioctl requires 0 as value */ 106c0abf9e6Sopenharmony_ci rc = ioctl(dev_fd, EVIOCREVOKE, 1); 107c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, -1); 108c0abf9e6Sopenharmony_ci ck_assert_int_eq(errno, EINVAL); 109c0abf9e6Sopenharmony_ci 110c0abf9e6Sopenharmony_ci uinput_device_free(uidev); 111c0abf9e6Sopenharmony_ci libevdev_free(dev); 112c0abf9e6Sopenharmony_ci} 113c0abf9e6Sopenharmony_ciEND_TEST 114c0abf9e6Sopenharmony_ci 115c0abf9e6Sopenharmony_ciSTART_TEST(test_revoke_fail_after) 116c0abf9e6Sopenharmony_ci{ 117c0abf9e6Sopenharmony_ci struct uinput_device* uidev; 118c0abf9e6Sopenharmony_ci struct libevdev *dev, *dev2 = NULL; 119c0abf9e6Sopenharmony_ci int rc, fd; 120c0abf9e6Sopenharmony_ci 121c0abf9e6Sopenharmony_ci test_create_device(&uidev, &dev, 122c0abf9e6Sopenharmony_ci EV_SYN, SYN_REPORT, 123c0abf9e6Sopenharmony_ci EV_REL, REL_X, 124c0abf9e6Sopenharmony_ci EV_REL, REL_Y, 125c0abf9e6Sopenharmony_ci EV_REL, REL_WHEEL, 126c0abf9e6Sopenharmony_ci EV_KEY, BTN_LEFT, 127c0abf9e6Sopenharmony_ci EV_KEY, BTN_MIDDLE, 128c0abf9e6Sopenharmony_ci EV_KEY, BTN_RIGHT, 129c0abf9e6Sopenharmony_ci -1); 130c0abf9e6Sopenharmony_ci 131c0abf9e6Sopenharmony_ci fd = open(uinput_device_get_devnode(uidev), O_RDONLY|O_NONBLOCK); 132c0abf9e6Sopenharmony_ci ck_assert_int_gt(fd, -1); 133c0abf9e6Sopenharmony_ci 134c0abf9e6Sopenharmony_ci rc = ioctl(fd, EVIOCREVOKE, NULL); 135c0abf9e6Sopenharmony_ci if (rc == -1 && errno == EINVAL) { 136c0abf9e6Sopenharmony_ci fprintf(stderr, "WARNING: skipping EVIOCREVOKE test, not suported by current kernel\n"); 137c0abf9e6Sopenharmony_ci goto out; 138c0abf9e6Sopenharmony_ci } 139c0abf9e6Sopenharmony_ci ck_assert_msg(rc == 0, "Failed to revoke device: %s", strerror(errno)); 140c0abf9e6Sopenharmony_ci 141c0abf9e6Sopenharmony_ci rc = libevdev_new_from_fd(fd, &dev2); 142c0abf9e6Sopenharmony_ci ck_assert_int_eq(rc, -ENODEV); 143c0abf9e6Sopenharmony_ci 144c0abf9e6Sopenharmony_ciout: 145c0abf9e6Sopenharmony_ci uinput_device_free(uidev); 146c0abf9e6Sopenharmony_ci libevdev_free(dev); 147c0abf9e6Sopenharmony_ci close(fd); 148c0abf9e6Sopenharmony_ci} 149c0abf9e6Sopenharmony_ciEND_TEST 150c0abf9e6Sopenharmony_ci 151c0abf9e6Sopenharmony_ciTEST_SUITE_ROOT_PRIVILEGES(kernel) 152c0abf9e6Sopenharmony_ci{ 153c0abf9e6Sopenharmony_ci Suite *s = suite_create("kernel"); 154c0abf9e6Sopenharmony_ci 155c0abf9e6Sopenharmony_ci add_test(s, test_revoke); 156c0abf9e6Sopenharmony_ci add_test(s, test_revoke_invalid); 157c0abf9e6Sopenharmony_ci add_test(s, test_revoke_fail_after); 158c0abf9e6Sopenharmony_ci 159c0abf9e6Sopenharmony_ci return s; 160c0abf9e6Sopenharmony_ci} 161