1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2013 Red Hat, Inc. 3a46c0ec8Sopenharmony_ci * Copyright © 2013 Marcin Slusarz <marcin.slusarz@gmail.com> 4a46c0ec8Sopenharmony_ci * 5a46c0ec8Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6a46c0ec8Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7a46c0ec8Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8a46c0ec8Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9a46c0ec8Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10a46c0ec8Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11a46c0ec8Sopenharmony_ci * 12a46c0ec8Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13a46c0ec8Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14a46c0ec8Sopenharmony_ci * Software. 15a46c0ec8Sopenharmony_ci * 16a46c0ec8Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17a46c0ec8Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18a46c0ec8Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19a46c0ec8Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20a46c0ec8Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21a46c0ec8Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22a46c0ec8Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 23a46c0ec8Sopenharmony_ci */ 24a46c0ec8Sopenharmony_ci 25a46c0ec8Sopenharmony_ci#include "config.h" 26a46c0ec8Sopenharmony_ci 27a46c0ec8Sopenharmony_ci#include <check.h> 28a46c0ec8Sopenharmony_ci#include <dirent.h> 29a46c0ec8Sopenharmony_ci#include <errno.h> 30a46c0ec8Sopenharmony_ci#include <libgen.h> 31a46c0ec8Sopenharmony_ci#include <fcntl.h> 32a46c0ec8Sopenharmony_ci#include <fnmatch.h> 33a46c0ec8Sopenharmony_ci#include <getopt.h> 34a46c0ec8Sopenharmony_ci#include <poll.h> 35a46c0ec8Sopenharmony_ci#include <signal.h> 36a46c0ec8Sopenharmony_ci#include <stdint.h> 37a46c0ec8Sopenharmony_ci#include <stdio.h> 38a46c0ec8Sopenharmony_ci#include <stdlib.h> 39a46c0ec8Sopenharmony_ci#include <stdarg.h> 40a46c0ec8Sopenharmony_ci#include <time.h> 41a46c0ec8Sopenharmony_ci#include <unistd.h> 42a46c0ec8Sopenharmony_ci#include "linux/input.h" 43a46c0ec8Sopenharmony_ci#include <sys/ptrace.h> 44a46c0ec8Sopenharmony_ci#include <sys/resource.h> 45a46c0ec8Sopenharmony_ci#include <sys/timerfd.h> 46a46c0ec8Sopenharmony_ci#include <sys/wait.h> 47a46c0ec8Sopenharmony_ci#include <sys/stat.h> 48a46c0ec8Sopenharmony_ci#include <sys/types.h> 49a46c0ec8Sopenharmony_ci#include <sys/sysinfo.h> 50a46c0ec8Sopenharmony_ci#include <libudev.h> 51a46c0ec8Sopenharmony_ci#if HAVE_LIBSYSTEMD 52a46c0ec8Sopenharmony_ci#include <systemd/sd-bus.h> 53a46c0ec8Sopenharmony_ci#endif 54a46c0ec8Sopenharmony_ci#ifdef __FreeBSD__ 55a46c0ec8Sopenharmony_ci#include <termios.h> 56a46c0ec8Sopenharmony_ci#endif 57a46c0ec8Sopenharmony_ci 58a46c0ec8Sopenharmony_ci#include <valgrind/valgrind.h> 59a46c0ec8Sopenharmony_ci 60a46c0ec8Sopenharmony_ci#include "litest.h" 61a46c0ec8Sopenharmony_ci#include "litest-int.h" 62a46c0ec8Sopenharmony_ci#include "libinput-util.h" 63a46c0ec8Sopenharmony_ci#include "quirks.h" 64a46c0ec8Sopenharmony_ci#include "builddir.h" 65a46c0ec8Sopenharmony_ci 66a46c0ec8Sopenharmony_ci#include <linux/kd.h> 67a46c0ec8Sopenharmony_ci 68a46c0ec8Sopenharmony_ci#define evbit(t, c) ((t) << 16U | (c & 0xffff)) 69a46c0ec8Sopenharmony_ci 70a46c0ec8Sopenharmony_ci#define UDEV_RULES_D "/run/udev/rules.d" 71a46c0ec8Sopenharmony_ci#define UDEV_FUZZ_OVERRIDE_RULE_FILE UDEV_RULES_D \ 72a46c0ec8Sopenharmony_ci "/91-litest-fuzz-override-REMOVEME-XXXXXX.rules" 73a46c0ec8Sopenharmony_ci#define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \ 74a46c0ec8Sopenharmony_ci "/91-litest-test-device-REMOVEME-XXXXXXX.rules" 75a46c0ec8Sopenharmony_ci#define UDEV_DEVICE_GROUPS_FILE UDEV_RULES_D \ 76a46c0ec8Sopenharmony_ci "/80-libinput-device-groups-litest-XXXXXX.rules" 77a46c0ec8Sopenharmony_ci 78a46c0ec8Sopenharmony_cistatic int jobs; 79a46c0ec8Sopenharmony_cistatic bool in_debugger = false; 80a46c0ec8Sopenharmony_cistatic bool verbose = false; 81a46c0ec8Sopenharmony_cistatic bool run_deviceless = false; 82a46c0ec8Sopenharmony_cistatic bool use_system_rules_quirks = false; 83a46c0ec8Sopenharmony_cistatic const char *filter_test = NULL; 84a46c0ec8Sopenharmony_cistatic const char *filter_device = NULL; 85a46c0ec8Sopenharmony_cistatic const char *filter_group = NULL; 86a46c0ec8Sopenharmony_cistatic const char *xml_prefix = NULL; 87a46c0ec8Sopenharmony_cistatic struct quirks_context *quirks_context; 88a46c0ec8Sopenharmony_ci 89a46c0ec8Sopenharmony_cistruct created_file { 90a46c0ec8Sopenharmony_ci struct list link; 91a46c0ec8Sopenharmony_ci char *path; 92a46c0ec8Sopenharmony_ci}; 93a46c0ec8Sopenharmony_ci 94a46c0ec8Sopenharmony_cistatic struct list created_files_list; /* list of all files to remove at the end 95a46c0ec8Sopenharmony_ci of the test run */ 96a46c0ec8Sopenharmony_ci 97a46c0ec8Sopenharmony_cistatic void litest_init_udev_rules(struct list *created_files_list); 98a46c0ec8Sopenharmony_cistatic void litest_remove_udev_rules(struct list *created_files_list); 99a46c0ec8Sopenharmony_ci 100a46c0ec8Sopenharmony_cienum quirks_setup_mode { 101a46c0ec8Sopenharmony_ci QUIRKS_SETUP_USE_SRCDIR, 102a46c0ec8Sopenharmony_ci QUIRKS_SETUP_ONLY_DEVICE, 103a46c0ec8Sopenharmony_ci QUIRKS_SETUP_FULL, 104a46c0ec8Sopenharmony_ci}; 105a46c0ec8Sopenharmony_cistatic void litest_setup_quirks(struct list *created_files_list, 106a46c0ec8Sopenharmony_ci enum quirks_setup_mode mode); 107a46c0ec8Sopenharmony_ci 108a46c0ec8Sopenharmony_ci/* defined for the litest selftest */ 109a46c0ec8Sopenharmony_ci#ifndef LITEST_DISABLE_BACKTRACE_LOGGING 110a46c0ec8Sopenharmony_ci#define litest_log(...) fprintf(stderr, __VA_ARGS__) 111a46c0ec8Sopenharmony_ci#define litest_vlog(format_, args_) vfprintf(stderr, format_, args_) 112a46c0ec8Sopenharmony_ci#else 113a46c0ec8Sopenharmony_ci#define litest_log(...) { /* __VA_ARGS__ */ } 114a46c0ec8Sopenharmony_ci#define litest_vlog(...) { /* __VA_ARGS__ */ } 115a46c0ec8Sopenharmony_ci#endif 116a46c0ec8Sopenharmony_ci 117a46c0ec8Sopenharmony_cistatic void 118a46c0ec8Sopenharmony_cilitest_backtrace(void) 119a46c0ec8Sopenharmony_ci{ 120a46c0ec8Sopenharmony_ci#if HAVE_GSTACK 121a46c0ec8Sopenharmony_ci pid_t parent, child; 122a46c0ec8Sopenharmony_ci int pipefd[2]; 123a46c0ec8Sopenharmony_ci 124a46c0ec8Sopenharmony_ci if (RUNNING_ON_VALGRIND) { 125a46c0ec8Sopenharmony_ci litest_log(" Using valgrind, omitting backtrace\n"); 126a46c0ec8Sopenharmony_ci return; 127a46c0ec8Sopenharmony_ci } 128a46c0ec8Sopenharmony_ci 129a46c0ec8Sopenharmony_ci if (pipe(pipefd) == -1) 130a46c0ec8Sopenharmony_ci return; 131a46c0ec8Sopenharmony_ci 132a46c0ec8Sopenharmony_ci parent = getpid(); 133a46c0ec8Sopenharmony_ci child = fork(); 134a46c0ec8Sopenharmony_ci 135a46c0ec8Sopenharmony_ci if (child == 0) { 136a46c0ec8Sopenharmony_ci char pid[8]; 137a46c0ec8Sopenharmony_ci 138a46c0ec8Sopenharmony_ci close(pipefd[0]); 139a46c0ec8Sopenharmony_ci dup2(pipefd[1], STDOUT_FILENO); 140a46c0ec8Sopenharmony_ci 141a46c0ec8Sopenharmony_ci sprintf(pid, "%d", parent); 142a46c0ec8Sopenharmony_ci 143a46c0ec8Sopenharmony_ci execlp("gstack", "gstack", pid, NULL); 144a46c0ec8Sopenharmony_ci exit(errno); 145a46c0ec8Sopenharmony_ci } 146a46c0ec8Sopenharmony_ci 147a46c0ec8Sopenharmony_ci /* parent */ 148a46c0ec8Sopenharmony_ci char buf[1024]; 149a46c0ec8Sopenharmony_ci int status, nread; 150a46c0ec8Sopenharmony_ci 151a46c0ec8Sopenharmony_ci close(pipefd[1]); 152a46c0ec8Sopenharmony_ci waitpid(child, &status, 0); 153a46c0ec8Sopenharmony_ci 154a46c0ec8Sopenharmony_ci status = WEXITSTATUS(status); 155a46c0ec8Sopenharmony_ci if (status != 0) { 156a46c0ec8Sopenharmony_ci litest_log("ERROR: gstack failed, no backtrace available: %s\n", 157a46c0ec8Sopenharmony_ci strerror(status)); 158a46c0ec8Sopenharmony_ci } else { 159a46c0ec8Sopenharmony_ci litest_log("\nBacktrace:\n"); 160a46c0ec8Sopenharmony_ci while ((nread = read(pipefd[0], buf, sizeof(buf) - 1)) > 0) { 161a46c0ec8Sopenharmony_ci buf[nread] = '\0'; 162a46c0ec8Sopenharmony_ci litest_log("%s", buf); 163a46c0ec8Sopenharmony_ci } 164a46c0ec8Sopenharmony_ci litest_log("\n"); 165a46c0ec8Sopenharmony_ci } 166a46c0ec8Sopenharmony_ci close(pipefd[0]); 167a46c0ec8Sopenharmony_ci#endif 168a46c0ec8Sopenharmony_ci} 169a46c0ec8Sopenharmony_ci 170a46c0ec8Sopenharmony_ciLIBINPUT_ATTRIBUTE_PRINTF(5, 6) 171a46c0ec8Sopenharmony_ci__attribute__((noreturn)) 172a46c0ec8Sopenharmony_civoid 173a46c0ec8Sopenharmony_cilitest_fail_condition(const char *file, 174a46c0ec8Sopenharmony_ci int line, 175a46c0ec8Sopenharmony_ci const char *func, 176a46c0ec8Sopenharmony_ci const char *condition, 177a46c0ec8Sopenharmony_ci const char *message, 178a46c0ec8Sopenharmony_ci ...) 179a46c0ec8Sopenharmony_ci{ 180a46c0ec8Sopenharmony_ci litest_log("FAILED: %s\n", condition); 181a46c0ec8Sopenharmony_ci 182a46c0ec8Sopenharmony_ci if (message) { 183a46c0ec8Sopenharmony_ci va_list args; 184a46c0ec8Sopenharmony_ci va_start(args, message); 185a46c0ec8Sopenharmony_ci litest_vlog(message, args); 186a46c0ec8Sopenharmony_ci va_end(args); 187a46c0ec8Sopenharmony_ci } 188a46c0ec8Sopenharmony_ci 189a46c0ec8Sopenharmony_ci litest_log("in %s() (%s:%d)\n", func, file, line); 190a46c0ec8Sopenharmony_ci litest_backtrace(); 191a46c0ec8Sopenharmony_ci abort(); 192a46c0ec8Sopenharmony_ci} 193a46c0ec8Sopenharmony_ci 194a46c0ec8Sopenharmony_ci__attribute__((noreturn)) 195a46c0ec8Sopenharmony_civoid 196a46c0ec8Sopenharmony_cilitest_fail_comparison_int(const char *file, 197a46c0ec8Sopenharmony_ci int line, 198a46c0ec8Sopenharmony_ci const char *func, 199a46c0ec8Sopenharmony_ci const char *operator, 200a46c0ec8Sopenharmony_ci int a, 201a46c0ec8Sopenharmony_ci int b, 202a46c0ec8Sopenharmony_ci const char *astr, 203a46c0ec8Sopenharmony_ci const char *bstr) 204a46c0ec8Sopenharmony_ci{ 205a46c0ec8Sopenharmony_ci litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr); 206a46c0ec8Sopenharmony_ci litest_log("Resolved to: %d %s %d\n", a, operator, b); 207a46c0ec8Sopenharmony_ci litest_log("in %s() (%s:%d)\n", func, file, line); 208a46c0ec8Sopenharmony_ci litest_backtrace(); 209a46c0ec8Sopenharmony_ci abort(); 210a46c0ec8Sopenharmony_ci} 211a46c0ec8Sopenharmony_ci 212a46c0ec8Sopenharmony_ci__attribute__((noreturn)) 213a46c0ec8Sopenharmony_civoid 214a46c0ec8Sopenharmony_cilitest_fail_comparison_double(const char *file, 215a46c0ec8Sopenharmony_ci int line, 216a46c0ec8Sopenharmony_ci const char *func, 217a46c0ec8Sopenharmony_ci const char *operator, 218a46c0ec8Sopenharmony_ci double a, 219a46c0ec8Sopenharmony_ci double b, 220a46c0ec8Sopenharmony_ci const char *astr, 221a46c0ec8Sopenharmony_ci const char *bstr) 222a46c0ec8Sopenharmony_ci{ 223a46c0ec8Sopenharmony_ci litest_log("FAILED COMPARISON: %s %s %s\n", astr, operator, bstr); 224a46c0ec8Sopenharmony_ci litest_log("Resolved to: %.3f %s %.3f\n", a, operator, b); 225a46c0ec8Sopenharmony_ci litest_log("in %s() (%s:%d)\n", func, file, line); 226a46c0ec8Sopenharmony_ci litest_backtrace(); 227a46c0ec8Sopenharmony_ci abort(); 228a46c0ec8Sopenharmony_ci} 229a46c0ec8Sopenharmony_ci 230a46c0ec8Sopenharmony_ci__attribute__((noreturn)) 231a46c0ec8Sopenharmony_civoid 232a46c0ec8Sopenharmony_cilitest_fail_comparison_ptr(const char *file, 233a46c0ec8Sopenharmony_ci int line, 234a46c0ec8Sopenharmony_ci const char *func, 235a46c0ec8Sopenharmony_ci const char *comparison) 236a46c0ec8Sopenharmony_ci{ 237a46c0ec8Sopenharmony_ci litest_log("FAILED COMPARISON: %s\n", comparison); 238a46c0ec8Sopenharmony_ci litest_log("in %s() (%s:%d)\n", func, file, line); 239a46c0ec8Sopenharmony_ci litest_backtrace(); 240a46c0ec8Sopenharmony_ci abort(); 241a46c0ec8Sopenharmony_ci} 242a46c0ec8Sopenharmony_ci 243a46c0ec8Sopenharmony_cistruct test { 244a46c0ec8Sopenharmony_ci struct list node; 245a46c0ec8Sopenharmony_ci char *name; 246a46c0ec8Sopenharmony_ci char *devname; 247a46c0ec8Sopenharmony_ci const void *func; 248a46c0ec8Sopenharmony_ci void *setup; 249a46c0ec8Sopenharmony_ci void *teardown; 250a46c0ec8Sopenharmony_ci 251a46c0ec8Sopenharmony_ci struct range range; 252a46c0ec8Sopenharmony_ci bool deviceless; 253a46c0ec8Sopenharmony_ci}; 254a46c0ec8Sopenharmony_ci 255a46c0ec8Sopenharmony_cistruct suite { 256a46c0ec8Sopenharmony_ci struct list node; 257a46c0ec8Sopenharmony_ci struct list tests; 258a46c0ec8Sopenharmony_ci char *name; 259a46c0ec8Sopenharmony_ci}; 260a46c0ec8Sopenharmony_ci 261a46c0ec8Sopenharmony_cistatic struct litest_device *current_device; 262a46c0ec8Sopenharmony_ci 263a46c0ec8Sopenharmony_cistruct litest_device *litest_current_device(void) 264a46c0ec8Sopenharmony_ci{ 265a46c0ec8Sopenharmony_ci return current_device; 266a46c0ec8Sopenharmony_ci} 267a46c0ec8Sopenharmony_ci 268a46c0ec8Sopenharmony_cistatic void 269a46c0ec8Sopenharmony_cigrab_device(struct litest_device *device, bool mode) 270a46c0ec8Sopenharmony_ci{ 271a46c0ec8Sopenharmony_ci struct libinput *li = libinput_device_get_context(device->libinput_device); 272a46c0ec8Sopenharmony_ci struct litest_context *ctx = libinput_get_user_data(li); 273a46c0ec8Sopenharmony_ci struct udev_device *udev_device; 274a46c0ec8Sopenharmony_ci const char *devnode; 275a46c0ec8Sopenharmony_ci struct path *p; 276a46c0ec8Sopenharmony_ci 277a46c0ec8Sopenharmony_ci udev_device = libinput_device_get_udev_device(device->libinput_device); 278a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(udev_device); 279a46c0ec8Sopenharmony_ci 280a46c0ec8Sopenharmony_ci devnode = udev_device_get_devnode(udev_device); 281a46c0ec8Sopenharmony_ci 282a46c0ec8Sopenharmony_ci /* Note: in some tests we create multiple devices for the same path. 283a46c0ec8Sopenharmony_ci * This will only grab the first device in the list but we're using 284a46c0ec8Sopenharmony_ci * list_insert() so the first device is the latest that was 285a46c0ec8Sopenharmony_ci * initialized, so we should be good. 286a46c0ec8Sopenharmony_ci */ 287a46c0ec8Sopenharmony_ci list_for_each(p, &ctx->paths, link) { 288a46c0ec8Sopenharmony_ci if (streq(p->path, devnode)) { 289a46c0ec8Sopenharmony_ci int rc = ioctl(p->fd, EVIOCGRAB, (void*)mode ? 1 : 0); 290a46c0ec8Sopenharmony_ci ck_assert_int_gt(rc, -1); 291a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 292a46c0ec8Sopenharmony_ci return; 293a46c0ec8Sopenharmony_ci } 294a46c0ec8Sopenharmony_ci } 295a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to find device %s to %sgrab\n", 296a46c0ec8Sopenharmony_ci devnode, mode ? "" : "un"); 297a46c0ec8Sopenharmony_ci} 298a46c0ec8Sopenharmony_ci 299a46c0ec8Sopenharmony_civoid 300a46c0ec8Sopenharmony_cilitest_grab_device(struct litest_device *device) 301a46c0ec8Sopenharmony_ci{ 302a46c0ec8Sopenharmony_ci grab_device(device, true); 303a46c0ec8Sopenharmony_ci} 304a46c0ec8Sopenharmony_ci 305a46c0ec8Sopenharmony_civoid 306a46c0ec8Sopenharmony_cilitest_ungrab_device(struct litest_device *device) 307a46c0ec8Sopenharmony_ci{ 308a46c0ec8Sopenharmony_ci grab_device(device, false); 309a46c0ec8Sopenharmony_ci} 310a46c0ec8Sopenharmony_ci 311a46c0ec8Sopenharmony_civoid litest_set_current_device(struct litest_device *device) 312a46c0ec8Sopenharmony_ci{ 313a46c0ec8Sopenharmony_ci current_device = device; 314a46c0ec8Sopenharmony_ci} 315a46c0ec8Sopenharmony_ci 316a46c0ec8Sopenharmony_civoid litest_generic_device_teardown(void) 317a46c0ec8Sopenharmony_ci{ 318a46c0ec8Sopenharmony_ci litest_delete_device(current_device); 319a46c0ec8Sopenharmony_ci current_device = NULL; 320a46c0ec8Sopenharmony_ci} 321a46c0ec8Sopenharmony_ci 322a46c0ec8Sopenharmony_cistatic struct list devices; 323a46c0ec8Sopenharmony_ci 324a46c0ec8Sopenharmony_cistatic struct list all_tests; 325a46c0ec8Sopenharmony_ci 326a46c0ec8Sopenharmony_cistatic inline void 327a46c0ec8Sopenharmony_cilitest_system(const char *command) 328a46c0ec8Sopenharmony_ci{ 329a46c0ec8Sopenharmony_ci int ret; 330a46c0ec8Sopenharmony_ci 331a46c0ec8Sopenharmony_ci ret = system(command); 332a46c0ec8Sopenharmony_ci 333a46c0ec8Sopenharmony_ci if (ret == -1) { 334a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to execute: %s", command); 335a46c0ec8Sopenharmony_ci } else if (WIFEXITED(ret)) { 336a46c0ec8Sopenharmony_ci if (WEXITSTATUS(ret)) 337a46c0ec8Sopenharmony_ci litest_abort_msg("'%s' failed with %d", 338a46c0ec8Sopenharmony_ci command, 339a46c0ec8Sopenharmony_ci WEXITSTATUS(ret)); 340a46c0ec8Sopenharmony_ci } else if (WIFSIGNALED(ret)) { 341a46c0ec8Sopenharmony_ci litest_abort_msg("'%s' terminated with signal %d", 342a46c0ec8Sopenharmony_ci command, 343a46c0ec8Sopenharmony_ci WTERMSIG(ret)); 344a46c0ec8Sopenharmony_ci } 345a46c0ec8Sopenharmony_ci} 346a46c0ec8Sopenharmony_ci 347a46c0ec8Sopenharmony_cistatic void 348a46c0ec8Sopenharmony_cilitest_reload_udev_rules(void) 349a46c0ec8Sopenharmony_ci{ 350a46c0ec8Sopenharmony_ci litest_system("udevadm control --reload-rules"); 351a46c0ec8Sopenharmony_ci} 352a46c0ec8Sopenharmony_ci 353a46c0ec8Sopenharmony_cistatic void 354a46c0ec8Sopenharmony_cilitest_add_tcase_for_device(struct suite *suite, 355a46c0ec8Sopenharmony_ci const char *funcname, 356a46c0ec8Sopenharmony_ci const void *func, 357a46c0ec8Sopenharmony_ci const struct litest_test_device *dev, 358a46c0ec8Sopenharmony_ci const struct range *range) 359a46c0ec8Sopenharmony_ci{ 360a46c0ec8Sopenharmony_ci struct test *t; 361a46c0ec8Sopenharmony_ci 362a46c0ec8Sopenharmony_ci t = zalloc(sizeof(*t)); 363a46c0ec8Sopenharmony_ci t->name = safe_strdup(funcname); 364a46c0ec8Sopenharmony_ci t->devname = safe_strdup(dev->shortname); 365a46c0ec8Sopenharmony_ci t->func = func; 366a46c0ec8Sopenharmony_ci t->setup = dev->setup; 367a46c0ec8Sopenharmony_ci t->teardown = dev->teardown ? 368a46c0ec8Sopenharmony_ci dev->teardown : litest_generic_device_teardown; 369a46c0ec8Sopenharmony_ci if (range) 370a46c0ec8Sopenharmony_ci t->range = *range; 371a46c0ec8Sopenharmony_ci 372a46c0ec8Sopenharmony_ci list_insert(&suite->tests, &t->node); 373a46c0ec8Sopenharmony_ci} 374a46c0ec8Sopenharmony_ci 375a46c0ec8Sopenharmony_cistatic void 376a46c0ec8Sopenharmony_cilitest_add_tcase_no_device(struct suite *suite, 377a46c0ec8Sopenharmony_ci const void *func, 378a46c0ec8Sopenharmony_ci const char *funcname, 379a46c0ec8Sopenharmony_ci const struct range *range) 380a46c0ec8Sopenharmony_ci{ 381a46c0ec8Sopenharmony_ci struct test *t; 382a46c0ec8Sopenharmony_ci const char *test_name = funcname; 383a46c0ec8Sopenharmony_ci 384a46c0ec8Sopenharmony_ci if (filter_device && 385a46c0ec8Sopenharmony_ci strstr(test_name, filter_device) == NULL && 386a46c0ec8Sopenharmony_ci fnmatch(filter_device, test_name, 0) != 0) 387a46c0ec8Sopenharmony_ci return; 388a46c0ec8Sopenharmony_ci 389a46c0ec8Sopenharmony_ci t = zalloc(sizeof(*t)); 390a46c0ec8Sopenharmony_ci t->name = safe_strdup(test_name); 391a46c0ec8Sopenharmony_ci t->devname = safe_strdup("no device"); 392a46c0ec8Sopenharmony_ci t->func = func; 393a46c0ec8Sopenharmony_ci if (range) 394a46c0ec8Sopenharmony_ci t->range = *range; 395a46c0ec8Sopenharmony_ci t->setup = NULL; 396a46c0ec8Sopenharmony_ci t->teardown = NULL; 397a46c0ec8Sopenharmony_ci 398a46c0ec8Sopenharmony_ci list_insert(&suite->tests, &t->node); 399a46c0ec8Sopenharmony_ci} 400a46c0ec8Sopenharmony_ci 401a46c0ec8Sopenharmony_cistatic void 402a46c0ec8Sopenharmony_cilitest_add_tcase_deviceless(struct suite *suite, 403a46c0ec8Sopenharmony_ci const void *func, 404a46c0ec8Sopenharmony_ci const char *funcname, 405a46c0ec8Sopenharmony_ci const struct range *range) 406a46c0ec8Sopenharmony_ci{ 407a46c0ec8Sopenharmony_ci struct test *t; 408a46c0ec8Sopenharmony_ci const char *test_name = funcname; 409a46c0ec8Sopenharmony_ci 410a46c0ec8Sopenharmony_ci if (filter_device && 411a46c0ec8Sopenharmony_ci strstr(test_name, filter_device) == NULL && 412a46c0ec8Sopenharmony_ci fnmatch(filter_device, test_name, 0) != 0) 413a46c0ec8Sopenharmony_ci return; 414a46c0ec8Sopenharmony_ci 415a46c0ec8Sopenharmony_ci t = zalloc(sizeof(*t)); 416a46c0ec8Sopenharmony_ci t->deviceless = true; 417a46c0ec8Sopenharmony_ci t->name = safe_strdup(test_name); 418a46c0ec8Sopenharmony_ci t->devname = safe_strdup("deviceless"); 419a46c0ec8Sopenharmony_ci t->func = func; 420a46c0ec8Sopenharmony_ci if (range) 421a46c0ec8Sopenharmony_ci t->range = *range; 422a46c0ec8Sopenharmony_ci t->setup = NULL; 423a46c0ec8Sopenharmony_ci t->teardown = NULL; 424a46c0ec8Sopenharmony_ci 425a46c0ec8Sopenharmony_ci list_insert(&suite->tests, &t->node); 426a46c0ec8Sopenharmony_ci} 427a46c0ec8Sopenharmony_ci 428a46c0ec8Sopenharmony_cistatic struct suite * 429a46c0ec8Sopenharmony_ciget_suite(const char *name) 430a46c0ec8Sopenharmony_ci{ 431a46c0ec8Sopenharmony_ci struct suite *s; 432a46c0ec8Sopenharmony_ci 433a46c0ec8Sopenharmony_ci list_for_each(s, &all_tests, node) { 434a46c0ec8Sopenharmony_ci if (streq(s->name, name)) 435a46c0ec8Sopenharmony_ci return s; 436a46c0ec8Sopenharmony_ci } 437a46c0ec8Sopenharmony_ci 438a46c0ec8Sopenharmony_ci s = zalloc(sizeof(*s)); 439a46c0ec8Sopenharmony_ci s->name = safe_strdup(name); 440a46c0ec8Sopenharmony_ci 441a46c0ec8Sopenharmony_ci list_init(&s->tests); 442a46c0ec8Sopenharmony_ci list_insert(&all_tests, &s->node); 443a46c0ec8Sopenharmony_ci 444a46c0ec8Sopenharmony_ci return s; 445a46c0ec8Sopenharmony_ci} 446a46c0ec8Sopenharmony_ci 447a46c0ec8Sopenharmony_cistatic void 448a46c0ec8Sopenharmony_cicreate_suite_name(const char *filename, char suitename[64]) 449a46c0ec8Sopenharmony_ci{ 450a46c0ec8Sopenharmony_ci char *trunk = trunkname(filename); 451a46c0ec8Sopenharmony_ci char *p = trunk; 452a46c0ec8Sopenharmony_ci 453a46c0ec8Sopenharmony_ci /* strip the test- prefix */ 454a46c0ec8Sopenharmony_ci if (strstartswith(trunk, "test-")) 455a46c0ec8Sopenharmony_ci p += 5; 456a46c0ec8Sopenharmony_ci 457a46c0ec8Sopenharmony_ci snprintf(suitename, 64, "%s", p); 458a46c0ec8Sopenharmony_ci free(trunk); 459a46c0ec8Sopenharmony_ci} 460a46c0ec8Sopenharmony_ci 461a46c0ec8Sopenharmony_cistatic void 462a46c0ec8Sopenharmony_cilitest_add_tcase(const char *filename, 463a46c0ec8Sopenharmony_ci const char *funcname, 464a46c0ec8Sopenharmony_ci const void *func, 465a46c0ec8Sopenharmony_ci int64_t required, 466a46c0ec8Sopenharmony_ci int64_t excluded, 467a46c0ec8Sopenharmony_ci const struct range *range) 468a46c0ec8Sopenharmony_ci{ 469a46c0ec8Sopenharmony_ci char suite_name[65]; 470a46c0ec8Sopenharmony_ci struct suite *suite; 471a46c0ec8Sopenharmony_ci bool added = false; 472a46c0ec8Sopenharmony_ci 473a46c0ec8Sopenharmony_ci litest_assert(required >= LITEST_DEVICELESS); 474a46c0ec8Sopenharmony_ci litest_assert(excluded >= LITEST_DEVICELESS); 475a46c0ec8Sopenharmony_ci 476a46c0ec8Sopenharmony_ci if (filter_test && 477a46c0ec8Sopenharmony_ci strstr(funcname, filter_test) == NULL && 478a46c0ec8Sopenharmony_ci fnmatch(filter_test, funcname, 0) != 0) 479a46c0ec8Sopenharmony_ci return; 480a46c0ec8Sopenharmony_ci 481a46c0ec8Sopenharmony_ci create_suite_name(filename, suite_name); 482a46c0ec8Sopenharmony_ci 483a46c0ec8Sopenharmony_ci if (filter_group && fnmatch(filter_group, suite_name, 0) != 0) 484a46c0ec8Sopenharmony_ci return; 485a46c0ec8Sopenharmony_ci 486a46c0ec8Sopenharmony_ci suite = get_suite(suite_name); 487a46c0ec8Sopenharmony_ci 488a46c0ec8Sopenharmony_ci if (required == LITEST_DEVICELESS && 489a46c0ec8Sopenharmony_ci excluded == LITEST_DEVICELESS) { 490a46c0ec8Sopenharmony_ci litest_add_tcase_deviceless(suite, func, funcname, range); 491a46c0ec8Sopenharmony_ci added = true; 492a46c0ec8Sopenharmony_ci } else if (required == LITEST_DISABLE_DEVICE && 493a46c0ec8Sopenharmony_ci excluded == LITEST_DISABLE_DEVICE) { 494a46c0ec8Sopenharmony_ci litest_add_tcase_no_device(suite, func, funcname, range); 495a46c0ec8Sopenharmony_ci added = true; 496a46c0ec8Sopenharmony_ci } else if (required != LITEST_ANY || excluded != LITEST_ANY) { 497a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 498a46c0ec8Sopenharmony_ci 499a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) { 500a46c0ec8Sopenharmony_ci if (dev->features & LITEST_IGNORED) 501a46c0ec8Sopenharmony_ci continue; 502a46c0ec8Sopenharmony_ci 503a46c0ec8Sopenharmony_ci if (filter_device && 504a46c0ec8Sopenharmony_ci strstr(dev->shortname, filter_device) == NULL && 505a46c0ec8Sopenharmony_ci fnmatch(filter_device, dev->shortname, 0) != 0) 506a46c0ec8Sopenharmony_ci continue; 507a46c0ec8Sopenharmony_ci if ((dev->features & required) != required || 508a46c0ec8Sopenharmony_ci (dev->features & excluded) != 0) 509a46c0ec8Sopenharmony_ci continue; 510a46c0ec8Sopenharmony_ci 511a46c0ec8Sopenharmony_ci litest_add_tcase_for_device(suite, 512a46c0ec8Sopenharmony_ci funcname, 513a46c0ec8Sopenharmony_ci func, 514a46c0ec8Sopenharmony_ci dev, 515a46c0ec8Sopenharmony_ci range); 516a46c0ec8Sopenharmony_ci added = true; 517a46c0ec8Sopenharmony_ci } 518a46c0ec8Sopenharmony_ci } else { 519a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 520a46c0ec8Sopenharmony_ci 521a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) { 522a46c0ec8Sopenharmony_ci if (dev->features & LITEST_IGNORED) 523a46c0ec8Sopenharmony_ci continue; 524a46c0ec8Sopenharmony_ci 525a46c0ec8Sopenharmony_ci if (filter_device && 526a46c0ec8Sopenharmony_ci strstr(dev->shortname, filter_device) == NULL && 527a46c0ec8Sopenharmony_ci fnmatch(filter_device, dev->shortname, 0) != 0) 528a46c0ec8Sopenharmony_ci continue; 529a46c0ec8Sopenharmony_ci 530a46c0ec8Sopenharmony_ci litest_add_tcase_for_device(suite, 531a46c0ec8Sopenharmony_ci funcname, 532a46c0ec8Sopenharmony_ci func, 533a46c0ec8Sopenharmony_ci dev, 534a46c0ec8Sopenharmony_ci range); 535a46c0ec8Sopenharmony_ci added = true; 536a46c0ec8Sopenharmony_ci } 537a46c0ec8Sopenharmony_ci } 538a46c0ec8Sopenharmony_ci 539a46c0ec8Sopenharmony_ci if (!added && 540a46c0ec8Sopenharmony_ci filter_test == NULL && 541a46c0ec8Sopenharmony_ci filter_device == NULL && 542a46c0ec8Sopenharmony_ci filter_group == NULL) { 543a46c0ec8Sopenharmony_ci fprintf(stderr, "Test '%s' does not match any devices. Aborting.\n", funcname); 544a46c0ec8Sopenharmony_ci abort(); 545a46c0ec8Sopenharmony_ci } 546a46c0ec8Sopenharmony_ci} 547a46c0ec8Sopenharmony_ci 548a46c0ec8Sopenharmony_civoid 549a46c0ec8Sopenharmony_ci_litest_add_no_device(const char *name, const char *funcname, const void *func) 550a46c0ec8Sopenharmony_ci{ 551a46c0ec8Sopenharmony_ci _litest_add(name, funcname, func, LITEST_DISABLE_DEVICE, LITEST_DISABLE_DEVICE); 552a46c0ec8Sopenharmony_ci} 553a46c0ec8Sopenharmony_ci 554a46c0ec8Sopenharmony_civoid 555a46c0ec8Sopenharmony_ci_litest_add_ranged_no_device(const char *name, 556a46c0ec8Sopenharmony_ci const char *funcname, 557a46c0ec8Sopenharmony_ci const void *func, 558a46c0ec8Sopenharmony_ci const struct range *range) 559a46c0ec8Sopenharmony_ci{ 560a46c0ec8Sopenharmony_ci _litest_add_ranged(name, 561a46c0ec8Sopenharmony_ci funcname, 562a46c0ec8Sopenharmony_ci func, 563a46c0ec8Sopenharmony_ci LITEST_DISABLE_DEVICE, 564a46c0ec8Sopenharmony_ci LITEST_DISABLE_DEVICE, 565a46c0ec8Sopenharmony_ci range); 566a46c0ec8Sopenharmony_ci} 567a46c0ec8Sopenharmony_ci 568a46c0ec8Sopenharmony_civoid 569a46c0ec8Sopenharmony_ci_litest_add_deviceless(const char *name, 570a46c0ec8Sopenharmony_ci const char *funcname, 571a46c0ec8Sopenharmony_ci const void *func) 572a46c0ec8Sopenharmony_ci{ 573a46c0ec8Sopenharmony_ci _litest_add_ranged(name, 574a46c0ec8Sopenharmony_ci funcname, 575a46c0ec8Sopenharmony_ci func, 576a46c0ec8Sopenharmony_ci LITEST_DEVICELESS, 577a46c0ec8Sopenharmony_ci LITEST_DEVICELESS, 578a46c0ec8Sopenharmony_ci NULL); 579a46c0ec8Sopenharmony_ci} 580a46c0ec8Sopenharmony_ci 581a46c0ec8Sopenharmony_civoid 582a46c0ec8Sopenharmony_ci_litest_add(const char *name, 583a46c0ec8Sopenharmony_ci const char *funcname, 584a46c0ec8Sopenharmony_ci const void *func, 585a46c0ec8Sopenharmony_ci int64_t required, 586a46c0ec8Sopenharmony_ci int64_t excluded) 587a46c0ec8Sopenharmony_ci{ 588a46c0ec8Sopenharmony_ci _litest_add_ranged(name, 589a46c0ec8Sopenharmony_ci funcname, 590a46c0ec8Sopenharmony_ci func, 591a46c0ec8Sopenharmony_ci required, 592a46c0ec8Sopenharmony_ci excluded, 593a46c0ec8Sopenharmony_ci NULL); 594a46c0ec8Sopenharmony_ci} 595a46c0ec8Sopenharmony_ci 596a46c0ec8Sopenharmony_civoid 597a46c0ec8Sopenharmony_ci_litest_add_ranged(const char *name, 598a46c0ec8Sopenharmony_ci const char *funcname, 599a46c0ec8Sopenharmony_ci const void *func, 600a46c0ec8Sopenharmony_ci int64_t required, 601a46c0ec8Sopenharmony_ci int64_t excluded, 602a46c0ec8Sopenharmony_ci const struct range *range) 603a46c0ec8Sopenharmony_ci{ 604a46c0ec8Sopenharmony_ci litest_add_tcase(name, funcname, func, required, excluded, range); 605a46c0ec8Sopenharmony_ci} 606a46c0ec8Sopenharmony_ci 607a46c0ec8Sopenharmony_civoid 608a46c0ec8Sopenharmony_ci_litest_add_for_device(const char *name, 609a46c0ec8Sopenharmony_ci const char *funcname, 610a46c0ec8Sopenharmony_ci const void *func, 611a46c0ec8Sopenharmony_ci enum litest_device_type type) 612a46c0ec8Sopenharmony_ci{ 613a46c0ec8Sopenharmony_ci _litest_add_ranged_for_device(name, funcname, func, type, NULL); 614a46c0ec8Sopenharmony_ci} 615a46c0ec8Sopenharmony_ci 616a46c0ec8Sopenharmony_civoid 617a46c0ec8Sopenharmony_ci_litest_add_ranged_for_device(const char *filename, 618a46c0ec8Sopenharmony_ci const char *funcname, 619a46c0ec8Sopenharmony_ci const void *func, 620a46c0ec8Sopenharmony_ci enum litest_device_type type, 621a46c0ec8Sopenharmony_ci const struct range *range) 622a46c0ec8Sopenharmony_ci{ 623a46c0ec8Sopenharmony_ci struct suite *s; 624a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 625a46c0ec8Sopenharmony_ci bool device_filtered = false; 626a46c0ec8Sopenharmony_ci char suite_name[64]; 627a46c0ec8Sopenharmony_ci 628a46c0ec8Sopenharmony_ci litest_assert(type < LITEST_NO_DEVICE); 629a46c0ec8Sopenharmony_ci 630a46c0ec8Sopenharmony_ci if (filter_test && 631a46c0ec8Sopenharmony_ci strstr(funcname, filter_test) == NULL && 632a46c0ec8Sopenharmony_ci fnmatch(filter_test, funcname, 0) != 0) 633a46c0ec8Sopenharmony_ci return; 634a46c0ec8Sopenharmony_ci 635a46c0ec8Sopenharmony_ci create_suite_name(filename, suite_name); 636a46c0ec8Sopenharmony_ci if (filter_group && fnmatch(filter_group, suite_name, 0) != 0) 637a46c0ec8Sopenharmony_ci return; 638a46c0ec8Sopenharmony_ci 639a46c0ec8Sopenharmony_ci s = get_suite(suite_name); 640a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) { 641a46c0ec8Sopenharmony_ci if (filter_device && 642a46c0ec8Sopenharmony_ci strstr(dev->shortname, filter_device) == NULL && 643a46c0ec8Sopenharmony_ci fnmatch(filter_device, dev->shortname, 0) != 0) { 644a46c0ec8Sopenharmony_ci device_filtered = true; 645a46c0ec8Sopenharmony_ci continue; 646a46c0ec8Sopenharmony_ci } 647a46c0ec8Sopenharmony_ci 648a46c0ec8Sopenharmony_ci if (dev->type == type) { 649a46c0ec8Sopenharmony_ci litest_add_tcase_for_device(s, 650a46c0ec8Sopenharmony_ci funcname, 651a46c0ec8Sopenharmony_ci func, 652a46c0ec8Sopenharmony_ci dev, 653a46c0ec8Sopenharmony_ci range); 654a46c0ec8Sopenharmony_ci return; 655a46c0ec8Sopenharmony_ci } 656a46c0ec8Sopenharmony_ci } 657a46c0ec8Sopenharmony_ci 658a46c0ec8Sopenharmony_ci /* only abort if no filter was set, that's a bug */ 659a46c0ec8Sopenharmony_ci if (!device_filtered) 660a46c0ec8Sopenharmony_ci litest_abort_msg("Invalid test device type\n"); 661a46c0ec8Sopenharmony_ci} 662a46c0ec8Sopenharmony_ci 663a46c0ec8Sopenharmony_ciLIBINPUT_ATTRIBUTE_PRINTF(3, 0) 664a46c0ec8Sopenharmony_cistatic void 665a46c0ec8Sopenharmony_cilitest_log_handler(struct libinput *libinput, 666a46c0ec8Sopenharmony_ci enum libinput_log_priority pri, 667a46c0ec8Sopenharmony_ci const char *format, 668a46c0ec8Sopenharmony_ci va_list args) 669a46c0ec8Sopenharmony_ci{ 670a46c0ec8Sopenharmony_ci static int is_tty = -1; 671a46c0ec8Sopenharmony_ci const char *priority = NULL; 672a46c0ec8Sopenharmony_ci const char *color; 673a46c0ec8Sopenharmony_ci 674a46c0ec8Sopenharmony_ci if (is_tty == -1) 675a46c0ec8Sopenharmony_ci is_tty = isatty(STDERR_FILENO); 676a46c0ec8Sopenharmony_ci 677a46c0ec8Sopenharmony_ci switch(pri) { 678a46c0ec8Sopenharmony_ci case LIBINPUT_LOG_PRIORITY_INFO: 679a46c0ec8Sopenharmony_ci priority = "info "; 680a46c0ec8Sopenharmony_ci color = ANSI_HIGHLIGHT; 681a46c0ec8Sopenharmony_ci break; 682a46c0ec8Sopenharmony_ci case LIBINPUT_LOG_PRIORITY_ERROR: 683a46c0ec8Sopenharmony_ci priority = "error"; 684a46c0ec8Sopenharmony_ci color = ANSI_BRIGHT_RED; 685a46c0ec8Sopenharmony_ci break; 686a46c0ec8Sopenharmony_ci case LIBINPUT_LOG_PRIORITY_DEBUG: 687a46c0ec8Sopenharmony_ci priority = "debug"; 688a46c0ec8Sopenharmony_ci color = ANSI_NORMAL; 689a46c0ec8Sopenharmony_ci break; 690a46c0ec8Sopenharmony_ci default: 691a46c0ec8Sopenharmony_ci abort(); 692a46c0ec8Sopenharmony_ci } 693a46c0ec8Sopenharmony_ci 694a46c0ec8Sopenharmony_ci if (!is_tty) 695a46c0ec8Sopenharmony_ci color = ""; 696a46c0ec8Sopenharmony_ci else if (strstr(format, "tap:")) 697a46c0ec8Sopenharmony_ci color = ANSI_BLUE; 698a46c0ec8Sopenharmony_ci else if (strstr(format, "thumb state:")) 699a46c0ec8Sopenharmony_ci color = ANSI_YELLOW; 700a46c0ec8Sopenharmony_ci else if (strstr(format, "button state:")) 701a46c0ec8Sopenharmony_ci color = ANSI_MAGENTA; 702a46c0ec8Sopenharmony_ci else if (strstr(format, "touch-size:") || 703a46c0ec8Sopenharmony_ci strstr(format, "pressure:")) 704a46c0ec8Sopenharmony_ci color = ANSI_GREEN; 705a46c0ec8Sopenharmony_ci else if (strstr(format, "palm:") || 706a46c0ec8Sopenharmony_ci strstr(format, "thumb:")) 707a46c0ec8Sopenharmony_ci color = ANSI_CYAN; 708a46c0ec8Sopenharmony_ci else if (strstr(format, "edge-scroll:")) 709a46c0ec8Sopenharmony_ci color = ANSI_BRIGHT_GREEN; 710a46c0ec8Sopenharmony_ci 711a46c0ec8Sopenharmony_ci fprintf(stderr, "%slitest %s ", color, priority); 712a46c0ec8Sopenharmony_ci vfprintf(stderr, format, args); 713a46c0ec8Sopenharmony_ci if (is_tty) 714a46c0ec8Sopenharmony_ci fprintf(stderr, ANSI_NORMAL); 715a46c0ec8Sopenharmony_ci 716a46c0ec8Sopenharmony_ci if (strstr(format, "client bug: ") || 717a46c0ec8Sopenharmony_ci strstr(format, "libinput bug: ")) { 718a46c0ec8Sopenharmony_ci /* valgrind is too slow and some of our offsets are too 719a46c0ec8Sopenharmony_ci * short, don't abort if during a valgrind run we get a 720a46c0ec8Sopenharmony_ci * negative offset */ 721a46c0ec8Sopenharmony_ci if ((RUNNING_ON_VALGRIND && in_debugger) || 722a46c0ec8Sopenharmony_ci !strstr(format, "scheduled expiry is in the past")) { 723a46c0ec8Sopenharmony_ci /* noop */ 724a46c0ec8Sopenharmony_ci } else if (!strstr(format, "event processing lagging behind")) { 725a46c0ec8Sopenharmony_ci /* noop */ 726a46c0ec8Sopenharmony_ci } else { 727a46c0ec8Sopenharmony_ci litest_abort_msg("libinput bug triggered, aborting.\n"); 728a46c0ec8Sopenharmony_ci } 729a46c0ec8Sopenharmony_ci } 730a46c0ec8Sopenharmony_ci 731a46c0ec8Sopenharmony_ci if (strstr(format, "Touch jump detected and discarded")) { 732a46c0ec8Sopenharmony_ci litest_abort_msg("libinput touch jump triggered, aborting.\n"); 733a46c0ec8Sopenharmony_ci } 734a46c0ec8Sopenharmony_ci} 735a46c0ec8Sopenharmony_ci 736a46c0ec8Sopenharmony_cistatic void 737a46c0ec8Sopenharmony_cilitest_init_device_udev_rules(struct litest_test_device *dev, FILE *f) 738a46c0ec8Sopenharmony_ci{ 739a46c0ec8Sopenharmony_ci const struct key_value_str *kv; 740a46c0ec8Sopenharmony_ci static int count; 741a46c0ec8Sopenharmony_ci bool need_keyboard_builtin = false; 742a46c0ec8Sopenharmony_ci 743a46c0ec8Sopenharmony_ci if (dev->udev_properties[0].key == NULL) 744a46c0ec8Sopenharmony_ci return; 745a46c0ec8Sopenharmony_ci 746a46c0ec8Sopenharmony_ci count++; 747a46c0ec8Sopenharmony_ci 748a46c0ec8Sopenharmony_ci fprintf(f, "# %s\n", dev->shortname); 749a46c0ec8Sopenharmony_ci fprintf(f, "ACTION==\"remove\", GOTO=\"rule%d_end\"\n", count); 750a46c0ec8Sopenharmony_ci fprintf(f, "KERNEL!=\"event*\", GOTO=\"rule%d_end\"\n", count); 751a46c0ec8Sopenharmony_ci 752a46c0ec8Sopenharmony_ci fprintf(f, "ATTRS{name}==\"litest %s*\"", dev->name); 753a46c0ec8Sopenharmony_ci 754a46c0ec8Sopenharmony_ci kv = dev->udev_properties; 755a46c0ec8Sopenharmony_ci while (kv->key) { 756a46c0ec8Sopenharmony_ci fprintf(f, ", \\\n\tENV{%s}=\"%s\"", kv->key, kv->value); 757a46c0ec8Sopenharmony_ci if (strneq(kv->key, "EVDEV_ABS_", 10)) 758a46c0ec8Sopenharmony_ci need_keyboard_builtin = true; 759a46c0ec8Sopenharmony_ci kv++; 760a46c0ec8Sopenharmony_ci } 761a46c0ec8Sopenharmony_ci fprintf(f, "\n"); 762a46c0ec8Sopenharmony_ci 763a46c0ec8Sopenharmony_ci /* Special case: the udev keyboard builtin is only run for hwdb 764a46c0ec8Sopenharmony_ci * matches but we don't set any up in litest. So instead scan the 765a46c0ec8Sopenharmony_ci * device's udev properties for any EVDEV_ABS properties and where 766a46c0ec8Sopenharmony_ci * they exist, force a (re-)run of the keyboard builtin to set up 767a46c0ec8Sopenharmony_ci * the evdev device correctly. 768a46c0ec8Sopenharmony_ci * This needs to be done as separate rule apparently, otherwise the 769a46c0ec8Sopenharmony_ci * ENV variables aren't set yet by the time the builtin runs. 770a46c0ec8Sopenharmony_ci */ 771a46c0ec8Sopenharmony_ci if (need_keyboard_builtin) { 772a46c0ec8Sopenharmony_ci fprintf(f, "" 773a46c0ec8Sopenharmony_ci "ATTRS{name}==\"litest %s*\"," 774a46c0ec8Sopenharmony_ci " IMPORT{builtin}=\"keyboard\"\n", 775a46c0ec8Sopenharmony_ci dev->name); 776a46c0ec8Sopenharmony_ci } 777a46c0ec8Sopenharmony_ci 778a46c0ec8Sopenharmony_ci fprintf(f, "LABEL=\"rule%d_end\"\n\n", count);; 779a46c0ec8Sopenharmony_ci} 780a46c0ec8Sopenharmony_ci 781a46c0ec8Sopenharmony_cistatic void 782a46c0ec8Sopenharmony_cilitest_init_all_device_udev_rules(struct list *created_files) 783a46c0ec8Sopenharmony_ci{ 784a46c0ec8Sopenharmony_ci struct created_file *file = zalloc(sizeof(*file)); 785a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 786a46c0ec8Sopenharmony_ci char *path = NULL; 787a46c0ec8Sopenharmony_ci FILE *f; 788a46c0ec8Sopenharmony_ci int rc; 789a46c0ec8Sopenharmony_ci int fd; 790a46c0ec8Sopenharmony_ci 791a46c0ec8Sopenharmony_ci rc = xasprintf(&path, 792a46c0ec8Sopenharmony_ci "%s/99-litest-XXXXXX.rules", 793a46c0ec8Sopenharmony_ci UDEV_RULES_D); 794a46c0ec8Sopenharmony_ci litest_assert_int_gt(rc, 0); 795a46c0ec8Sopenharmony_ci 796a46c0ec8Sopenharmony_ci fd = mkstemps(path, 6); 797a46c0ec8Sopenharmony_ci litest_assert_int_ne(fd, -1); 798a46c0ec8Sopenharmony_ci f = fdopen(fd, "w"); 799a46c0ec8Sopenharmony_ci litest_assert_notnull(f); 800a46c0ec8Sopenharmony_ci 801a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) 802a46c0ec8Sopenharmony_ci litest_init_device_udev_rules(dev, f); 803a46c0ec8Sopenharmony_ci 804a46c0ec8Sopenharmony_ci fclose(f); 805a46c0ec8Sopenharmony_ci 806a46c0ec8Sopenharmony_ci file->path = path; 807a46c0ec8Sopenharmony_ci list_insert(created_files, &file->link); 808a46c0ec8Sopenharmony_ci} 809a46c0ec8Sopenharmony_ci 810a46c0ec8Sopenharmony_cistatic int 811a46c0ec8Sopenharmony_ciopen_restricted(const char *path, int flags, void *userdata) 812a46c0ec8Sopenharmony_ci{ 813a46c0ec8Sopenharmony_ci const char prefix[] = "/dev/input/event"; 814a46c0ec8Sopenharmony_ci struct litest_context *ctx = userdata; 815a46c0ec8Sopenharmony_ci struct path *p; 816a46c0ec8Sopenharmony_ci int fd; 817a46c0ec8Sopenharmony_ci 818a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(ctx); 819a46c0ec8Sopenharmony_ci 820a46c0ec8Sopenharmony_ci fd = open(path, flags); 821a46c0ec8Sopenharmony_ci if (fd < 0) 822a46c0ec8Sopenharmony_ci return -errno; 823a46c0ec8Sopenharmony_ci 824a46c0ec8Sopenharmony_ci if (strneq(path, prefix, strlen(prefix))) { 825a46c0ec8Sopenharmony_ci p = zalloc(sizeof *p); 826a46c0ec8Sopenharmony_ci p->path = safe_strdup(path); 827a46c0ec8Sopenharmony_ci p->fd = fd; 828a46c0ec8Sopenharmony_ci /* We specifically insert here so that the most-recently 829a46c0ec8Sopenharmony_ci * opened path is the first one in the list. This helps when 830a46c0ec8Sopenharmony_ci * we have multiple test devices with the same device path, 831a46c0ec8Sopenharmony_ci * the fd of the most recent device is the first one to get 832a46c0ec8Sopenharmony_ci * grabbed 833a46c0ec8Sopenharmony_ci */ 834a46c0ec8Sopenharmony_ci list_insert(&ctx->paths, &p->link); 835a46c0ec8Sopenharmony_ci } 836a46c0ec8Sopenharmony_ci 837a46c0ec8Sopenharmony_ci return fd; 838a46c0ec8Sopenharmony_ci} 839a46c0ec8Sopenharmony_ci 840a46c0ec8Sopenharmony_cistatic void 841a46c0ec8Sopenharmony_ciclose_restricted(int fd, void *userdata) 842a46c0ec8Sopenharmony_ci{ 843a46c0ec8Sopenharmony_ci struct litest_context *ctx = userdata; 844a46c0ec8Sopenharmony_ci struct path *p; 845a46c0ec8Sopenharmony_ci 846a46c0ec8Sopenharmony_ci list_for_each_safe(p, &ctx->paths, link) { 847a46c0ec8Sopenharmony_ci if (p->fd != fd) 848a46c0ec8Sopenharmony_ci continue; 849a46c0ec8Sopenharmony_ci list_remove(&p->link); 850a46c0ec8Sopenharmony_ci free(p->path); 851a46c0ec8Sopenharmony_ci free(p); 852a46c0ec8Sopenharmony_ci } 853a46c0ec8Sopenharmony_ci 854a46c0ec8Sopenharmony_ci close(fd); 855a46c0ec8Sopenharmony_ci} 856a46c0ec8Sopenharmony_ci 857a46c0ec8Sopenharmony_cistatic struct libinput_interface interface = { 858a46c0ec8Sopenharmony_ci .open_restricted = open_restricted, 859a46c0ec8Sopenharmony_ci .close_restricted = close_restricted, 860a46c0ec8Sopenharmony_ci}; 861a46c0ec8Sopenharmony_ci 862a46c0ec8Sopenharmony_cistatic void 863a46c0ec8Sopenharmony_cilitest_signal(int sig) 864a46c0ec8Sopenharmony_ci{ 865a46c0ec8Sopenharmony_ci struct created_file *f; 866a46c0ec8Sopenharmony_ci 867a46c0ec8Sopenharmony_ci list_for_each_safe(f, &created_files_list, link) { 868a46c0ec8Sopenharmony_ci list_remove(&f->link); 869a46c0ec8Sopenharmony_ci unlink(f->path); 870a46c0ec8Sopenharmony_ci rmdir(f->path); 871a46c0ec8Sopenharmony_ci /* in the sighandler, we can't free */ 872a46c0ec8Sopenharmony_ci } 873a46c0ec8Sopenharmony_ci 874a46c0ec8Sopenharmony_ci if (fork() == 0) { 875a46c0ec8Sopenharmony_ci /* child, we can run system() */ 876a46c0ec8Sopenharmony_ci litest_reload_udev_rules(); 877a46c0ec8Sopenharmony_ci exit(0); 878a46c0ec8Sopenharmony_ci } 879a46c0ec8Sopenharmony_ci 880a46c0ec8Sopenharmony_ci exit(1); 881a46c0ec8Sopenharmony_ci} 882a46c0ec8Sopenharmony_ci 883a46c0ec8Sopenharmony_cistatic inline void 884a46c0ec8Sopenharmony_cilitest_setup_sighandler(int sig) 885a46c0ec8Sopenharmony_ci{ 886a46c0ec8Sopenharmony_ci struct sigaction act, oact; 887a46c0ec8Sopenharmony_ci int rc; 888a46c0ec8Sopenharmony_ci 889a46c0ec8Sopenharmony_ci sigemptyset(&act.sa_mask); 890a46c0ec8Sopenharmony_ci sigaddset(&act.sa_mask, sig); 891a46c0ec8Sopenharmony_ci act.sa_flags = 0; 892a46c0ec8Sopenharmony_ci act.sa_handler = litest_signal; 893a46c0ec8Sopenharmony_ci rc = sigaction(sig, &act, &oact); 894a46c0ec8Sopenharmony_ci litest_assert_int_ne(rc, -1); 895a46c0ec8Sopenharmony_ci} 896a46c0ec8Sopenharmony_ci 897a46c0ec8Sopenharmony_cistatic void 898a46c0ec8Sopenharmony_cilitest_free_test_list(struct list *tests) 899a46c0ec8Sopenharmony_ci{ 900a46c0ec8Sopenharmony_ci struct suite *s; 901a46c0ec8Sopenharmony_ci 902a46c0ec8Sopenharmony_ci list_for_each_safe(s, tests, node) { 903a46c0ec8Sopenharmony_ci struct test *t; 904a46c0ec8Sopenharmony_ci 905a46c0ec8Sopenharmony_ci list_for_each_safe(t, &s->tests, node) { 906a46c0ec8Sopenharmony_ci free(t->name); 907a46c0ec8Sopenharmony_ci free(t->devname); 908a46c0ec8Sopenharmony_ci list_remove(&t->node); 909a46c0ec8Sopenharmony_ci free(t); 910a46c0ec8Sopenharmony_ci } 911a46c0ec8Sopenharmony_ci 912a46c0ec8Sopenharmony_ci list_remove(&s->node); 913a46c0ec8Sopenharmony_ci free(s->name); 914a46c0ec8Sopenharmony_ci free(s); 915a46c0ec8Sopenharmony_ci } 916a46c0ec8Sopenharmony_ci} 917a46c0ec8Sopenharmony_ci 918a46c0ec8Sopenharmony_ciLIBINPUT_ATTRIBUTE_PRINTF(3, 0) 919a46c0ec8Sopenharmony_cistatic inline void 920a46c0ec8Sopenharmony_ciquirk_log_handler(struct libinput *unused, 921a46c0ec8Sopenharmony_ci enum libinput_log_priority priority, 922a46c0ec8Sopenharmony_ci const char *format, 923a46c0ec8Sopenharmony_ci va_list args) 924a46c0ec8Sopenharmony_ci{ 925a46c0ec8Sopenharmony_ci if (priority < LIBINPUT_LOG_PRIORITY_ERROR) 926a46c0ec8Sopenharmony_ci return; 927a46c0ec8Sopenharmony_ci 928a46c0ec8Sopenharmony_ci vfprintf(stderr, format, args); 929a46c0ec8Sopenharmony_ci} 930a46c0ec8Sopenharmony_ci 931a46c0ec8Sopenharmony_cistatic void 932a46c0ec8Sopenharmony_cilitest_export_xml(SRunner *sr, const char *xml_prefix) 933a46c0ec8Sopenharmony_ci{ 934a46c0ec8Sopenharmony_ci TestResult **results; 935a46c0ec8Sopenharmony_ci int nresults, nfailed; 936a46c0ec8Sopenharmony_ci char *filename; 937a46c0ec8Sopenharmony_ci int fd; 938a46c0ec8Sopenharmony_ci 939a46c0ec8Sopenharmony_ci /* This is the minimum-effort implementation here because its only 940a46c0ec8Sopenharmony_ci * real purpose is to make test logs look pretty in the gitlab CI. 941a46c0ec8Sopenharmony_ci * 942a46c0ec8Sopenharmony_ci * Which means: 943a46c0ec8Sopenharmony_ci * - there's no filename validation, if you supply a filename that 944a46c0ec8Sopenharmony_ci * mkstemps doesn't like, things go boom. 945a46c0ec8Sopenharmony_ci * - every fork writes out a separate junit.xml file. gitlab is better 946a46c0ec8Sopenharmony_ci * at collecting lots of files than I am at writing code to collect 947a46c0ec8Sopenharmony_ci * this across forks to write out only one file. 948a46c0ec8Sopenharmony_ci * - most of the content is pretty useless because libcheck only gives 949a46c0ec8Sopenharmony_ci * us minimal information. the libcheck XML file has more info like 950a46c0ec8Sopenharmony_ci * the duration of each test but it's more complicated to extract 951a46c0ec8Sopenharmony_ci * and we don't need it for now. 952a46c0ec8Sopenharmony_ci */ 953a46c0ec8Sopenharmony_ci filename = safe_strdup(xml_prefix); 954a46c0ec8Sopenharmony_ci fd = mkstemps(filename, 4); 955a46c0ec8Sopenharmony_ci 956a46c0ec8Sopenharmony_ci results = srunner_results(sr); 957a46c0ec8Sopenharmony_ci nresults = srunner_ntests_run(sr); 958a46c0ec8Sopenharmony_ci nfailed = srunner_ntests_failed(sr); 959a46c0ec8Sopenharmony_ci 960a46c0ec8Sopenharmony_ci dprintf(fd, "<?xml version=\"1.0\"?>\n"); 961a46c0ec8Sopenharmony_ci dprintf(fd, "<testsuites id=\"%s\" tests=\"%d\" failures=\"%d\">\n", 962a46c0ec8Sopenharmony_ci filename, 963a46c0ec8Sopenharmony_ci nresults, 964a46c0ec8Sopenharmony_ci nfailed); 965a46c0ec8Sopenharmony_ci dprintf(fd, " <testsuite>\n"); 966a46c0ec8Sopenharmony_ci for (int i = 0; i < nresults; i++) { 967a46c0ec8Sopenharmony_ci TestResult *r = results[i]; 968a46c0ec8Sopenharmony_ci 969a46c0ec8Sopenharmony_ci dprintf(fd, " <testcase id=\"%s\" name=\"%s\" %s>\n", 970a46c0ec8Sopenharmony_ci tr_tcname(r), 971a46c0ec8Sopenharmony_ci tr_tcname(r), 972a46c0ec8Sopenharmony_ci tr_rtype(r) == CK_PASS ? "/" : ""); 973a46c0ec8Sopenharmony_ci if (tr_rtype(r) != CK_PASS) { 974a46c0ec8Sopenharmony_ci dprintf(fd, " <failure message=\"%s:%d\">\n", 975a46c0ec8Sopenharmony_ci tr_lfile(r), 976a46c0ec8Sopenharmony_ci tr_lno(r)); 977a46c0ec8Sopenharmony_ci dprintf(fd, " %s:%d\n", tr_lfile(r), tr_lno(r)); 978a46c0ec8Sopenharmony_ci dprintf(fd, " %s\n", tr_tcname(r)); 979a46c0ec8Sopenharmony_ci dprintf(fd, "\n"); 980a46c0ec8Sopenharmony_ci dprintf(fd, " %s\n", tr_msg(r)); 981a46c0ec8Sopenharmony_ci dprintf(fd, " </failure>\n"); 982a46c0ec8Sopenharmony_ci dprintf(fd, " </testcase>\n"); 983a46c0ec8Sopenharmony_ci } 984a46c0ec8Sopenharmony_ci } 985a46c0ec8Sopenharmony_ci dprintf(fd, " </testsuite>\n"); 986a46c0ec8Sopenharmony_ci dprintf(fd, "</testsuites>\n"); 987a46c0ec8Sopenharmony_ci 988a46c0ec8Sopenharmony_ci free(results); 989a46c0ec8Sopenharmony_ci close(fd); 990a46c0ec8Sopenharmony_ci free(filename); 991a46c0ec8Sopenharmony_ci} 992a46c0ec8Sopenharmony_ci 993a46c0ec8Sopenharmony_cistatic int 994a46c0ec8Sopenharmony_cilitest_run_suite(struct list *tests, int which, int max, int error_fd) 995a46c0ec8Sopenharmony_ci{ 996a46c0ec8Sopenharmony_ci int failed = 0; 997a46c0ec8Sopenharmony_ci SRunner *sr = NULL; 998a46c0ec8Sopenharmony_ci struct suite *s; 999a46c0ec8Sopenharmony_ci struct test *t; 1000a46c0ec8Sopenharmony_ci int count = -1; 1001a46c0ec8Sopenharmony_ci struct name { 1002a46c0ec8Sopenharmony_ci struct list node; 1003a46c0ec8Sopenharmony_ci char *name; 1004a46c0ec8Sopenharmony_ci }; 1005a46c0ec8Sopenharmony_ci struct name *n; 1006a46c0ec8Sopenharmony_ci struct list testnames; 1007a46c0ec8Sopenharmony_ci const char *data_path; 1008a46c0ec8Sopenharmony_ci 1009a46c0ec8Sopenharmony_ci data_path = getenv("LIBINPUT_QUIRKS_DIR"); 1010a46c0ec8Sopenharmony_ci if (!data_path) 1011a46c0ec8Sopenharmony_ci data_path = LIBINPUT_QUIRKS_DIR; 1012a46c0ec8Sopenharmony_ci 1013a46c0ec8Sopenharmony_ci quirks_context = quirks_init_subsystem(data_path, 1014a46c0ec8Sopenharmony_ci NULL, 1015a46c0ec8Sopenharmony_ci quirk_log_handler, 1016a46c0ec8Sopenharmony_ci NULL, 1017a46c0ec8Sopenharmony_ci QLOG_LIBINPUT_LOGGING); 1018a46c0ec8Sopenharmony_ci 1019a46c0ec8Sopenharmony_ci /* Check just takes the suite/test name pointers but doesn't strdup 1020a46c0ec8Sopenharmony_ci * them - we have to keep them around */ 1021a46c0ec8Sopenharmony_ci list_init(&testnames); 1022a46c0ec8Sopenharmony_ci 1023a46c0ec8Sopenharmony_ci /* For each test, create one test suite with one test case, then 1024a46c0ec8Sopenharmony_ci add it to the test runner. The only benefit suites give us in 1025a46c0ec8Sopenharmony_ci check is that we can filter them, but our test runner has a 1026a46c0ec8Sopenharmony_ci --filter-group anyway. */ 1027a46c0ec8Sopenharmony_ci list_for_each(s, tests, node) { 1028a46c0ec8Sopenharmony_ci list_for_each(t, &s->tests, node) { 1029a46c0ec8Sopenharmony_ci Suite *suite; 1030a46c0ec8Sopenharmony_ci TCase *tc; 1031a46c0ec8Sopenharmony_ci char *sname, *tname; 1032a46c0ec8Sopenharmony_ci 1033a46c0ec8Sopenharmony_ci /* We run deviceless tests as part of the normal 1034a46c0ec8Sopenharmony_ci * test suite runner, just in case. Filtering 1035a46c0ec8Sopenharmony_ci * all the other ones out just for the case where 1036a46c0ec8Sopenharmony_ci * we can't run the full runner. 1037a46c0ec8Sopenharmony_ci */ 1038a46c0ec8Sopenharmony_ci if (run_deviceless && !t->deviceless) 1039a46c0ec8Sopenharmony_ci continue; 1040a46c0ec8Sopenharmony_ci 1041a46c0ec8Sopenharmony_ci count = (count + 1) % max; 1042a46c0ec8Sopenharmony_ci if (max != 1 && (count % max) != which) 1043a46c0ec8Sopenharmony_ci continue; 1044a46c0ec8Sopenharmony_ci 1045a46c0ec8Sopenharmony_ci xasprintf(&sname, 1046a46c0ec8Sopenharmony_ci "%s:%s:%s", 1047a46c0ec8Sopenharmony_ci s->name, 1048a46c0ec8Sopenharmony_ci t->name, 1049a46c0ec8Sopenharmony_ci t->devname); 1050a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(sname); 1051a46c0ec8Sopenharmony_ci n = zalloc(sizeof(*n)); 1052a46c0ec8Sopenharmony_ci n->name = sname; 1053a46c0ec8Sopenharmony_ci list_insert(&testnames, &n->node); 1054a46c0ec8Sopenharmony_ci 1055a46c0ec8Sopenharmony_ci xasprintf(&tname, 1056a46c0ec8Sopenharmony_ci "%s:%s", 1057a46c0ec8Sopenharmony_ci t->name, 1058a46c0ec8Sopenharmony_ci t->devname); 1059a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(tname); 1060a46c0ec8Sopenharmony_ci n = zalloc(sizeof(*n)); 1061a46c0ec8Sopenharmony_ci n->name = tname; 1062a46c0ec8Sopenharmony_ci list_insert(&testnames, &n->node); 1063a46c0ec8Sopenharmony_ci 1064a46c0ec8Sopenharmony_ci tc = tcase_create(tname); 1065a46c0ec8Sopenharmony_ci tcase_add_checked_fixture(tc, 1066a46c0ec8Sopenharmony_ci t->setup, 1067a46c0ec8Sopenharmony_ci t->teardown); 1068a46c0ec8Sopenharmony_ci if (t->range.upper != t->range.lower) 1069a46c0ec8Sopenharmony_ci tcase_add_loop_test(tc, 1070a46c0ec8Sopenharmony_ci t->func, 1071a46c0ec8Sopenharmony_ci t->range.lower, 1072a46c0ec8Sopenharmony_ci t->range.upper); 1073a46c0ec8Sopenharmony_ci else 1074a46c0ec8Sopenharmony_ci tcase_add_test(tc, t->func); 1075a46c0ec8Sopenharmony_ci 1076a46c0ec8Sopenharmony_ci suite = suite_create(sname); 1077a46c0ec8Sopenharmony_ci suite_add_tcase(suite, tc); 1078a46c0ec8Sopenharmony_ci 1079a46c0ec8Sopenharmony_ci if (!sr) 1080a46c0ec8Sopenharmony_ci sr = srunner_create(suite); 1081a46c0ec8Sopenharmony_ci else 1082a46c0ec8Sopenharmony_ci srunner_add_suite(sr, suite); 1083a46c0ec8Sopenharmony_ci } 1084a46c0ec8Sopenharmony_ci } 1085a46c0ec8Sopenharmony_ci 1086a46c0ec8Sopenharmony_ci if (!sr) 1087a46c0ec8Sopenharmony_ci goto out; 1088a46c0ec8Sopenharmony_ci 1089a46c0ec8Sopenharmony_ci srunner_run_all(sr, CK_ENV); 1090a46c0ec8Sopenharmony_ci if (xml_prefix) 1091a46c0ec8Sopenharmony_ci litest_export_xml(sr, xml_prefix); 1092a46c0ec8Sopenharmony_ci 1093a46c0ec8Sopenharmony_ci 1094a46c0ec8Sopenharmony_ci failed = srunner_ntests_failed(sr); 1095a46c0ec8Sopenharmony_ci if (failed) { 1096a46c0ec8Sopenharmony_ci TestResult **trs; 1097a46c0ec8Sopenharmony_ci 1098a46c0ec8Sopenharmony_ci trs = srunner_failures(sr); 1099a46c0ec8Sopenharmony_ci for (int i = 0; i < failed; i++) { 1100a46c0ec8Sopenharmony_ci char tname[256]; 1101a46c0ec8Sopenharmony_ci char *c = tname; 1102a46c0ec8Sopenharmony_ci 1103a46c0ec8Sopenharmony_ci /* tr_tcname is in the form "suite:testcase", let's 1104a46c0ec8Sopenharmony_ci * convert this to "suite(testcase)" to make 1105a46c0ec8Sopenharmony_ci * double-click selection in the terminal a bit 1106a46c0ec8Sopenharmony_ci * easier. */ 1107a46c0ec8Sopenharmony_ci snprintf(tname, sizeof(tname), "%s)", tr_tcname(trs[i])); 1108a46c0ec8Sopenharmony_ci if ((c = index(c, ':'))) 1109a46c0ec8Sopenharmony_ci *c = '('; 1110a46c0ec8Sopenharmony_ci 1111a46c0ec8Sopenharmony_ci dprintf(error_fd, 1112a46c0ec8Sopenharmony_ci ":: Failure: %s:%d: %s\n", 1113a46c0ec8Sopenharmony_ci tr_lfile(trs[i]), 1114a46c0ec8Sopenharmony_ci tr_lno(trs[i]), 1115a46c0ec8Sopenharmony_ci tname); 1116a46c0ec8Sopenharmony_ci } 1117a46c0ec8Sopenharmony_ci free(trs); 1118a46c0ec8Sopenharmony_ci } 1119a46c0ec8Sopenharmony_ci srunner_free(sr); 1120a46c0ec8Sopenharmony_ciout: 1121a46c0ec8Sopenharmony_ci list_for_each_safe(n, &testnames, node) { 1122a46c0ec8Sopenharmony_ci free(n->name); 1123a46c0ec8Sopenharmony_ci free(n); 1124a46c0ec8Sopenharmony_ci } 1125a46c0ec8Sopenharmony_ci 1126a46c0ec8Sopenharmony_ci quirks_context_unref(quirks_context); 1127a46c0ec8Sopenharmony_ci 1128a46c0ec8Sopenharmony_ci return failed; 1129a46c0ec8Sopenharmony_ci} 1130a46c0ec8Sopenharmony_ci 1131a46c0ec8Sopenharmony_cistatic int 1132a46c0ec8Sopenharmony_cilitest_fork_subtests(struct list *tests, int max_forks) 1133a46c0ec8Sopenharmony_ci{ 1134a46c0ec8Sopenharmony_ci int failed = 0; 1135a46c0ec8Sopenharmony_ci int status; 1136a46c0ec8Sopenharmony_ci pid_t pid; 1137a46c0ec8Sopenharmony_ci int f; 1138a46c0ec8Sopenharmony_ci int pipes[max_forks]; 1139a46c0ec8Sopenharmony_ci 1140a46c0ec8Sopenharmony_ci for (f = 0; f < max_forks; f++) { 1141a46c0ec8Sopenharmony_ci int rc; 1142a46c0ec8Sopenharmony_ci int pipefd[2]; 1143a46c0ec8Sopenharmony_ci 1144a46c0ec8Sopenharmony_ci rc = pipe2(pipefd, O_NONBLOCK); 1145a46c0ec8Sopenharmony_ci assert(rc != -1); 1146a46c0ec8Sopenharmony_ci 1147a46c0ec8Sopenharmony_ci pid = fork(); 1148a46c0ec8Sopenharmony_ci if (pid == 0) { 1149a46c0ec8Sopenharmony_ci close(pipefd[0]); 1150a46c0ec8Sopenharmony_ci failed = litest_run_suite(tests, 1151a46c0ec8Sopenharmony_ci f, 1152a46c0ec8Sopenharmony_ci max_forks, 1153a46c0ec8Sopenharmony_ci pipefd[1]); 1154a46c0ec8Sopenharmony_ci 1155a46c0ec8Sopenharmony_ci litest_free_test_list(&all_tests); 1156a46c0ec8Sopenharmony_ci exit(failed); 1157a46c0ec8Sopenharmony_ci /* child always exits here */ 1158a46c0ec8Sopenharmony_ci } else { 1159a46c0ec8Sopenharmony_ci pipes[f] = pipefd[0]; 1160a46c0ec8Sopenharmony_ci close(pipefd[1]); 1161a46c0ec8Sopenharmony_ci } 1162a46c0ec8Sopenharmony_ci } 1163a46c0ec8Sopenharmony_ci 1164a46c0ec8Sopenharmony_ci /* parent process only */ 1165a46c0ec8Sopenharmony_ci while (wait(&status) != -1 && errno != ECHILD) { 1166a46c0ec8Sopenharmony_ci if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 1167a46c0ec8Sopenharmony_ci failed = 1; 1168a46c0ec8Sopenharmony_ci } 1169a46c0ec8Sopenharmony_ci 1170a46c0ec8Sopenharmony_ci for (f = 0; f < max_forks; f++) { 1171a46c0ec8Sopenharmony_ci char buf[1024] = {0}; 1172a46c0ec8Sopenharmony_ci int rc; 1173a46c0ec8Sopenharmony_ci 1174a46c0ec8Sopenharmony_ci while ((rc = read(pipes[f], buf, sizeof(buf) - 1)) > 0) { 1175a46c0ec8Sopenharmony_ci buf[rc] = '\0'; 1176a46c0ec8Sopenharmony_ci fprintf(stderr, "%s", buf); 1177a46c0ec8Sopenharmony_ci } 1178a46c0ec8Sopenharmony_ci 1179a46c0ec8Sopenharmony_ci close(pipes[f]); 1180a46c0ec8Sopenharmony_ci } 1181a46c0ec8Sopenharmony_ci 1182a46c0ec8Sopenharmony_ci return failed; 1183a46c0ec8Sopenharmony_ci} 1184a46c0ec8Sopenharmony_ci 1185a46c0ec8Sopenharmony_cistatic inline int 1186a46c0ec8Sopenharmony_ciinhibit(void) 1187a46c0ec8Sopenharmony_ci{ 1188a46c0ec8Sopenharmony_ci int lock_fd = -1; 1189a46c0ec8Sopenharmony_ci#if HAVE_LIBSYSTEMD 1190a46c0ec8Sopenharmony_ci sd_bus_error error = SD_BUS_ERROR_NULL; 1191a46c0ec8Sopenharmony_ci sd_bus_message *m = NULL; 1192a46c0ec8Sopenharmony_ci sd_bus *bus = NULL; 1193a46c0ec8Sopenharmony_ci int rc; 1194a46c0ec8Sopenharmony_ci 1195a46c0ec8Sopenharmony_ci if (run_deviceless) 1196a46c0ec8Sopenharmony_ci return -1; 1197a46c0ec8Sopenharmony_ci 1198a46c0ec8Sopenharmony_ci rc = sd_bus_open_system(&bus); 1199a46c0ec8Sopenharmony_ci if (rc != 0) { 1200a46c0ec8Sopenharmony_ci fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc)); 1201a46c0ec8Sopenharmony_ci goto out; 1202a46c0ec8Sopenharmony_ci } 1203a46c0ec8Sopenharmony_ci 1204a46c0ec8Sopenharmony_ci rc = sd_bus_call_method(bus, 1205a46c0ec8Sopenharmony_ci "org.freedesktop.login1", 1206a46c0ec8Sopenharmony_ci "/org/freedesktop/login1", 1207a46c0ec8Sopenharmony_ci "org.freedesktop.login1.Manager", 1208a46c0ec8Sopenharmony_ci "Inhibit", 1209a46c0ec8Sopenharmony_ci &error, 1210a46c0ec8Sopenharmony_ci &m, 1211a46c0ec8Sopenharmony_ci "ssss", 1212a46c0ec8Sopenharmony_ci "sleep:shutdown:handle-lid-switch:handle-power-key:handle-suspend-key:handle-hibernate-key", 1213a46c0ec8Sopenharmony_ci "libinput test-suite runner", 1214a46c0ec8Sopenharmony_ci "testing in progress", 1215a46c0ec8Sopenharmony_ci "block"); 1216a46c0ec8Sopenharmony_ci if (rc < 0) { 1217a46c0ec8Sopenharmony_ci fprintf(stderr, "Warning: inhibit failed: %s\n", error.message); 1218a46c0ec8Sopenharmony_ci goto out; 1219a46c0ec8Sopenharmony_ci } 1220a46c0ec8Sopenharmony_ci 1221a46c0ec8Sopenharmony_ci rc = sd_bus_message_read(m, "h", &lock_fd); 1222a46c0ec8Sopenharmony_ci if (rc < 0) { 1223a46c0ec8Sopenharmony_ci fprintf(stderr, "Warning: inhibit failed: %s\n", strerror(-rc)); 1224a46c0ec8Sopenharmony_ci goto out; 1225a46c0ec8Sopenharmony_ci } 1226a46c0ec8Sopenharmony_ci 1227a46c0ec8Sopenharmony_ci lock_fd = dup(lock_fd); 1228a46c0ec8Sopenharmony_ciout: 1229a46c0ec8Sopenharmony_ci sd_bus_error_free(&error); 1230a46c0ec8Sopenharmony_ci sd_bus_message_unref(m); 1231a46c0ec8Sopenharmony_ci sd_bus_close(bus); 1232a46c0ec8Sopenharmony_ci sd_bus_unref(bus); 1233a46c0ec8Sopenharmony_ci#endif 1234a46c0ec8Sopenharmony_ci return lock_fd; 1235a46c0ec8Sopenharmony_ci} 1236a46c0ec8Sopenharmony_ci 1237a46c0ec8Sopenharmony_cistatic inline int 1238a46c0ec8Sopenharmony_cilitest_run(int argc, char **argv) 1239a46c0ec8Sopenharmony_ci{ 1240a46c0ec8Sopenharmony_ci int failed = 0; 1241a46c0ec8Sopenharmony_ci int inhibit_lock_fd; 1242a46c0ec8Sopenharmony_ci 1243a46c0ec8Sopenharmony_ci list_init(&created_files_list); 1244a46c0ec8Sopenharmony_ci 1245a46c0ec8Sopenharmony_ci if (list_empty(&all_tests)) { 1246a46c0ec8Sopenharmony_ci fprintf(stderr, 1247a46c0ec8Sopenharmony_ci "Error: filters are too strict, no tests to run.\n"); 1248a46c0ec8Sopenharmony_ci return 1; 1249a46c0ec8Sopenharmony_ci } 1250a46c0ec8Sopenharmony_ci 1251a46c0ec8Sopenharmony_ci if (getenv("LITEST_VERBOSE")) 1252a46c0ec8Sopenharmony_ci verbose = true; 1253a46c0ec8Sopenharmony_ci 1254a46c0ec8Sopenharmony_ci if (run_deviceless) { 1255a46c0ec8Sopenharmony_ci litest_setup_quirks(&created_files_list, 1256a46c0ec8Sopenharmony_ci QUIRKS_SETUP_USE_SRCDIR); 1257a46c0ec8Sopenharmony_ci } else { 1258a46c0ec8Sopenharmony_ci enum quirks_setup_mode mode; 1259a46c0ec8Sopenharmony_ci litest_init_udev_rules(&created_files_list); 1260a46c0ec8Sopenharmony_ci 1261a46c0ec8Sopenharmony_ci 1262a46c0ec8Sopenharmony_ci mode = use_system_rules_quirks ? 1263a46c0ec8Sopenharmony_ci QUIRKS_SETUP_ONLY_DEVICE : 1264a46c0ec8Sopenharmony_ci QUIRKS_SETUP_FULL; 1265a46c0ec8Sopenharmony_ci litest_setup_quirks(&created_files_list, mode); 1266a46c0ec8Sopenharmony_ci } 1267a46c0ec8Sopenharmony_ci 1268a46c0ec8Sopenharmony_ci litest_setup_sighandler(SIGINT); 1269a46c0ec8Sopenharmony_ci 1270a46c0ec8Sopenharmony_ci inhibit_lock_fd = inhibit(); 1271a46c0ec8Sopenharmony_ci 1272a46c0ec8Sopenharmony_ci if (jobs == 1) 1273a46c0ec8Sopenharmony_ci failed = litest_run_suite(&all_tests, 1, 1, STDERR_FILENO); 1274a46c0ec8Sopenharmony_ci else 1275a46c0ec8Sopenharmony_ci failed = litest_fork_subtests(&all_tests, jobs); 1276a46c0ec8Sopenharmony_ci 1277a46c0ec8Sopenharmony_ci close(inhibit_lock_fd); 1278a46c0ec8Sopenharmony_ci 1279a46c0ec8Sopenharmony_ci litest_free_test_list(&all_tests); 1280a46c0ec8Sopenharmony_ci 1281a46c0ec8Sopenharmony_ci litest_remove_udev_rules(&created_files_list); 1282a46c0ec8Sopenharmony_ci 1283a46c0ec8Sopenharmony_ci return failed; 1284a46c0ec8Sopenharmony_ci} 1285a46c0ec8Sopenharmony_ci 1286a46c0ec8Sopenharmony_cistatic struct input_absinfo * 1287a46c0ec8Sopenharmony_cimerge_absinfo(const struct input_absinfo *orig, 1288a46c0ec8Sopenharmony_ci const struct input_absinfo *override) 1289a46c0ec8Sopenharmony_ci{ 1290a46c0ec8Sopenharmony_ci struct input_absinfo *abs; 1291a46c0ec8Sopenharmony_ci unsigned int nelem, i; 1292a46c0ec8Sopenharmony_ci size_t sz = ABS_MAX + 1; 1293a46c0ec8Sopenharmony_ci 1294a46c0ec8Sopenharmony_ci if (!orig) 1295a46c0ec8Sopenharmony_ci return NULL; 1296a46c0ec8Sopenharmony_ci 1297a46c0ec8Sopenharmony_ci abs = zalloc(sz * sizeof(*abs)); 1298a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(abs); 1299a46c0ec8Sopenharmony_ci 1300a46c0ec8Sopenharmony_ci nelem = 0; 1301a46c0ec8Sopenharmony_ci while (orig[nelem].value != -1) { 1302a46c0ec8Sopenharmony_ci abs[nelem] = orig[nelem]; 1303a46c0ec8Sopenharmony_ci nelem++; 1304a46c0ec8Sopenharmony_ci litest_assert_int_lt(nelem, sz); 1305a46c0ec8Sopenharmony_ci } 1306a46c0ec8Sopenharmony_ci 1307a46c0ec8Sopenharmony_ci /* just append, if the same axis is present twice, libevdev will 1308a46c0ec8Sopenharmony_ci only use the last value anyway */ 1309a46c0ec8Sopenharmony_ci i = 0; 1310a46c0ec8Sopenharmony_ci while (override && override[i].value != -1) { 1311a46c0ec8Sopenharmony_ci abs[nelem++] = override[i++]; 1312a46c0ec8Sopenharmony_ci litest_assert_int_lt(nelem, sz); 1313a46c0ec8Sopenharmony_ci } 1314a46c0ec8Sopenharmony_ci 1315a46c0ec8Sopenharmony_ci litest_assert_int_lt(nelem, sz); 1316a46c0ec8Sopenharmony_ci abs[nelem].value = -1; 1317a46c0ec8Sopenharmony_ci 1318a46c0ec8Sopenharmony_ci return abs; 1319a46c0ec8Sopenharmony_ci} 1320a46c0ec8Sopenharmony_ci 1321a46c0ec8Sopenharmony_cistatic int* 1322a46c0ec8Sopenharmony_cimerge_events(const int *orig, const int *override) 1323a46c0ec8Sopenharmony_ci{ 1324a46c0ec8Sopenharmony_ci int *events; 1325a46c0ec8Sopenharmony_ci unsigned int nelem, i; 1326a46c0ec8Sopenharmony_ci size_t sz = KEY_MAX * 3; 1327a46c0ec8Sopenharmony_ci 1328a46c0ec8Sopenharmony_ci if (!orig) 1329a46c0ec8Sopenharmony_ci return NULL; 1330a46c0ec8Sopenharmony_ci 1331a46c0ec8Sopenharmony_ci events = zalloc(sz * sizeof(int)); 1332a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(events); 1333a46c0ec8Sopenharmony_ci 1334a46c0ec8Sopenharmony_ci nelem = 0; 1335a46c0ec8Sopenharmony_ci while (orig[nelem] != -1) { 1336a46c0ec8Sopenharmony_ci events[nelem] = orig[nelem]; 1337a46c0ec8Sopenharmony_ci nelem++; 1338a46c0ec8Sopenharmony_ci litest_assert_int_lt(nelem, sz); 1339a46c0ec8Sopenharmony_ci } 1340a46c0ec8Sopenharmony_ci 1341a46c0ec8Sopenharmony_ci /* just append, if the same axis is present twice, libevdev will 1342a46c0ec8Sopenharmony_ci * ignore the double definition anyway */ 1343a46c0ec8Sopenharmony_ci i = 0; 1344a46c0ec8Sopenharmony_ci while (override && override[i] != -1) { 1345a46c0ec8Sopenharmony_ci events[nelem++] = override[i++]; 1346a46c0ec8Sopenharmony_ci litest_assert_int_le(nelem, sz); 1347a46c0ec8Sopenharmony_ci } 1348a46c0ec8Sopenharmony_ci 1349a46c0ec8Sopenharmony_ci litest_assert_int_lt(nelem, sz); 1350a46c0ec8Sopenharmony_ci events[nelem] = -1; 1351a46c0ec8Sopenharmony_ci 1352a46c0ec8Sopenharmony_ci return events; 1353a46c0ec8Sopenharmony_ci} 1354a46c0ec8Sopenharmony_ci 1355a46c0ec8Sopenharmony_cistatic inline struct created_file * 1356a46c0ec8Sopenharmony_cilitest_copy_file(const char *dest, const char *src, const char *header, bool is_file) 1357a46c0ec8Sopenharmony_ci{ 1358a46c0ec8Sopenharmony_ci int in, out, length; 1359a46c0ec8Sopenharmony_ci struct created_file *file; 1360a46c0ec8Sopenharmony_ci 1361a46c0ec8Sopenharmony_ci file = zalloc(sizeof(*file)); 1362a46c0ec8Sopenharmony_ci file->path = safe_strdup(dest); 1363a46c0ec8Sopenharmony_ci 1364a46c0ec8Sopenharmony_ci if (strstr(dest, "XXXXXX")) { 1365a46c0ec8Sopenharmony_ci int suffixlen; 1366a46c0ec8Sopenharmony_ci 1367a46c0ec8Sopenharmony_ci suffixlen = file->path + 1368a46c0ec8Sopenharmony_ci strlen(file->path) - 1369a46c0ec8Sopenharmony_ci rindex(file->path, '.'); 1370a46c0ec8Sopenharmony_ci out = mkstemps(file->path, suffixlen); 1371a46c0ec8Sopenharmony_ci } else { 1372a46c0ec8Sopenharmony_ci out = open(file->path, O_CREAT|O_WRONLY, 0644); 1373a46c0ec8Sopenharmony_ci } 1374a46c0ec8Sopenharmony_ci if (out == -1) 1375a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to write to file %s (%s)\n", 1376a46c0ec8Sopenharmony_ci file->path, 1377a46c0ec8Sopenharmony_ci strerror(errno)); 1378a46c0ec8Sopenharmony_ci litest_assert_int_ne(chmod(file->path, 0644), -1); 1379a46c0ec8Sopenharmony_ci 1380a46c0ec8Sopenharmony_ci if (header) { 1381a46c0ec8Sopenharmony_ci length = strlen(header); 1382a46c0ec8Sopenharmony_ci litest_assert_int_eq(write(out, header, length), length); 1383a46c0ec8Sopenharmony_ci } 1384a46c0ec8Sopenharmony_ci 1385a46c0ec8Sopenharmony_ci if (is_file) { 1386a46c0ec8Sopenharmony_ci in = open(src, O_RDONLY); 1387a46c0ec8Sopenharmony_ci if (in == -1) 1388a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to open file %s (%s)\n", 1389a46c0ec8Sopenharmony_ci src, 1390a46c0ec8Sopenharmony_ci strerror(errno)); 1391a46c0ec8Sopenharmony_ci /* lazy, just check for error and empty file copy */ 1392a46c0ec8Sopenharmony_ci litest_assert_int_gt(litest_send_file(out, in), 0); 1393a46c0ec8Sopenharmony_ci close(in); 1394a46c0ec8Sopenharmony_ci } else { 1395a46c0ec8Sopenharmony_ci size_t written = write(out, src, strlen(src)); 1396a46c0ec8Sopenharmony_ci litest_assert_int_eq(written, strlen(src)); 1397a46c0ec8Sopenharmony_ci 1398a46c0ec8Sopenharmony_ci } 1399a46c0ec8Sopenharmony_ci close(out); 1400a46c0ec8Sopenharmony_ci 1401a46c0ec8Sopenharmony_ci return file; 1402a46c0ec8Sopenharmony_ci} 1403a46c0ec8Sopenharmony_ci 1404a46c0ec8Sopenharmony_cistatic inline void 1405a46c0ec8Sopenharmony_cilitest_install_model_quirks(struct list *created_files_list) 1406a46c0ec8Sopenharmony_ci{ 1407a46c0ec8Sopenharmony_ci const char *warning = 1408a46c0ec8Sopenharmony_ci "#################################################################\n" 1409a46c0ec8Sopenharmony_ci "# WARNING: REMOVE THIS FILE\n" 1410a46c0ec8Sopenharmony_ci "# This is a run-time file for the libinput test suite and\n" 1411a46c0ec8Sopenharmony_ci "# should be removed on exit. If the test-suite is not currently \n" 1412a46c0ec8Sopenharmony_ci "# running, remove this file\n" 1413a46c0ec8Sopenharmony_ci "#################################################################\n\n"; 1414a46c0ec8Sopenharmony_ci struct created_file *file; 1415a46c0ec8Sopenharmony_ci const char *test_device_udev_rule = "KERNELS==\"*input*\", " 1416a46c0ec8Sopenharmony_ci "ATTRS{name}==\"litest *\", " 1417a46c0ec8Sopenharmony_ci "ENV{LIBINPUT_TEST_DEVICE}=\"1\""; 1418a46c0ec8Sopenharmony_ci 1419a46c0ec8Sopenharmony_ci file = litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE, 1420a46c0ec8Sopenharmony_ci test_device_udev_rule, 1421a46c0ec8Sopenharmony_ci warning, 1422a46c0ec8Sopenharmony_ci false); 1423a46c0ec8Sopenharmony_ci list_insert(created_files_list, &file->link); 1424a46c0ec8Sopenharmony_ci 1425a46c0ec8Sopenharmony_ci /* Only install the litest device rule when we're running as system 1426a46c0ec8Sopenharmony_ci * test suite, we expect the others to be in place already */ 1427a46c0ec8Sopenharmony_ci if (use_system_rules_quirks) 1428a46c0ec8Sopenharmony_ci return; 1429a46c0ec8Sopenharmony_ci 1430a46c0ec8Sopenharmony_ci file = litest_copy_file(UDEV_DEVICE_GROUPS_FILE, 1431a46c0ec8Sopenharmony_ci LIBINPUT_DEVICE_GROUPS_RULES_FILE, 1432a46c0ec8Sopenharmony_ci warning, 1433a46c0ec8Sopenharmony_ci true); 1434a46c0ec8Sopenharmony_ci list_insert(created_files_list, &file->link); 1435a46c0ec8Sopenharmony_ci 1436a46c0ec8Sopenharmony_ci file = litest_copy_file(UDEV_FUZZ_OVERRIDE_RULE_FILE, 1437a46c0ec8Sopenharmony_ci LIBINPUT_FUZZ_OVERRIDE_UDEV_RULES_FILE, 1438a46c0ec8Sopenharmony_ci warning, 1439a46c0ec8Sopenharmony_ci true); 1440a46c0ec8Sopenharmony_ci list_insert(created_files_list, &file->link); 1441a46c0ec8Sopenharmony_ci} 1442a46c0ec8Sopenharmony_ci 1443a46c0ec8Sopenharmony_cistatic char * 1444a46c0ec8Sopenharmony_cilitest_init_device_quirk_file(const char *data_dir, 1445a46c0ec8Sopenharmony_ci struct litest_test_device *dev) 1446a46c0ec8Sopenharmony_ci{ 1447a46c0ec8Sopenharmony_ci int fd; 1448a46c0ec8Sopenharmony_ci FILE *f; 1449a46c0ec8Sopenharmony_ci char path[PATH_MAX]; 1450a46c0ec8Sopenharmony_ci static int count; 1451a46c0ec8Sopenharmony_ci 1452a46c0ec8Sopenharmony_ci if (!dev->quirk_file) 1453a46c0ec8Sopenharmony_ci return NULL; 1454a46c0ec8Sopenharmony_ci 1455a46c0ec8Sopenharmony_ci snprintf(path, sizeof(path), 1456a46c0ec8Sopenharmony_ci "%s/99-%03d-%s.quirks", 1457a46c0ec8Sopenharmony_ci data_dir, 1458a46c0ec8Sopenharmony_ci ++count, 1459a46c0ec8Sopenharmony_ci dev->shortname); 1460a46c0ec8Sopenharmony_ci fd = open(path, O_CREAT|O_WRONLY, 0644); 1461a46c0ec8Sopenharmony_ci litest_assert_int_ne(fd, -1); 1462a46c0ec8Sopenharmony_ci f = fdopen(fd, "w"); 1463a46c0ec8Sopenharmony_ci litest_assert_notnull(f); 1464a46c0ec8Sopenharmony_ci litest_assert_int_ge(fputs(dev->quirk_file, f), 0); 1465a46c0ec8Sopenharmony_ci fclose(f); 1466a46c0ec8Sopenharmony_ci 1467a46c0ec8Sopenharmony_ci return safe_strdup(path); 1468a46c0ec8Sopenharmony_ci} 1469a46c0ec8Sopenharmony_ci 1470a46c0ec8Sopenharmony_cistatic int is_quirks_file(const struct dirent *dir) { 1471a46c0ec8Sopenharmony_ci return strendswith(dir->d_name, ".quirks"); 1472a46c0ec8Sopenharmony_ci} 1473a46c0ec8Sopenharmony_ci 1474a46c0ec8Sopenharmony_ci/** 1475a46c0ec8Sopenharmony_ci * Install the quirks from the quirks/ source directory. 1476a46c0ec8Sopenharmony_ci */ 1477a46c0ec8Sopenharmony_cistatic void 1478a46c0ec8Sopenharmony_cilitest_install_source_quirks(struct list *created_files_list, 1479a46c0ec8Sopenharmony_ci const char *dirname) 1480a46c0ec8Sopenharmony_ci{ 1481a46c0ec8Sopenharmony_ci struct dirent **namelist; 1482a46c0ec8Sopenharmony_ci int ndev; 1483a46c0ec8Sopenharmony_ci 1484a46c0ec8Sopenharmony_ci ndev = scandir(LIBINPUT_QUIRKS_SRCDIR, 1485a46c0ec8Sopenharmony_ci &namelist, 1486a46c0ec8Sopenharmony_ci is_quirks_file, 1487a46c0ec8Sopenharmony_ci versionsort); 1488a46c0ec8Sopenharmony_ci litest_assert_int_ge(ndev, 0); 1489a46c0ec8Sopenharmony_ci 1490a46c0ec8Sopenharmony_ci for (int idx = 0; idx < ndev; idx++) { 1491a46c0ec8Sopenharmony_ci struct created_file *file; 1492a46c0ec8Sopenharmony_ci char *filename; 1493a46c0ec8Sopenharmony_ci char dest[PATH_MAX]; 1494a46c0ec8Sopenharmony_ci char src[PATH_MAX]; 1495a46c0ec8Sopenharmony_ci 1496a46c0ec8Sopenharmony_ci filename = namelist[idx]->d_name; 1497a46c0ec8Sopenharmony_ci snprintf(src, sizeof(src), "%s/%s", 1498a46c0ec8Sopenharmony_ci LIBINPUT_QUIRKS_SRCDIR, filename); 1499a46c0ec8Sopenharmony_ci snprintf(dest, sizeof(dest), "%s/%s", dirname, filename); 1500a46c0ec8Sopenharmony_ci file = litest_copy_file(dest, src, NULL, true); 1501a46c0ec8Sopenharmony_ci list_append(created_files_list, &file->link); 1502a46c0ec8Sopenharmony_ci free(namelist[idx]); 1503a46c0ec8Sopenharmony_ci } 1504a46c0ec8Sopenharmony_ci free(namelist); 1505a46c0ec8Sopenharmony_ci} 1506a46c0ec8Sopenharmony_ci 1507a46c0ec8Sopenharmony_ci/** 1508a46c0ec8Sopenharmony_ci * Install the quirks from the various litest test devices 1509a46c0ec8Sopenharmony_ci */ 1510a46c0ec8Sopenharmony_cistatic void 1511a46c0ec8Sopenharmony_cilitest_install_device_quirks(struct list *created_files_list, 1512a46c0ec8Sopenharmony_ci const char *dirname) 1513a46c0ec8Sopenharmony_ci{ 1514a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 1515a46c0ec8Sopenharmony_ci 1516a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) { 1517a46c0ec8Sopenharmony_ci char *path; 1518a46c0ec8Sopenharmony_ci 1519a46c0ec8Sopenharmony_ci path = litest_init_device_quirk_file(dirname, dev); 1520a46c0ec8Sopenharmony_ci if (path) { 1521a46c0ec8Sopenharmony_ci struct created_file *file = zalloc(sizeof(*file)); 1522a46c0ec8Sopenharmony_ci file->path = path; 1523a46c0ec8Sopenharmony_ci list_insert(created_files_list, &file->link); 1524a46c0ec8Sopenharmony_ci } 1525a46c0ec8Sopenharmony_ci } 1526a46c0ec8Sopenharmony_ci} 1527a46c0ec8Sopenharmony_ci 1528a46c0ec8Sopenharmony_cistatic void 1529a46c0ec8Sopenharmony_cilitest_setup_quirks(struct list *created_files_list, 1530a46c0ec8Sopenharmony_ci enum quirks_setup_mode mode) 1531a46c0ec8Sopenharmony_ci{ 1532a46c0ec8Sopenharmony_ci struct created_file *file = NULL; 1533a46c0ec8Sopenharmony_ci const char *dirname; 1534a46c0ec8Sopenharmony_ci char tmpdir[] = "/run/litest-XXXXXX"; 1535a46c0ec8Sopenharmony_ci 1536a46c0ec8Sopenharmony_ci switch (mode) { 1537a46c0ec8Sopenharmony_ci case QUIRKS_SETUP_USE_SRCDIR: 1538a46c0ec8Sopenharmony_ci dirname = LIBINPUT_QUIRKS_SRCDIR; 1539a46c0ec8Sopenharmony_ci break; 1540a46c0ec8Sopenharmony_ci case QUIRKS_SETUP_ONLY_DEVICE: 1541a46c0ec8Sopenharmony_ci dirname = LIBINPUT_QUIRKS_DIR; 1542a46c0ec8Sopenharmony_ci litest_install_device_quirks(created_files_list, dirname); 1543a46c0ec8Sopenharmony_ci break; 1544a46c0ec8Sopenharmony_ci case QUIRKS_SETUP_FULL: 1545a46c0ec8Sopenharmony_ci litest_assert_notnull(mkdtemp(tmpdir)); 1546a46c0ec8Sopenharmony_ci litest_assert_int_ne(chmod(tmpdir, 0755), -1); 1547a46c0ec8Sopenharmony_ci file = zalloc(sizeof *file); 1548a46c0ec8Sopenharmony_ci file->path = safe_strdup(tmpdir); 1549a46c0ec8Sopenharmony_ci dirname = tmpdir; 1550a46c0ec8Sopenharmony_ci 1551a46c0ec8Sopenharmony_ci litest_install_source_quirks(created_files_list, dirname); 1552a46c0ec8Sopenharmony_ci litest_install_device_quirks(created_files_list, dirname); 1553a46c0ec8Sopenharmony_ci list_append(created_files_list, &file->link); 1554a46c0ec8Sopenharmony_ci break; 1555a46c0ec8Sopenharmony_ci } 1556a46c0ec8Sopenharmony_ci 1557a46c0ec8Sopenharmony_ci setenv("LIBINPUT_QUIRKS_DIR", dirname, 1); 1558a46c0ec8Sopenharmony_ci} 1559a46c0ec8Sopenharmony_ci 1560a46c0ec8Sopenharmony_cistatic inline void 1561a46c0ec8Sopenharmony_cimkdir_p(const char *dir) 1562a46c0ec8Sopenharmony_ci{ 1563a46c0ec8Sopenharmony_ci char *path, *parent; 1564a46c0ec8Sopenharmony_ci int rc; 1565a46c0ec8Sopenharmony_ci 1566a46c0ec8Sopenharmony_ci if (streq(dir, "/")) 1567a46c0ec8Sopenharmony_ci return; 1568a46c0ec8Sopenharmony_ci 1569a46c0ec8Sopenharmony_ci path = safe_strdup(dir); 1570a46c0ec8Sopenharmony_ci parent = dirname(path); 1571a46c0ec8Sopenharmony_ci 1572a46c0ec8Sopenharmony_ci mkdir_p(parent); 1573a46c0ec8Sopenharmony_ci rc = mkdir(dir, 0755); 1574a46c0ec8Sopenharmony_ci 1575a46c0ec8Sopenharmony_ci if (rc == -1 && errno != EEXIST) { 1576a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to create directory %s (%s)\n", 1577a46c0ec8Sopenharmony_ci dir, 1578a46c0ec8Sopenharmony_ci strerror(errno)); 1579a46c0ec8Sopenharmony_ci } 1580a46c0ec8Sopenharmony_ci 1581a46c0ec8Sopenharmony_ci free(path); 1582a46c0ec8Sopenharmony_ci} 1583a46c0ec8Sopenharmony_ci 1584a46c0ec8Sopenharmony_cistatic inline void 1585a46c0ec8Sopenharmony_cilitest_init_udev_rules(struct list *created_files) 1586a46c0ec8Sopenharmony_ci{ 1587a46c0ec8Sopenharmony_ci mkdir_p(UDEV_RULES_D); 1588a46c0ec8Sopenharmony_ci 1589a46c0ec8Sopenharmony_ci litest_install_model_quirks(created_files); 1590a46c0ec8Sopenharmony_ci litest_init_all_device_udev_rules(created_files); 1591a46c0ec8Sopenharmony_ci litest_reload_udev_rules(); 1592a46c0ec8Sopenharmony_ci} 1593a46c0ec8Sopenharmony_ci 1594a46c0ec8Sopenharmony_cistatic inline void 1595a46c0ec8Sopenharmony_cilitest_remove_udev_rules(struct list *created_files_list) 1596a46c0ec8Sopenharmony_ci{ 1597a46c0ec8Sopenharmony_ci struct created_file *f; 1598a46c0ec8Sopenharmony_ci bool reload_udev; 1599a46c0ec8Sopenharmony_ci 1600a46c0ec8Sopenharmony_ci reload_udev = !list_empty(created_files_list); 1601a46c0ec8Sopenharmony_ci 1602a46c0ec8Sopenharmony_ci list_for_each_safe(f, created_files_list, link) { 1603a46c0ec8Sopenharmony_ci list_remove(&f->link); 1604a46c0ec8Sopenharmony_ci unlink(f->path); 1605a46c0ec8Sopenharmony_ci rmdir(f->path); 1606a46c0ec8Sopenharmony_ci free(f->path); 1607a46c0ec8Sopenharmony_ci free(f); 1608a46c0ec8Sopenharmony_ci } 1609a46c0ec8Sopenharmony_ci 1610a46c0ec8Sopenharmony_ci if (reload_udev) 1611a46c0ec8Sopenharmony_ci litest_reload_udev_rules(); 1612a46c0ec8Sopenharmony_ci} 1613a46c0ec8Sopenharmony_ci 1614a46c0ec8Sopenharmony_ci/** 1615a46c0ec8Sopenharmony_ci * Creates a uinput device but does not add it to a libinput context 1616a46c0ec8Sopenharmony_ci */ 1617a46c0ec8Sopenharmony_cistruct litest_device * 1618a46c0ec8Sopenharmony_cilitest_create(enum litest_device_type which, 1619a46c0ec8Sopenharmony_ci const char *name_override, 1620a46c0ec8Sopenharmony_ci struct input_id *id_override, 1621a46c0ec8Sopenharmony_ci const struct input_absinfo *abs_override, 1622a46c0ec8Sopenharmony_ci const int *events_override) 1623a46c0ec8Sopenharmony_ci{ 1624a46c0ec8Sopenharmony_ci struct litest_device *d = NULL; 1625a46c0ec8Sopenharmony_ci struct litest_test_device *dev; 1626a46c0ec8Sopenharmony_ci const char *name; 1627a46c0ec8Sopenharmony_ci const struct input_id *id; 1628a46c0ec8Sopenharmony_ci struct input_absinfo *abs; 1629a46c0ec8Sopenharmony_ci int *events, *e; 1630a46c0ec8Sopenharmony_ci const char *path; 1631a46c0ec8Sopenharmony_ci int fd, rc; 1632a46c0ec8Sopenharmony_ci bool found = false; 1633a46c0ec8Sopenharmony_ci bool create_device = true; 1634a46c0ec8Sopenharmony_ci 1635a46c0ec8Sopenharmony_ci list_for_each(dev, &devices, node) { 1636a46c0ec8Sopenharmony_ci if (dev->type == which) { 1637a46c0ec8Sopenharmony_ci found = true; 1638a46c0ec8Sopenharmony_ci break; 1639a46c0ec8Sopenharmony_ci } 1640a46c0ec8Sopenharmony_ci } 1641a46c0ec8Sopenharmony_ci 1642a46c0ec8Sopenharmony_ci if (!found) 1643a46c0ec8Sopenharmony_ci ck_abort_msg("Invalid device type %d\n", which); 1644a46c0ec8Sopenharmony_ci 1645a46c0ec8Sopenharmony_ci d = zalloc(sizeof(*d)); 1646a46c0ec8Sopenharmony_ci d->which = which; 1647a46c0ec8Sopenharmony_ci 1648a46c0ec8Sopenharmony_ci /* device has custom create method */ 1649a46c0ec8Sopenharmony_ci if (dev->create) { 1650a46c0ec8Sopenharmony_ci create_device = dev->create(d); 1651a46c0ec8Sopenharmony_ci if (abs_override || events_override) { 1652a46c0ec8Sopenharmony_ci litest_abort_msg("Custom create cannot be overridden"); 1653a46c0ec8Sopenharmony_ci } 1654a46c0ec8Sopenharmony_ci } 1655a46c0ec8Sopenharmony_ci 1656a46c0ec8Sopenharmony_ci abs = merge_absinfo(dev->absinfo, abs_override); 1657a46c0ec8Sopenharmony_ci events = merge_events(dev->events, events_override); 1658a46c0ec8Sopenharmony_ci name = name_override ? name_override : dev->name; 1659a46c0ec8Sopenharmony_ci id = id_override ? id_override : dev->id; 1660a46c0ec8Sopenharmony_ci 1661a46c0ec8Sopenharmony_ci if (create_device) { 1662a46c0ec8Sopenharmony_ci d->uinput = litest_create_uinput_device_from_description(name, 1663a46c0ec8Sopenharmony_ci id, 1664a46c0ec8Sopenharmony_ci abs, 1665a46c0ec8Sopenharmony_ci events); 1666a46c0ec8Sopenharmony_ci d->interface = dev->interface; 1667a46c0ec8Sopenharmony_ci 1668a46c0ec8Sopenharmony_ci for (e = events; *e != -1; e += 2) { 1669a46c0ec8Sopenharmony_ci unsigned int type = *e, 1670a46c0ec8Sopenharmony_ci code = *(e + 1); 1671a46c0ec8Sopenharmony_ci 1672a46c0ec8Sopenharmony_ci if (type == INPUT_PROP_MAX && 1673a46c0ec8Sopenharmony_ci code == INPUT_PROP_SEMI_MT) { 1674a46c0ec8Sopenharmony_ci d->semi_mt.is_semi_mt = true; 1675a46c0ec8Sopenharmony_ci break; 1676a46c0ec8Sopenharmony_ci } 1677a46c0ec8Sopenharmony_ci } 1678a46c0ec8Sopenharmony_ci } 1679a46c0ec8Sopenharmony_ci 1680a46c0ec8Sopenharmony_ci free(abs); 1681a46c0ec8Sopenharmony_ci free(events); 1682a46c0ec8Sopenharmony_ci 1683a46c0ec8Sopenharmony_ci path = libevdev_uinput_get_devnode(d->uinput); 1684a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(path); 1685a46c0ec8Sopenharmony_ci fd = open(path, O_RDWR|O_NONBLOCK); 1686a46c0ec8Sopenharmony_ci litest_assert_int_ne(fd, -1); 1687a46c0ec8Sopenharmony_ci 1688a46c0ec8Sopenharmony_ci rc = libevdev_new_from_fd(fd, &d->evdev); 1689a46c0ec8Sopenharmony_ci litest_assert_int_eq(rc, 0); 1690a46c0ec8Sopenharmony_ci 1691a46c0ec8Sopenharmony_ci return d; 1692a46c0ec8Sopenharmony_ci 1693a46c0ec8Sopenharmony_ci} 1694a46c0ec8Sopenharmony_ci 1695a46c0ec8Sopenharmony_cistruct libinput * 1696a46c0ec8Sopenharmony_cilitest_create_context(void) 1697a46c0ec8Sopenharmony_ci{ 1698a46c0ec8Sopenharmony_ci struct libinput *libinput; 1699a46c0ec8Sopenharmony_ci struct litest_context *ctx; 1700a46c0ec8Sopenharmony_ci 1701a46c0ec8Sopenharmony_ci ctx = zalloc(sizeof *ctx); 1702a46c0ec8Sopenharmony_ci list_init(&ctx->paths); 1703a46c0ec8Sopenharmony_ci 1704a46c0ec8Sopenharmony_ci libinput = libinput_path_create_context(&interface, ctx); 1705a46c0ec8Sopenharmony_ci litest_assert_notnull(libinput); 1706a46c0ec8Sopenharmony_ci 1707a46c0ec8Sopenharmony_ci libinput_log_set_handler(libinput, litest_log_handler); 1708a46c0ec8Sopenharmony_ci if (verbose) 1709a46c0ec8Sopenharmony_ci libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG); 1710a46c0ec8Sopenharmony_ci 1711a46c0ec8Sopenharmony_ci return libinput; 1712a46c0ec8Sopenharmony_ci} 1713a46c0ec8Sopenharmony_ci 1714a46c0ec8Sopenharmony_civoid 1715a46c0ec8Sopenharmony_cilitest_destroy_context(struct libinput *li) 1716a46c0ec8Sopenharmony_ci{ 1717a46c0ec8Sopenharmony_ci struct path *p; 1718a46c0ec8Sopenharmony_ci struct litest_context *ctx; 1719a46c0ec8Sopenharmony_ci 1720a46c0ec8Sopenharmony_ci 1721a46c0ec8Sopenharmony_ci ctx = libinput_get_user_data(li); 1722a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(ctx); 1723a46c0ec8Sopenharmony_ci libinput_unref(li); 1724a46c0ec8Sopenharmony_ci 1725a46c0ec8Sopenharmony_ci list_for_each_safe(p, &ctx->paths, link) { 1726a46c0ec8Sopenharmony_ci litest_abort_msg("Device paths should be removed by now"); 1727a46c0ec8Sopenharmony_ci } 1728a46c0ec8Sopenharmony_ci free(ctx); 1729a46c0ec8Sopenharmony_ci} 1730a46c0ec8Sopenharmony_ci 1731a46c0ec8Sopenharmony_civoid 1732a46c0ec8Sopenharmony_cilitest_disable_log_handler(struct libinput *libinput) 1733a46c0ec8Sopenharmony_ci{ 1734a46c0ec8Sopenharmony_ci libinput_log_set_handler(libinput, NULL); 1735a46c0ec8Sopenharmony_ci} 1736a46c0ec8Sopenharmony_ci 1737a46c0ec8Sopenharmony_civoid 1738a46c0ec8Sopenharmony_cilitest_restore_log_handler(struct libinput *libinput) 1739a46c0ec8Sopenharmony_ci{ 1740a46c0ec8Sopenharmony_ci libinput_log_set_handler(libinput, litest_log_handler); 1741a46c0ec8Sopenharmony_ci if (verbose) 1742a46c0ec8Sopenharmony_ci libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG); 1743a46c0ec8Sopenharmony_ci} 1744a46c0ec8Sopenharmony_ci 1745a46c0ec8Sopenharmony_ciLIBINPUT_ATTRIBUTE_PRINTF(3, 0) 1746a46c0ec8Sopenharmony_cistatic void 1747a46c0ec8Sopenharmony_cilitest_bug_log_handler(struct libinput *libinput, 1748a46c0ec8Sopenharmony_ci enum libinput_log_priority pri, 1749a46c0ec8Sopenharmony_ci const char *format, 1750a46c0ec8Sopenharmony_ci va_list args) 1751a46c0ec8Sopenharmony_ci{ 1752a46c0ec8Sopenharmony_ci if (strstr(format, "client bug: ") || 1753a46c0ec8Sopenharmony_ci strstr(format, "libinput bug: ") || 1754a46c0ec8Sopenharmony_ci strstr(format, "kernel bug: ")) 1755a46c0ec8Sopenharmony_ci return; 1756a46c0ec8Sopenharmony_ci 1757a46c0ec8Sopenharmony_ci litest_abort_msg("Expected bug statement in log msg, aborting.\n"); 1758a46c0ec8Sopenharmony_ci} 1759a46c0ec8Sopenharmony_ci 1760a46c0ec8Sopenharmony_civoid 1761a46c0ec8Sopenharmony_cilitest_set_log_handler_bug(struct libinput *libinput) 1762a46c0ec8Sopenharmony_ci{ 1763a46c0ec8Sopenharmony_ci libinput_log_set_handler(libinput, litest_bug_log_handler); 1764a46c0ec8Sopenharmony_ci} 1765a46c0ec8Sopenharmony_ci 1766a46c0ec8Sopenharmony_cistruct litest_device * 1767a46c0ec8Sopenharmony_cilitest_add_device_with_overrides(struct libinput *libinput, 1768a46c0ec8Sopenharmony_ci enum litest_device_type which, 1769a46c0ec8Sopenharmony_ci const char *name_override, 1770a46c0ec8Sopenharmony_ci struct input_id *id_override, 1771a46c0ec8Sopenharmony_ci const struct input_absinfo *abs_override, 1772a46c0ec8Sopenharmony_ci const int *events_override) 1773a46c0ec8Sopenharmony_ci{ 1774a46c0ec8Sopenharmony_ci struct udev_device *ud; 1775a46c0ec8Sopenharmony_ci struct litest_device *d; 1776a46c0ec8Sopenharmony_ci const char *path; 1777a46c0ec8Sopenharmony_ci 1778a46c0ec8Sopenharmony_ci d = litest_create(which, 1779a46c0ec8Sopenharmony_ci name_override, 1780a46c0ec8Sopenharmony_ci id_override, 1781a46c0ec8Sopenharmony_ci abs_override, 1782a46c0ec8Sopenharmony_ci events_override); 1783a46c0ec8Sopenharmony_ci 1784a46c0ec8Sopenharmony_ci path = libevdev_uinput_get_devnode(d->uinput); 1785a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(path); 1786a46c0ec8Sopenharmony_ci 1787a46c0ec8Sopenharmony_ci d->libinput = libinput; 1788a46c0ec8Sopenharmony_ci d->libinput_device = libinput_path_add_device(d->libinput, path); 1789a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(d->libinput_device); 1790a46c0ec8Sopenharmony_ci ud = libinput_device_get_udev_device(d->libinput_device); 1791a46c0ec8Sopenharmony_ci d->quirks = quirks_fetch_for_device(quirks_context, ud); 1792a46c0ec8Sopenharmony_ci udev_device_unref(ud); 1793a46c0ec8Sopenharmony_ci 1794a46c0ec8Sopenharmony_ci libinput_device_ref(d->libinput_device); 1795a46c0ec8Sopenharmony_ci 1796a46c0ec8Sopenharmony_ci if (d->interface) { 1797a46c0ec8Sopenharmony_ci unsigned int code; 1798a46c0ec8Sopenharmony_ci 1799a46c0ec8Sopenharmony_ci code = ABS_X; 1800a46c0ec8Sopenharmony_ci if (!libevdev_has_event_code(d->evdev, EV_ABS, code)) 1801a46c0ec8Sopenharmony_ci code = ABS_MT_POSITION_X; 1802a46c0ec8Sopenharmony_ci if (libevdev_has_event_code(d->evdev, EV_ABS, code)) { 1803a46c0ec8Sopenharmony_ci d->interface->min[ABS_X] = libevdev_get_abs_minimum(d->evdev, code); 1804a46c0ec8Sopenharmony_ci d->interface->max[ABS_X] = libevdev_get_abs_maximum(d->evdev, code); 1805a46c0ec8Sopenharmony_ci } 1806a46c0ec8Sopenharmony_ci 1807a46c0ec8Sopenharmony_ci code = ABS_Y; 1808a46c0ec8Sopenharmony_ci if (!libevdev_has_event_code(d->evdev, EV_ABS, code)) 1809a46c0ec8Sopenharmony_ci code = ABS_MT_POSITION_Y; 1810a46c0ec8Sopenharmony_ci if (libevdev_has_event_code(d->evdev, EV_ABS, code)) { 1811a46c0ec8Sopenharmony_ci d->interface->min[ABS_Y] = libevdev_get_abs_minimum(d->evdev, code); 1812a46c0ec8Sopenharmony_ci d->interface->max[ABS_Y] = libevdev_get_abs_maximum(d->evdev, code); 1813a46c0ec8Sopenharmony_ci } 1814a46c0ec8Sopenharmony_ci d->interface->tool_type = BTN_TOOL_PEN; 1815a46c0ec8Sopenharmony_ci } 1816a46c0ec8Sopenharmony_ci return d; 1817a46c0ec8Sopenharmony_ci} 1818a46c0ec8Sopenharmony_ci 1819a46c0ec8Sopenharmony_cistruct litest_device * 1820a46c0ec8Sopenharmony_cilitest_add_device(struct libinput *libinput, 1821a46c0ec8Sopenharmony_ci enum litest_device_type which) 1822a46c0ec8Sopenharmony_ci{ 1823a46c0ec8Sopenharmony_ci return litest_add_device_with_overrides(libinput, 1824a46c0ec8Sopenharmony_ci which, 1825a46c0ec8Sopenharmony_ci NULL, 1826a46c0ec8Sopenharmony_ci NULL, 1827a46c0ec8Sopenharmony_ci NULL, 1828a46c0ec8Sopenharmony_ci NULL); 1829a46c0ec8Sopenharmony_ci} 1830a46c0ec8Sopenharmony_ci 1831a46c0ec8Sopenharmony_cistruct litest_device * 1832a46c0ec8Sopenharmony_cilitest_create_device_with_overrides(enum litest_device_type which, 1833a46c0ec8Sopenharmony_ci const char *name_override, 1834a46c0ec8Sopenharmony_ci struct input_id *id_override, 1835a46c0ec8Sopenharmony_ci const struct input_absinfo *abs_override, 1836a46c0ec8Sopenharmony_ci const int *events_override) 1837a46c0ec8Sopenharmony_ci{ 1838a46c0ec8Sopenharmony_ci struct litest_device *dev = 1839a46c0ec8Sopenharmony_ci litest_add_device_with_overrides(litest_create_context(), 1840a46c0ec8Sopenharmony_ci which, 1841a46c0ec8Sopenharmony_ci name_override, 1842a46c0ec8Sopenharmony_ci id_override, 1843a46c0ec8Sopenharmony_ci abs_override, 1844a46c0ec8Sopenharmony_ci events_override); 1845a46c0ec8Sopenharmony_ci dev->owns_context = true; 1846a46c0ec8Sopenharmony_ci return dev; 1847a46c0ec8Sopenharmony_ci} 1848a46c0ec8Sopenharmony_ci 1849a46c0ec8Sopenharmony_cistruct litest_device * 1850a46c0ec8Sopenharmony_cilitest_create_device(enum litest_device_type which) 1851a46c0ec8Sopenharmony_ci{ 1852a46c0ec8Sopenharmony_ci return litest_create_device_with_overrides(which, NULL, NULL, NULL, NULL); 1853a46c0ec8Sopenharmony_ci} 1854a46c0ec8Sopenharmony_ci 1855a46c0ec8Sopenharmony_cistatic struct udev_monitor * 1856a46c0ec8Sopenharmony_ciudev_setup_monitor(void) 1857a46c0ec8Sopenharmony_ci{ 1858a46c0ec8Sopenharmony_ci struct udev *udev; 1859a46c0ec8Sopenharmony_ci struct udev_monitor *udev_monitor; 1860a46c0ec8Sopenharmony_ci int rc; 1861a46c0ec8Sopenharmony_ci 1862a46c0ec8Sopenharmony_ci udev = udev_new(); 1863a46c0ec8Sopenharmony_ci litest_assert_notnull(udev); 1864a46c0ec8Sopenharmony_ci udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); 1865a46c0ec8Sopenharmony_ci litest_assert_notnull(udev_monitor); 1866a46c0ec8Sopenharmony_ci udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", 1867a46c0ec8Sopenharmony_ci NULL); 1868a46c0ec8Sopenharmony_ci 1869a46c0ec8Sopenharmony_ci 1870a46c0ec8Sopenharmony_ci /* remove O_NONBLOCK */ 1871a46c0ec8Sopenharmony_ci rc = fcntl(udev_monitor_get_fd(udev_monitor), F_SETFL, 0); 1872a46c0ec8Sopenharmony_ci litest_assert_int_ne(rc, -1); 1873a46c0ec8Sopenharmony_ci litest_assert_int_eq(udev_monitor_enable_receiving(udev_monitor), 1874a46c0ec8Sopenharmony_ci 0); 1875a46c0ec8Sopenharmony_ci udev_unref(udev); 1876a46c0ec8Sopenharmony_ci 1877a46c0ec8Sopenharmony_ci return udev_monitor; 1878a46c0ec8Sopenharmony_ci} 1879a46c0ec8Sopenharmony_ci 1880a46c0ec8Sopenharmony_cistatic struct udev_device * 1881a46c0ec8Sopenharmony_ciudev_wait_for_device_event(struct udev_monitor *udev_monitor, 1882a46c0ec8Sopenharmony_ci const char *udev_event, 1883a46c0ec8Sopenharmony_ci const char *syspath) 1884a46c0ec8Sopenharmony_ci{ 1885a46c0ec8Sopenharmony_ci struct udev_device *udev_device = NULL; 1886a46c0ec8Sopenharmony_ci 1887a46c0ec8Sopenharmony_ci /* blocking, we don't want to continue until udev is ready */ 1888a46c0ec8Sopenharmony_ci while (1) { 1889a46c0ec8Sopenharmony_ci const char *udev_syspath = NULL; 1890a46c0ec8Sopenharmony_ci const char *udev_action; 1891a46c0ec8Sopenharmony_ci 1892a46c0ec8Sopenharmony_ci udev_device = udev_monitor_receive_device(udev_monitor); 1893a46c0ec8Sopenharmony_ci litest_assert_notnull(udev_device); 1894a46c0ec8Sopenharmony_ci udev_action = udev_device_get_action(udev_device); 1895a46c0ec8Sopenharmony_ci if (!udev_action || !streq(udev_action, udev_event)) { 1896a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 1897a46c0ec8Sopenharmony_ci continue; 1898a46c0ec8Sopenharmony_ci } 1899a46c0ec8Sopenharmony_ci 1900a46c0ec8Sopenharmony_ci udev_syspath = udev_device_get_syspath(udev_device); 1901a46c0ec8Sopenharmony_ci if (udev_syspath && strstartswith(udev_syspath, syspath)) 1902a46c0ec8Sopenharmony_ci break; 1903a46c0ec8Sopenharmony_ci 1904a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 1905a46c0ec8Sopenharmony_ci } 1906a46c0ec8Sopenharmony_ci 1907a46c0ec8Sopenharmony_ci return udev_device; 1908a46c0ec8Sopenharmony_ci} 1909a46c0ec8Sopenharmony_ci 1910a46c0ec8Sopenharmony_civoid 1911a46c0ec8Sopenharmony_cilitest_delete_device(struct litest_device *d) 1912a46c0ec8Sopenharmony_ci{ 1913a46c0ec8Sopenharmony_ci 1914a46c0ec8Sopenharmony_ci struct udev_monitor *udev_monitor; 1915a46c0ec8Sopenharmony_ci struct udev_device *udev_device; 1916a46c0ec8Sopenharmony_ci char path[PATH_MAX]; 1917a46c0ec8Sopenharmony_ci 1918a46c0ec8Sopenharmony_ci if (!d) 1919a46c0ec8Sopenharmony_ci return; 1920a46c0ec8Sopenharmony_ci 1921a46c0ec8Sopenharmony_ci udev_monitor = udev_setup_monitor(); 1922a46c0ec8Sopenharmony_ci snprintf(path, sizeof(path), 1923a46c0ec8Sopenharmony_ci "%s/event", 1924a46c0ec8Sopenharmony_ci libevdev_uinput_get_syspath(d->uinput)); 1925a46c0ec8Sopenharmony_ci 1926a46c0ec8Sopenharmony_ci litest_assert_int_eq(d->skip_ev_syn, 0); 1927a46c0ec8Sopenharmony_ci 1928a46c0ec8Sopenharmony_ci quirks_unref(d->quirks); 1929a46c0ec8Sopenharmony_ci 1930a46c0ec8Sopenharmony_ci if (d->libinput_device) { 1931a46c0ec8Sopenharmony_ci libinput_path_remove_device(d->libinput_device); 1932a46c0ec8Sopenharmony_ci libinput_device_unref(d->libinput_device); 1933a46c0ec8Sopenharmony_ci } 1934a46c0ec8Sopenharmony_ci if (d->owns_context) { 1935a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 1936a46c0ec8Sopenharmony_ci litest_destroy_context(d->libinput); 1937a46c0ec8Sopenharmony_ci } 1938a46c0ec8Sopenharmony_ci close(libevdev_get_fd(d->evdev)); 1939a46c0ec8Sopenharmony_ci libevdev_free(d->evdev); 1940a46c0ec8Sopenharmony_ci libevdev_uinput_destroy(d->uinput); 1941a46c0ec8Sopenharmony_ci free(d->private); 1942a46c0ec8Sopenharmony_ci memset(d,0, sizeof(*d)); 1943a46c0ec8Sopenharmony_ci free(d); 1944a46c0ec8Sopenharmony_ci 1945a46c0ec8Sopenharmony_ci udev_device = udev_wait_for_device_event(udev_monitor, 1946a46c0ec8Sopenharmony_ci "remove", 1947a46c0ec8Sopenharmony_ci path); 1948a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 1949a46c0ec8Sopenharmony_ci udev_monitor_unref(udev_monitor); 1950a46c0ec8Sopenharmony_ci} 1951a46c0ec8Sopenharmony_ci 1952a46c0ec8Sopenharmony_civoid 1953a46c0ec8Sopenharmony_cilitest_event(struct litest_device *d, unsigned int type, 1954a46c0ec8Sopenharmony_ci unsigned int code, int value) 1955a46c0ec8Sopenharmony_ci{ 1956a46c0ec8Sopenharmony_ci int ret; 1957a46c0ec8Sopenharmony_ci 1958a46c0ec8Sopenharmony_ci if (!libevdev_has_event_code(d->evdev, type, code)) 1959a46c0ec8Sopenharmony_ci return; 1960a46c0ec8Sopenharmony_ci 1961a46c0ec8Sopenharmony_ci if (d->skip_ev_syn && type == EV_SYN && code == SYN_REPORT) 1962a46c0ec8Sopenharmony_ci return; 1963a46c0ec8Sopenharmony_ci 1964a46c0ec8Sopenharmony_ci ret = libevdev_uinput_write_event(d->uinput, type, code, value); 1965a46c0ec8Sopenharmony_ci litest_assert_int_eq(ret, 0); 1966a46c0ec8Sopenharmony_ci} 1967a46c0ec8Sopenharmony_ci 1968a46c0ec8Sopenharmony_cistatic bool 1969a46c0ec8Sopenharmony_ciaxis_replacement_value(struct litest_device *d, 1970a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 1971a46c0ec8Sopenharmony_ci int32_t evcode, 1972a46c0ec8Sopenharmony_ci int32_t *value) 1973a46c0ec8Sopenharmony_ci{ 1974a46c0ec8Sopenharmony_ci struct axis_replacement *axis = axes; 1975a46c0ec8Sopenharmony_ci 1976a46c0ec8Sopenharmony_ci if (!axes) 1977a46c0ec8Sopenharmony_ci return false; 1978a46c0ec8Sopenharmony_ci 1979a46c0ec8Sopenharmony_ci while (axis->evcode != -1) { 1980a46c0ec8Sopenharmony_ci if (axis->evcode == evcode) { 1981a46c0ec8Sopenharmony_ci switch (evcode) { 1982a46c0ec8Sopenharmony_ci case ABS_MT_SLOT: 1983a46c0ec8Sopenharmony_ci case ABS_MT_TRACKING_ID: 1984a46c0ec8Sopenharmony_ci case ABS_MT_TOOL_TYPE: 1985a46c0ec8Sopenharmony_ci *value = axis->value; 1986a46c0ec8Sopenharmony_ci break; 1987a46c0ec8Sopenharmony_ci default: 1988a46c0ec8Sopenharmony_ci *value = litest_scale(d, evcode, axis->value); 1989a46c0ec8Sopenharmony_ci break; 1990a46c0ec8Sopenharmony_ci } 1991a46c0ec8Sopenharmony_ci return true; 1992a46c0ec8Sopenharmony_ci } 1993a46c0ec8Sopenharmony_ci axis++; 1994a46c0ec8Sopenharmony_ci } 1995a46c0ec8Sopenharmony_ci 1996a46c0ec8Sopenharmony_ci return false; 1997a46c0ec8Sopenharmony_ci} 1998a46c0ec8Sopenharmony_ci 1999a46c0ec8Sopenharmony_ciint 2000a46c0ec8Sopenharmony_cilitest_auto_assign_value(struct litest_device *d, 2001a46c0ec8Sopenharmony_ci const struct input_event *ev, 2002a46c0ec8Sopenharmony_ci int slot, double x, double y, 2003a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2004a46c0ec8Sopenharmony_ci bool touching) 2005a46c0ec8Sopenharmony_ci{ 2006a46c0ec8Sopenharmony_ci static int tracking_id; 2007a46c0ec8Sopenharmony_ci int value = ev->value; 2008a46c0ec8Sopenharmony_ci 2009a46c0ec8Sopenharmony_ci if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS) 2010a46c0ec8Sopenharmony_ci return value; 2011a46c0ec8Sopenharmony_ci 2012a46c0ec8Sopenharmony_ci switch (ev->code) { 2013a46c0ec8Sopenharmony_ci case ABS_X: 2014a46c0ec8Sopenharmony_ci case ABS_MT_POSITION_X: 2015a46c0ec8Sopenharmony_ci value = litest_scale(d, ABS_X, x); 2016a46c0ec8Sopenharmony_ci break; 2017a46c0ec8Sopenharmony_ci case ABS_Y: 2018a46c0ec8Sopenharmony_ci case ABS_MT_POSITION_Y: 2019a46c0ec8Sopenharmony_ci value = litest_scale(d, ABS_Y, y); 2020a46c0ec8Sopenharmony_ci break; 2021a46c0ec8Sopenharmony_ci case ABS_MT_TRACKING_ID: 2022a46c0ec8Sopenharmony_ci value = ++tracking_id; 2023a46c0ec8Sopenharmony_ci break; 2024a46c0ec8Sopenharmony_ci case ABS_MT_SLOT: 2025a46c0ec8Sopenharmony_ci value = slot; 2026a46c0ec8Sopenharmony_ci break; 2027a46c0ec8Sopenharmony_ci case ABS_MT_DISTANCE: 2028a46c0ec8Sopenharmony_ci value = touching ? 0 : 1; 2029a46c0ec8Sopenharmony_ci break; 2030a46c0ec8Sopenharmony_ci case ABS_MT_TOOL_TYPE: 2031a46c0ec8Sopenharmony_ci if (!axis_replacement_value(d, axes, ev->code, &value)) 2032a46c0ec8Sopenharmony_ci value = MT_TOOL_FINGER; 2033a46c0ec8Sopenharmony_ci break; 2034a46c0ec8Sopenharmony_ci default: 2035a46c0ec8Sopenharmony_ci if (!axis_replacement_value(d, axes, ev->code, &value) && 2036a46c0ec8Sopenharmony_ci d->interface->get_axis_default) { 2037a46c0ec8Sopenharmony_ci int error = d->interface->get_axis_default(d, 2038a46c0ec8Sopenharmony_ci ev->code, 2039a46c0ec8Sopenharmony_ci &value); 2040a46c0ec8Sopenharmony_ci if (error) { 2041a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to get default axis value for %s (%d)\n", 2042a46c0ec8Sopenharmony_ci libevdev_event_code_get_name(EV_ABS, ev->code), 2043a46c0ec8Sopenharmony_ci ev->code); 2044a46c0ec8Sopenharmony_ci } 2045a46c0ec8Sopenharmony_ci } 2046a46c0ec8Sopenharmony_ci break; 2047a46c0ec8Sopenharmony_ci } 2048a46c0ec8Sopenharmony_ci 2049a46c0ec8Sopenharmony_ci return value; 2050a46c0ec8Sopenharmony_ci} 2051a46c0ec8Sopenharmony_ci 2052a46c0ec8Sopenharmony_cistatic void 2053a46c0ec8Sopenharmony_cisend_btntool(struct litest_device *d, bool hover) 2054a46c0ec8Sopenharmony_ci{ 2055a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOUCH, d->ntouches_down != 0 && !hover); 2056a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOOL_FINGER, d->ntouches_down == 1); 2057a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOOL_DOUBLETAP, d->ntouches_down == 2); 2058a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOOL_TRIPLETAP, d->ntouches_down == 3); 2059a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOOL_QUADTAP, d->ntouches_down == 4); 2060a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOOL_QUINTTAP, d->ntouches_down == 5); 2061a46c0ec8Sopenharmony_ci} 2062a46c0ec8Sopenharmony_ci 2063a46c0ec8Sopenharmony_cistatic void 2064a46c0ec8Sopenharmony_cislot_start(struct litest_device *d, 2065a46c0ec8Sopenharmony_ci unsigned int slot, 2066a46c0ec8Sopenharmony_ci double x, 2067a46c0ec8Sopenharmony_ci double y, 2068a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2069a46c0ec8Sopenharmony_ci bool touching, 2070a46c0ec8Sopenharmony_ci bool filter_abs_xy) 2071a46c0ec8Sopenharmony_ci{ 2072a46c0ec8Sopenharmony_ci struct input_event *ev; 2073a46c0ec8Sopenharmony_ci 2074a46c0ec8Sopenharmony_ci litest_assert_int_ge(d->ntouches_down, 0); 2075a46c0ec8Sopenharmony_ci d->ntouches_down++; 2076a46c0ec8Sopenharmony_ci 2077a46c0ec8Sopenharmony_ci send_btntool(d, !touching); 2078a46c0ec8Sopenharmony_ci 2079a46c0ec8Sopenharmony_ci /* If the test device overrides touch_down and says it didn't 2080a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2081a46c0ec8Sopenharmony_ci if (d->interface->touch_down && 2082a46c0ec8Sopenharmony_ci d->interface->touch_down(d, slot, x, y)) 2083a46c0ec8Sopenharmony_ci return; 2084a46c0ec8Sopenharmony_ci 2085a46c0ec8Sopenharmony_ci for (ev = d->interface->touch_down_events; 2086a46c0ec8Sopenharmony_ci ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1; 2087a46c0ec8Sopenharmony_ci ev++) { 2088a46c0ec8Sopenharmony_ci int value = litest_auto_assign_value(d, 2089a46c0ec8Sopenharmony_ci ev, 2090a46c0ec8Sopenharmony_ci slot, 2091a46c0ec8Sopenharmony_ci x, 2092a46c0ec8Sopenharmony_ci y, 2093a46c0ec8Sopenharmony_ci axes, 2094a46c0ec8Sopenharmony_ci touching); 2095a46c0ec8Sopenharmony_ci if (value == LITEST_AUTO_ASSIGN) 2096a46c0ec8Sopenharmony_ci continue; 2097a46c0ec8Sopenharmony_ci 2098a46c0ec8Sopenharmony_ci if (filter_abs_xy && ev->type == EV_ABS && 2099a46c0ec8Sopenharmony_ci (ev->code == ABS_X || ev->code == ABS_Y)) 2100a46c0ec8Sopenharmony_ci continue; 2101a46c0ec8Sopenharmony_ci 2102a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2103a46c0ec8Sopenharmony_ci } 2104a46c0ec8Sopenharmony_ci} 2105a46c0ec8Sopenharmony_ci 2106a46c0ec8Sopenharmony_cistatic void 2107a46c0ec8Sopenharmony_cislot_move(struct litest_device *d, 2108a46c0ec8Sopenharmony_ci unsigned int slot, 2109a46c0ec8Sopenharmony_ci double x, 2110a46c0ec8Sopenharmony_ci double y, 2111a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2112a46c0ec8Sopenharmony_ci bool touching, 2113a46c0ec8Sopenharmony_ci bool filter_abs_xy) 2114a46c0ec8Sopenharmony_ci{ 2115a46c0ec8Sopenharmony_ci struct input_event *ev; 2116a46c0ec8Sopenharmony_ci 2117a46c0ec8Sopenharmony_ci if (d->interface->touch_move && 2118a46c0ec8Sopenharmony_ci d->interface->touch_move(d, slot, x, y)) 2119a46c0ec8Sopenharmony_ci return; 2120a46c0ec8Sopenharmony_ci 2121a46c0ec8Sopenharmony_ci for (ev = d->interface->touch_move_events; 2122a46c0ec8Sopenharmony_ci ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1; 2123a46c0ec8Sopenharmony_ci ev++) { 2124a46c0ec8Sopenharmony_ci int value = litest_auto_assign_value(d, 2125a46c0ec8Sopenharmony_ci ev, 2126a46c0ec8Sopenharmony_ci slot, 2127a46c0ec8Sopenharmony_ci x, 2128a46c0ec8Sopenharmony_ci y, 2129a46c0ec8Sopenharmony_ci axes, 2130a46c0ec8Sopenharmony_ci touching); 2131a46c0ec8Sopenharmony_ci if (value == LITEST_AUTO_ASSIGN) 2132a46c0ec8Sopenharmony_ci continue; 2133a46c0ec8Sopenharmony_ci 2134a46c0ec8Sopenharmony_ci if (filter_abs_xy && ev->type == EV_ABS && 2135a46c0ec8Sopenharmony_ci (ev->code == ABS_X || ev->code == ABS_Y)) 2136a46c0ec8Sopenharmony_ci continue; 2137a46c0ec8Sopenharmony_ci 2138a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2139a46c0ec8Sopenharmony_ci } 2140a46c0ec8Sopenharmony_ci} 2141a46c0ec8Sopenharmony_ci 2142a46c0ec8Sopenharmony_cistatic void 2143a46c0ec8Sopenharmony_citouch_up(struct litest_device *d, unsigned int slot) 2144a46c0ec8Sopenharmony_ci{ 2145a46c0ec8Sopenharmony_ci struct input_event *ev; 2146a46c0ec8Sopenharmony_ci struct input_event up[] = { 2147a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, 2148a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 }, 2149a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = 0 }, 2150a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 0 }, 2151a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 0 }, 2152a46c0ec8Sopenharmony_ci { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, 2153a46c0ec8Sopenharmony_ci { .type = -1, .code = -1 } 2154a46c0ec8Sopenharmony_ci }; 2155a46c0ec8Sopenharmony_ci 2156a46c0ec8Sopenharmony_ci litest_assert_int_gt(d->ntouches_down, 0); 2157a46c0ec8Sopenharmony_ci d->ntouches_down--; 2158a46c0ec8Sopenharmony_ci 2159a46c0ec8Sopenharmony_ci send_btntool(d, false); 2160a46c0ec8Sopenharmony_ci 2161a46c0ec8Sopenharmony_ci if (d->interface->touch_up && 2162a46c0ec8Sopenharmony_ci d->interface->touch_up(d, slot)) { 2163a46c0ec8Sopenharmony_ci return; 2164a46c0ec8Sopenharmony_ci } else if (d->interface->touch_up_events) { 2165a46c0ec8Sopenharmony_ci ev = d->interface->touch_up_events; 2166a46c0ec8Sopenharmony_ci } else 2167a46c0ec8Sopenharmony_ci ev = up; 2168a46c0ec8Sopenharmony_ci 2169a46c0ec8Sopenharmony_ci for ( /* */; 2170a46c0ec8Sopenharmony_ci ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1; 2171a46c0ec8Sopenharmony_ci ev++) { 2172a46c0ec8Sopenharmony_ci int value = litest_auto_assign_value(d, 2173a46c0ec8Sopenharmony_ci ev, 2174a46c0ec8Sopenharmony_ci slot, 2175a46c0ec8Sopenharmony_ci 0, 2176a46c0ec8Sopenharmony_ci 0, 2177a46c0ec8Sopenharmony_ci NULL, 2178a46c0ec8Sopenharmony_ci false); 2179a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2180a46c0ec8Sopenharmony_ci } 2181a46c0ec8Sopenharmony_ci} 2182a46c0ec8Sopenharmony_ci 2183a46c0ec8Sopenharmony_cistatic void 2184a46c0ec8Sopenharmony_cilitest_slot_start(struct litest_device *d, 2185a46c0ec8Sopenharmony_ci unsigned int slot, 2186a46c0ec8Sopenharmony_ci double x, 2187a46c0ec8Sopenharmony_ci double y, 2188a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2189a46c0ec8Sopenharmony_ci bool touching) 2190a46c0ec8Sopenharmony_ci{ 2191a46c0ec8Sopenharmony_ci double t, l, r = 0, b = 0; /* top, left, right, bottom */ 2192a46c0ec8Sopenharmony_ci bool filter_abs_xy = false; 2193a46c0ec8Sopenharmony_ci 2194a46c0ec8Sopenharmony_ci if (!d->semi_mt.is_semi_mt) { 2195a46c0ec8Sopenharmony_ci slot_start(d, slot, x, y, axes, touching, filter_abs_xy); 2196a46c0ec8Sopenharmony_ci return; 2197a46c0ec8Sopenharmony_ci } 2198a46c0ec8Sopenharmony_ci 2199a46c0ec8Sopenharmony_ci if (d->ntouches_down >= 2 || slot > 1) 2200a46c0ec8Sopenharmony_ci return; 2201a46c0ec8Sopenharmony_ci 2202a46c0ec8Sopenharmony_ci slot = d->ntouches_down; 2203a46c0ec8Sopenharmony_ci 2204a46c0ec8Sopenharmony_ci if (d->ntouches_down == 0) { 2205a46c0ec8Sopenharmony_ci l = x; 2206a46c0ec8Sopenharmony_ci t = y; 2207a46c0ec8Sopenharmony_ci } else { 2208a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 2209a46c0ec8Sopenharmony_ci l = min(x, d->semi_mt.touches[other].x); 2210a46c0ec8Sopenharmony_ci t = min(y, d->semi_mt.touches[other].y); 2211a46c0ec8Sopenharmony_ci r = max(x, d->semi_mt.touches[other].x); 2212a46c0ec8Sopenharmony_ci b = max(y, d->semi_mt.touches[other].y); 2213a46c0ec8Sopenharmony_ci } 2214a46c0ec8Sopenharmony_ci 2215a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2216a46c0ec8Sopenharmony_ci if (d->ntouches_down == 0) 2217a46c0ec8Sopenharmony_ci slot_start(d, 0, l, t, axes, touching, filter_abs_xy); 2218a46c0ec8Sopenharmony_ci else 2219a46c0ec8Sopenharmony_ci slot_move(d, 0, l, t, axes, touching, filter_abs_xy); 2220a46c0ec8Sopenharmony_ci 2221a46c0ec8Sopenharmony_ci if (slot == 1) { 2222a46c0ec8Sopenharmony_ci filter_abs_xy = true; 2223a46c0ec8Sopenharmony_ci slot_start(d, 1, r, b, axes, touching, filter_abs_xy); 2224a46c0ec8Sopenharmony_ci } 2225a46c0ec8Sopenharmony_ci 2226a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2227a46c0ec8Sopenharmony_ci 2228a46c0ec8Sopenharmony_ci d->semi_mt.touches[slot].x = x; 2229a46c0ec8Sopenharmony_ci d->semi_mt.touches[slot].y = y; 2230a46c0ec8Sopenharmony_ci} 2231a46c0ec8Sopenharmony_ci 2232a46c0ec8Sopenharmony_civoid 2233a46c0ec8Sopenharmony_cilitest_touch_sequence(struct litest_device *d, 2234a46c0ec8Sopenharmony_ci unsigned int slot, 2235a46c0ec8Sopenharmony_ci double x_from, 2236a46c0ec8Sopenharmony_ci double y_from, 2237a46c0ec8Sopenharmony_ci double x_to, 2238a46c0ec8Sopenharmony_ci double y_to, 2239a46c0ec8Sopenharmony_ci int steps) 2240a46c0ec8Sopenharmony_ci{ 2241a46c0ec8Sopenharmony_ci litest_touch_down(d, slot, x_from, y_from); 2242a46c0ec8Sopenharmony_ci litest_touch_move_to(d, slot, 2243a46c0ec8Sopenharmony_ci x_from, y_from, 2244a46c0ec8Sopenharmony_ci x_to, y_to, 2245a46c0ec8Sopenharmony_ci steps); 2246a46c0ec8Sopenharmony_ci litest_touch_up(d, slot); 2247a46c0ec8Sopenharmony_ci} 2248a46c0ec8Sopenharmony_ci 2249a46c0ec8Sopenharmony_civoid 2250a46c0ec8Sopenharmony_cilitest_touch_down(struct litest_device *d, 2251a46c0ec8Sopenharmony_ci unsigned int slot, 2252a46c0ec8Sopenharmony_ci double x, 2253a46c0ec8Sopenharmony_ci double y) 2254a46c0ec8Sopenharmony_ci{ 2255a46c0ec8Sopenharmony_ci litest_slot_start(d, slot, x, y, NULL, true); 2256a46c0ec8Sopenharmony_ci} 2257a46c0ec8Sopenharmony_ci 2258a46c0ec8Sopenharmony_civoid 2259a46c0ec8Sopenharmony_cilitest_touch_down_extended(struct litest_device *d, 2260a46c0ec8Sopenharmony_ci unsigned int slot, 2261a46c0ec8Sopenharmony_ci double x, 2262a46c0ec8Sopenharmony_ci double y, 2263a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2264a46c0ec8Sopenharmony_ci{ 2265a46c0ec8Sopenharmony_ci litest_slot_start(d, slot, x, y, axes, true); 2266a46c0ec8Sopenharmony_ci} 2267a46c0ec8Sopenharmony_ci 2268a46c0ec8Sopenharmony_cistatic void 2269a46c0ec8Sopenharmony_cilitest_slot_move(struct litest_device *d, 2270a46c0ec8Sopenharmony_ci unsigned int slot, 2271a46c0ec8Sopenharmony_ci double x, 2272a46c0ec8Sopenharmony_ci double y, 2273a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2274a46c0ec8Sopenharmony_ci bool touching) 2275a46c0ec8Sopenharmony_ci{ 2276a46c0ec8Sopenharmony_ci double t, l, r = 0, b = 0; /* top, left, right, bottom */ 2277a46c0ec8Sopenharmony_ci bool filter_abs_xy = false; 2278a46c0ec8Sopenharmony_ci 2279a46c0ec8Sopenharmony_ci if (!d->semi_mt.is_semi_mt) { 2280a46c0ec8Sopenharmony_ci slot_move(d, slot, x, y, axes, touching, filter_abs_xy); 2281a46c0ec8Sopenharmony_ci return; 2282a46c0ec8Sopenharmony_ci } 2283a46c0ec8Sopenharmony_ci 2284a46c0ec8Sopenharmony_ci if (d->ntouches_down > 2 || slot > 1) 2285a46c0ec8Sopenharmony_ci return; 2286a46c0ec8Sopenharmony_ci 2287a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) { 2288a46c0ec8Sopenharmony_ci l = x; 2289a46c0ec8Sopenharmony_ci t = y; 2290a46c0ec8Sopenharmony_ci } else { 2291a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 2292a46c0ec8Sopenharmony_ci l = min(x, d->semi_mt.touches[other].x); 2293a46c0ec8Sopenharmony_ci t = min(y, d->semi_mt.touches[other].y); 2294a46c0ec8Sopenharmony_ci r = max(x, d->semi_mt.touches[other].x); 2295a46c0ec8Sopenharmony_ci b = max(y, d->semi_mt.touches[other].y); 2296a46c0ec8Sopenharmony_ci } 2297a46c0ec8Sopenharmony_ci 2298a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2299a46c0ec8Sopenharmony_ci slot_move(d, 0, l, t, axes, touching, filter_abs_xy); 2300a46c0ec8Sopenharmony_ci 2301a46c0ec8Sopenharmony_ci if (d->ntouches_down == 2) { 2302a46c0ec8Sopenharmony_ci filter_abs_xy = true; 2303a46c0ec8Sopenharmony_ci slot_move(d, 1, r, b, axes, touching, filter_abs_xy); 2304a46c0ec8Sopenharmony_ci } 2305a46c0ec8Sopenharmony_ci 2306a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2307a46c0ec8Sopenharmony_ci 2308a46c0ec8Sopenharmony_ci d->semi_mt.touches[slot].x = x; 2309a46c0ec8Sopenharmony_ci d->semi_mt.touches[slot].y = y; 2310a46c0ec8Sopenharmony_ci} 2311a46c0ec8Sopenharmony_ci 2312a46c0ec8Sopenharmony_civoid 2313a46c0ec8Sopenharmony_cilitest_touch_up(struct litest_device *d, unsigned int slot) 2314a46c0ec8Sopenharmony_ci{ 2315a46c0ec8Sopenharmony_ci if (!d->semi_mt.is_semi_mt) { 2316a46c0ec8Sopenharmony_ci touch_up(d, slot); 2317a46c0ec8Sopenharmony_ci return; 2318a46c0ec8Sopenharmony_ci } 2319a46c0ec8Sopenharmony_ci 2320a46c0ec8Sopenharmony_ci if (d->ntouches_down > 2 || slot > 1) 2321a46c0ec8Sopenharmony_ci return; 2322a46c0ec8Sopenharmony_ci 2323a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2324a46c0ec8Sopenharmony_ci touch_up(d, d->ntouches_down - 1); 2325a46c0ec8Sopenharmony_ci 2326a46c0ec8Sopenharmony_ci /* if we have one finger left, send x/y coords for that finger left. 2327a46c0ec8Sopenharmony_ci this is likely to happen with a real touchpad */ 2328a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) { 2329a46c0ec8Sopenharmony_ci bool touching = true; 2330a46c0ec8Sopenharmony_ci bool filter_abs_xy = false; 2331a46c0ec8Sopenharmony_ci 2332a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 2333a46c0ec8Sopenharmony_ci slot_move(d, 2334a46c0ec8Sopenharmony_ci 0, 2335a46c0ec8Sopenharmony_ci d->semi_mt.touches[other].x, 2336a46c0ec8Sopenharmony_ci d->semi_mt.touches[other].y, 2337a46c0ec8Sopenharmony_ci NULL, 2338a46c0ec8Sopenharmony_ci touching, 2339a46c0ec8Sopenharmony_ci filter_abs_xy); 2340a46c0ec8Sopenharmony_ci } 2341a46c0ec8Sopenharmony_ci 2342a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2343a46c0ec8Sopenharmony_ci} 2344a46c0ec8Sopenharmony_ci 2345a46c0ec8Sopenharmony_civoid 2346a46c0ec8Sopenharmony_cilitest_touch_move(struct litest_device *d, 2347a46c0ec8Sopenharmony_ci unsigned int slot, 2348a46c0ec8Sopenharmony_ci double x, 2349a46c0ec8Sopenharmony_ci double y) 2350a46c0ec8Sopenharmony_ci{ 2351a46c0ec8Sopenharmony_ci litest_slot_move(d, slot, x, y, NULL, true); 2352a46c0ec8Sopenharmony_ci} 2353a46c0ec8Sopenharmony_ci 2354a46c0ec8Sopenharmony_civoid 2355a46c0ec8Sopenharmony_cilitest_touch_move_extended(struct litest_device *d, 2356a46c0ec8Sopenharmony_ci unsigned int slot, 2357a46c0ec8Sopenharmony_ci double x, 2358a46c0ec8Sopenharmony_ci double y, 2359a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2360a46c0ec8Sopenharmony_ci{ 2361a46c0ec8Sopenharmony_ci litest_slot_move(d, slot, x, y, axes, true); 2362a46c0ec8Sopenharmony_ci} 2363a46c0ec8Sopenharmony_ci 2364a46c0ec8Sopenharmony_civoid 2365a46c0ec8Sopenharmony_cilitest_touch_move_to(struct litest_device *d, 2366a46c0ec8Sopenharmony_ci unsigned int slot, 2367a46c0ec8Sopenharmony_ci double x_from, double y_from, 2368a46c0ec8Sopenharmony_ci double x_to, double y_to, 2369a46c0ec8Sopenharmony_ci int steps) 2370a46c0ec8Sopenharmony_ci{ 2371a46c0ec8Sopenharmony_ci litest_touch_move_to_extended(d, slot, 2372a46c0ec8Sopenharmony_ci x_from, y_from, 2373a46c0ec8Sopenharmony_ci x_to, y_to, 2374a46c0ec8Sopenharmony_ci NULL, 2375a46c0ec8Sopenharmony_ci steps); 2376a46c0ec8Sopenharmony_ci} 2377a46c0ec8Sopenharmony_ci 2378a46c0ec8Sopenharmony_civoid 2379a46c0ec8Sopenharmony_cilitest_touch_move_to_extended(struct litest_device *d, 2380a46c0ec8Sopenharmony_ci unsigned int slot, 2381a46c0ec8Sopenharmony_ci double x_from, double y_from, 2382a46c0ec8Sopenharmony_ci double x_to, double y_to, 2383a46c0ec8Sopenharmony_ci struct axis_replacement *axes, 2384a46c0ec8Sopenharmony_ci int steps) 2385a46c0ec8Sopenharmony_ci{ 2386a46c0ec8Sopenharmony_ci int sleep_ms = 10; 2387a46c0ec8Sopenharmony_ci 2388a46c0ec8Sopenharmony_ci for (int i = 1; i < steps; i++) { 2389a46c0ec8Sopenharmony_ci litest_touch_move_extended(d, slot, 2390a46c0ec8Sopenharmony_ci x_from + (x_to - x_from)/steps * i, 2391a46c0ec8Sopenharmony_ci y_from + (y_to - y_from)/steps * i, 2392a46c0ec8Sopenharmony_ci axes); 2393a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2394a46c0ec8Sopenharmony_ci msleep(sleep_ms); 2395a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2396a46c0ec8Sopenharmony_ci } 2397a46c0ec8Sopenharmony_ci litest_touch_move_extended(d, slot, x_to, y_to, axes); 2398a46c0ec8Sopenharmony_ci} 2399a46c0ec8Sopenharmony_ci 2400a46c0ec8Sopenharmony_cistatic int 2401a46c0ec8Sopenharmony_ciauto_assign_tablet_value(struct litest_device *d, 2402a46c0ec8Sopenharmony_ci const struct input_event *ev, 2403a46c0ec8Sopenharmony_ci int x, int y, 2404a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2405a46c0ec8Sopenharmony_ci{ 2406a46c0ec8Sopenharmony_ci static int tracking_id; 2407a46c0ec8Sopenharmony_ci int value = ev->value; 2408a46c0ec8Sopenharmony_ci 2409a46c0ec8Sopenharmony_ci if (value != LITEST_AUTO_ASSIGN || ev->type != EV_ABS) 2410a46c0ec8Sopenharmony_ci return value; 2411a46c0ec8Sopenharmony_ci 2412a46c0ec8Sopenharmony_ci switch (ev->code) { 2413a46c0ec8Sopenharmony_ci case ABS_MT_TRACKING_ID: 2414a46c0ec8Sopenharmony_ci value = ++tracking_id; 2415a46c0ec8Sopenharmony_ci break; 2416a46c0ec8Sopenharmony_ci case ABS_X: 2417a46c0ec8Sopenharmony_ci case ABS_MT_POSITION_X: 2418a46c0ec8Sopenharmony_ci value = litest_scale(d, ABS_X, x); 2419a46c0ec8Sopenharmony_ci break; 2420a46c0ec8Sopenharmony_ci case ABS_Y: 2421a46c0ec8Sopenharmony_ci case ABS_MT_POSITION_Y: 2422a46c0ec8Sopenharmony_ci value = litest_scale(d, ABS_Y, y); 2423a46c0ec8Sopenharmony_ci break; 2424a46c0ec8Sopenharmony_ci default: 2425a46c0ec8Sopenharmony_ci if (!axis_replacement_value(d, axes, ev->code, &value) && 2426a46c0ec8Sopenharmony_ci d->interface->get_axis_default) { 2427a46c0ec8Sopenharmony_ci int error = d->interface->get_axis_default(d, ev->code, &value); 2428a46c0ec8Sopenharmony_ci if (error) { 2429a46c0ec8Sopenharmony_ci litest_abort_msg("Failed to get default axis value for %s (%d)\n", 2430a46c0ec8Sopenharmony_ci libevdev_event_code_get_name(EV_ABS, ev->code), 2431a46c0ec8Sopenharmony_ci ev->code); 2432a46c0ec8Sopenharmony_ci } 2433a46c0ec8Sopenharmony_ci } 2434a46c0ec8Sopenharmony_ci break; 2435a46c0ec8Sopenharmony_ci } 2436a46c0ec8Sopenharmony_ci 2437a46c0ec8Sopenharmony_ci return value; 2438a46c0ec8Sopenharmony_ci} 2439a46c0ec8Sopenharmony_ci 2440a46c0ec8Sopenharmony_cistatic int 2441a46c0ec8Sopenharmony_citablet_ignore_event(const struct input_event *ev, int value) 2442a46c0ec8Sopenharmony_ci{ 2443a46c0ec8Sopenharmony_ci return value == -1 && (ev->code == ABS_PRESSURE || ev->code == ABS_DISTANCE); 2444a46c0ec8Sopenharmony_ci} 2445a46c0ec8Sopenharmony_ci 2446a46c0ec8Sopenharmony_civoid 2447a46c0ec8Sopenharmony_cilitest_tablet_set_tool_type(struct litest_device *d, unsigned int code) 2448a46c0ec8Sopenharmony_ci{ 2449a46c0ec8Sopenharmony_ci switch (code) { 2450a46c0ec8Sopenharmony_ci case BTN_TOOL_PEN: 2451a46c0ec8Sopenharmony_ci case BTN_TOOL_RUBBER: 2452a46c0ec8Sopenharmony_ci case BTN_TOOL_BRUSH: 2453a46c0ec8Sopenharmony_ci case BTN_TOOL_PENCIL: 2454a46c0ec8Sopenharmony_ci case BTN_TOOL_AIRBRUSH: 2455a46c0ec8Sopenharmony_ci case BTN_TOOL_MOUSE: 2456a46c0ec8Sopenharmony_ci case BTN_TOOL_LENS: 2457a46c0ec8Sopenharmony_ci break; 2458a46c0ec8Sopenharmony_ci default: 2459a46c0ec8Sopenharmony_ci abort(); 2460a46c0ec8Sopenharmony_ci } 2461a46c0ec8Sopenharmony_ci 2462a46c0ec8Sopenharmony_ci d->interface->tool_type = code; 2463a46c0ec8Sopenharmony_ci} 2464a46c0ec8Sopenharmony_ci 2465a46c0ec8Sopenharmony_cistatic void 2466a46c0ec8Sopenharmony_cilitest_tool_event(struct litest_device *d, int value) 2467a46c0ec8Sopenharmony_ci{ 2468a46c0ec8Sopenharmony_ci unsigned int tool = d->interface->tool_type; 2469a46c0ec8Sopenharmony_ci 2470a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, tool, value); 2471a46c0ec8Sopenharmony_ci} 2472a46c0ec8Sopenharmony_ci 2473a46c0ec8Sopenharmony_civoid 2474a46c0ec8Sopenharmony_cilitest_tablet_proximity_in(struct litest_device *d, 2475a46c0ec8Sopenharmony_ci double x, double y, 2476a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2477a46c0ec8Sopenharmony_ci{ 2478a46c0ec8Sopenharmony_ci struct input_event *ev; 2479a46c0ec8Sopenharmony_ci 2480a46c0ec8Sopenharmony_ci /* If the test device overrides proximity_in and says it didn't 2481a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2482a46c0ec8Sopenharmony_ci if (d->interface->tablet_proximity_in && 2483a46c0ec8Sopenharmony_ci d->interface->tablet_proximity_in(d, d->interface->tool_type, &x, &y, axes)) 2484a46c0ec8Sopenharmony_ci return; 2485a46c0ec8Sopenharmony_ci 2486a46c0ec8Sopenharmony_ci ev = d->interface->tablet_proximity_in_events; 2487a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2488a46c0ec8Sopenharmony_ci int value; 2489a46c0ec8Sopenharmony_ci 2490a46c0ec8Sopenharmony_ci switch (evbit(ev->type, ev->code)) { 2491a46c0ec8Sopenharmony_ci case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO): 2492a46c0ec8Sopenharmony_ci litest_tool_event(d, ev->value); 2493a46c0ec8Sopenharmony_ci break; 2494a46c0ec8Sopenharmony_ci default: 2495a46c0ec8Sopenharmony_ci value = auto_assign_tablet_value(d, ev, x, y, axes); 2496a46c0ec8Sopenharmony_ci if (!tablet_ignore_event(ev, value)) 2497a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2498a46c0ec8Sopenharmony_ci } 2499a46c0ec8Sopenharmony_ci ev++; 2500a46c0ec8Sopenharmony_ci } 2501a46c0ec8Sopenharmony_ci} 2502a46c0ec8Sopenharmony_ci 2503a46c0ec8Sopenharmony_civoid 2504a46c0ec8Sopenharmony_cilitest_tablet_proximity_out(struct litest_device *d) 2505a46c0ec8Sopenharmony_ci{ 2506a46c0ec8Sopenharmony_ci struct input_event *ev; 2507a46c0ec8Sopenharmony_ci 2508a46c0ec8Sopenharmony_ci /* If the test device overrides proximity_out and says it didn't 2509a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2510a46c0ec8Sopenharmony_ci if (d->interface->tablet_proximity_out && 2511a46c0ec8Sopenharmony_ci d->interface->tablet_proximity_out(d, d->interface->tool_type)) 2512a46c0ec8Sopenharmony_ci return; 2513a46c0ec8Sopenharmony_ci 2514a46c0ec8Sopenharmony_ci ev = d->interface->tablet_proximity_out_events; 2515a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2516a46c0ec8Sopenharmony_ci int value; 2517a46c0ec8Sopenharmony_ci 2518a46c0ec8Sopenharmony_ci switch (evbit(ev->type, ev->code)) { 2519a46c0ec8Sopenharmony_ci case evbit(EV_KEY, LITEST_BTN_TOOL_AUTO): 2520a46c0ec8Sopenharmony_ci litest_tool_event(d, ev->value); 2521a46c0ec8Sopenharmony_ci break; 2522a46c0ec8Sopenharmony_ci default: 2523a46c0ec8Sopenharmony_ci value = auto_assign_tablet_value(d, ev, -1, -1, NULL); 2524a46c0ec8Sopenharmony_ci if (!tablet_ignore_event(ev, value)) 2525a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2526a46c0ec8Sopenharmony_ci break; 2527a46c0ec8Sopenharmony_ci } 2528a46c0ec8Sopenharmony_ci ev++; 2529a46c0ec8Sopenharmony_ci } 2530a46c0ec8Sopenharmony_ci} 2531a46c0ec8Sopenharmony_ci 2532a46c0ec8Sopenharmony_civoid 2533a46c0ec8Sopenharmony_cilitest_tablet_motion(struct litest_device *d, 2534a46c0ec8Sopenharmony_ci double x, double y, 2535a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2536a46c0ec8Sopenharmony_ci{ 2537a46c0ec8Sopenharmony_ci struct input_event *ev; 2538a46c0ec8Sopenharmony_ci 2539a46c0ec8Sopenharmony_ci /* If the test device overrides proximity_out and says it didn't 2540a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2541a46c0ec8Sopenharmony_ci if (d->interface->tablet_motion && 2542a46c0ec8Sopenharmony_ci d->interface->tablet_motion(d, &x, &y, axes)) 2543a46c0ec8Sopenharmony_ci return; 2544a46c0ec8Sopenharmony_ci 2545a46c0ec8Sopenharmony_ci ev = d->interface->tablet_motion_events; 2546a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2547a46c0ec8Sopenharmony_ci int value = auto_assign_tablet_value(d, ev, x, y, axes); 2548a46c0ec8Sopenharmony_ci if (!tablet_ignore_event(ev, value)) 2549a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2550a46c0ec8Sopenharmony_ci ev++; 2551a46c0ec8Sopenharmony_ci } 2552a46c0ec8Sopenharmony_ci} 2553a46c0ec8Sopenharmony_ci 2554a46c0ec8Sopenharmony_civoid 2555a46c0ec8Sopenharmony_cilitest_tablet_tip_down(struct litest_device *d, 2556a46c0ec8Sopenharmony_ci double x, double y, 2557a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2558a46c0ec8Sopenharmony_ci{ 2559a46c0ec8Sopenharmony_ci /* If the test device overrides tip_down and says it didn't 2560a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2561a46c0ec8Sopenharmony_ci if (d->interface->tablet_tip_down && 2562a46c0ec8Sopenharmony_ci d->interface->tablet_tip_down(d, &x, &y, axes)) 2563a46c0ec8Sopenharmony_ci return; 2564a46c0ec8Sopenharmony_ci 2565a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOUCH, 1); 2566a46c0ec8Sopenharmony_ci litest_tablet_motion(d, x, y, axes); 2567a46c0ec8Sopenharmony_ci} 2568a46c0ec8Sopenharmony_ci 2569a46c0ec8Sopenharmony_civoid 2570a46c0ec8Sopenharmony_cilitest_tablet_tip_up(struct litest_device *d, 2571a46c0ec8Sopenharmony_ci double x, double y, 2572a46c0ec8Sopenharmony_ci struct axis_replacement *axes) 2573a46c0ec8Sopenharmony_ci{ 2574a46c0ec8Sopenharmony_ci /* If the test device overrides tip_down and says it didn't 2575a46c0ec8Sopenharmony_ci * handle the event, let's continue normally */ 2576a46c0ec8Sopenharmony_ci if (d->interface->tablet_tip_up && 2577a46c0ec8Sopenharmony_ci d->interface->tablet_tip_up(d, &x, &y, axes)) 2578a46c0ec8Sopenharmony_ci return; 2579a46c0ec8Sopenharmony_ci 2580a46c0ec8Sopenharmony_ci litest_event(d, EV_KEY, BTN_TOUCH, 0); 2581a46c0ec8Sopenharmony_ci litest_tablet_motion(d, x, y, axes); 2582a46c0ec8Sopenharmony_ci} 2583a46c0ec8Sopenharmony_ci 2584a46c0ec8Sopenharmony_civoid 2585a46c0ec8Sopenharmony_cilitest_touch_move_two_touches(struct litest_device *d, 2586a46c0ec8Sopenharmony_ci double x0, double y0, 2587a46c0ec8Sopenharmony_ci double x1, double y1, 2588a46c0ec8Sopenharmony_ci double dx, double dy, 2589a46c0ec8Sopenharmony_ci int steps) 2590a46c0ec8Sopenharmony_ci{ 2591a46c0ec8Sopenharmony_ci int sleep_ms = 10; 2592a46c0ec8Sopenharmony_ci 2593a46c0ec8Sopenharmony_ci for (int i = 1; i < steps; i++) { 2594a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2595a46c0ec8Sopenharmony_ci litest_touch_move(d, 0, x0 + dx / steps * i, 2596a46c0ec8Sopenharmony_ci y0 + dy / steps * i); 2597a46c0ec8Sopenharmony_ci litest_touch_move(d, 1, x1 + dx / steps * i, 2598a46c0ec8Sopenharmony_ci y1 + dy / steps * i); 2599a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2600a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2601a46c0ec8Sopenharmony_ci msleep(sleep_ms); 2602a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2603a46c0ec8Sopenharmony_ci } 2604a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2605a46c0ec8Sopenharmony_ci litest_touch_move(d, 0, x0 + dx, y0 + dy); 2606a46c0ec8Sopenharmony_ci litest_touch_move(d, 1, x1 + dx, y1 + dy); 2607a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2608a46c0ec8Sopenharmony_ci} 2609a46c0ec8Sopenharmony_ci 2610a46c0ec8Sopenharmony_civoid 2611a46c0ec8Sopenharmony_cilitest_touch_move_three_touches(struct litest_device *d, 2612a46c0ec8Sopenharmony_ci double x0, double y0, 2613a46c0ec8Sopenharmony_ci double x1, double y1, 2614a46c0ec8Sopenharmony_ci double x2, double y2, 2615a46c0ec8Sopenharmony_ci double dx, double dy, 2616a46c0ec8Sopenharmony_ci int steps) 2617a46c0ec8Sopenharmony_ci{ 2618a46c0ec8Sopenharmony_ci int sleep_ms = 10; 2619a46c0ec8Sopenharmony_ci 2620a46c0ec8Sopenharmony_ci for (int i = 1; i <= steps; i++) { 2621a46c0ec8Sopenharmony_ci double step_x = dx / steps * i; 2622a46c0ec8Sopenharmony_ci double step_y = dy / steps * i; 2623a46c0ec8Sopenharmony_ci 2624a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2625a46c0ec8Sopenharmony_ci litest_touch_move(d, 0, x0 + step_x, y0 + step_y); 2626a46c0ec8Sopenharmony_ci litest_touch_move(d, 1, x1 + step_x, y1 + step_y); 2627a46c0ec8Sopenharmony_ci litest_touch_move(d, 2, x2 + step_x, y2 + step_y); 2628a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2629a46c0ec8Sopenharmony_ci 2630a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2631a46c0ec8Sopenharmony_ci msleep(sleep_ms); 2632a46c0ec8Sopenharmony_ci } 2633a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2634a46c0ec8Sopenharmony_ci} 2635a46c0ec8Sopenharmony_ci 2636a46c0ec8Sopenharmony_civoid 2637a46c0ec8Sopenharmony_cilitest_hover_start(struct litest_device *d, 2638a46c0ec8Sopenharmony_ci unsigned int slot, 2639a46c0ec8Sopenharmony_ci double x, 2640a46c0ec8Sopenharmony_ci double y) 2641a46c0ec8Sopenharmony_ci{ 2642a46c0ec8Sopenharmony_ci struct axis_replacement axes[] = { 2643a46c0ec8Sopenharmony_ci {ABS_MT_PRESSURE, 0 }, 2644a46c0ec8Sopenharmony_ci {ABS_PRESSURE, 0 }, 2645a46c0ec8Sopenharmony_ci {-1, -1 }, 2646a46c0ec8Sopenharmony_ci }; 2647a46c0ec8Sopenharmony_ci 2648a46c0ec8Sopenharmony_ci litest_slot_start(d, slot, x, y, axes, 0); 2649a46c0ec8Sopenharmony_ci} 2650a46c0ec8Sopenharmony_ci 2651a46c0ec8Sopenharmony_civoid 2652a46c0ec8Sopenharmony_cilitest_hover_end(struct litest_device *d, unsigned int slot) 2653a46c0ec8Sopenharmony_ci{ 2654a46c0ec8Sopenharmony_ci struct input_event *ev; 2655a46c0ec8Sopenharmony_ci struct input_event up[] = { 2656a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, 2657a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_DISTANCE, .value = 1 }, 2658a46c0ec8Sopenharmony_ci { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = -1 }, 2659a46c0ec8Sopenharmony_ci { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, 2660a46c0ec8Sopenharmony_ci { .type = -1, .code = -1 } 2661a46c0ec8Sopenharmony_ci }; 2662a46c0ec8Sopenharmony_ci 2663a46c0ec8Sopenharmony_ci litest_assert_int_gt(d->ntouches_down, 0); 2664a46c0ec8Sopenharmony_ci d->ntouches_down--; 2665a46c0ec8Sopenharmony_ci 2666a46c0ec8Sopenharmony_ci send_btntool(d, true); 2667a46c0ec8Sopenharmony_ci 2668a46c0ec8Sopenharmony_ci if (d->interface->touch_up) { 2669a46c0ec8Sopenharmony_ci d->interface->touch_up(d, slot); 2670a46c0ec8Sopenharmony_ci return; 2671a46c0ec8Sopenharmony_ci } else if (d->interface->touch_up_events) { 2672a46c0ec8Sopenharmony_ci ev = d->interface->touch_up_events; 2673a46c0ec8Sopenharmony_ci } else 2674a46c0ec8Sopenharmony_ci ev = up; 2675a46c0ec8Sopenharmony_ci 2676a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2677a46c0ec8Sopenharmony_ci int value = litest_auto_assign_value(d, ev, slot, 0, 0, NULL, false); 2678a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2679a46c0ec8Sopenharmony_ci ev++; 2680a46c0ec8Sopenharmony_ci } 2681a46c0ec8Sopenharmony_ci} 2682a46c0ec8Sopenharmony_ci 2683a46c0ec8Sopenharmony_civoid 2684a46c0ec8Sopenharmony_cilitest_hover_move(struct litest_device *d, unsigned int slot, 2685a46c0ec8Sopenharmony_ci double x, double y) 2686a46c0ec8Sopenharmony_ci{ 2687a46c0ec8Sopenharmony_ci struct axis_replacement axes[] = { 2688a46c0ec8Sopenharmony_ci {ABS_MT_PRESSURE, 0 }, 2689a46c0ec8Sopenharmony_ci {ABS_PRESSURE, 0 }, 2690a46c0ec8Sopenharmony_ci {-1, -1 }, 2691a46c0ec8Sopenharmony_ci }; 2692a46c0ec8Sopenharmony_ci 2693a46c0ec8Sopenharmony_ci litest_slot_move(d, slot, x, y, axes, false); 2694a46c0ec8Sopenharmony_ci} 2695a46c0ec8Sopenharmony_ci 2696a46c0ec8Sopenharmony_civoid 2697a46c0ec8Sopenharmony_cilitest_hover_move_to(struct litest_device *d, 2698a46c0ec8Sopenharmony_ci unsigned int slot, 2699a46c0ec8Sopenharmony_ci double x_from, double y_from, 2700a46c0ec8Sopenharmony_ci double x_to, double y_to, 2701a46c0ec8Sopenharmony_ci int steps) 2702a46c0ec8Sopenharmony_ci{ 2703a46c0ec8Sopenharmony_ci int sleep_ms = 10; 2704a46c0ec8Sopenharmony_ci 2705a46c0ec8Sopenharmony_ci for (int i = 0; i < steps - 1; i++) { 2706a46c0ec8Sopenharmony_ci litest_hover_move(d, slot, 2707a46c0ec8Sopenharmony_ci x_from + (x_to - x_from)/steps * i, 2708a46c0ec8Sopenharmony_ci y_from + (y_to - y_from)/steps * i); 2709a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2710a46c0ec8Sopenharmony_ci msleep(sleep_ms); 2711a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2712a46c0ec8Sopenharmony_ci } 2713a46c0ec8Sopenharmony_ci litest_hover_move(d, slot, x_to, y_to); 2714a46c0ec8Sopenharmony_ci} 2715a46c0ec8Sopenharmony_ci 2716a46c0ec8Sopenharmony_civoid 2717a46c0ec8Sopenharmony_cilitest_hover_move_two_touches(struct litest_device *d, 2718a46c0ec8Sopenharmony_ci double x0, double y0, 2719a46c0ec8Sopenharmony_ci double x1, double y1, 2720a46c0ec8Sopenharmony_ci double dx, double dy, 2721a46c0ec8Sopenharmony_ci int steps) 2722a46c0ec8Sopenharmony_ci{ 2723a46c0ec8Sopenharmony_ci int sleep_ms = 10; 2724a46c0ec8Sopenharmony_ci 2725a46c0ec8Sopenharmony_ci for (int i = 0; i < steps - 1; i++) { 2726a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2727a46c0ec8Sopenharmony_ci litest_hover_move(d, 0, x0 + dx / steps * i, 2728a46c0ec8Sopenharmony_ci y0 + dy / steps * i); 2729a46c0ec8Sopenharmony_ci litest_hover_move(d, 1, x1 + dx / steps * i, 2730a46c0ec8Sopenharmony_ci y1 + dy / steps * i); 2731a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2732a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2733a46c0ec8Sopenharmony_ci msleep(sleep_ms); 2734a46c0ec8Sopenharmony_ci libinput_dispatch(d->libinput); 2735a46c0ec8Sopenharmony_ci } 2736a46c0ec8Sopenharmony_ci litest_push_event_frame(d); 2737a46c0ec8Sopenharmony_ci litest_hover_move(d, 0, x0 + dx, y0 + dy); 2738a46c0ec8Sopenharmony_ci litest_hover_move(d, 1, x1 + dx, y1 + dy); 2739a46c0ec8Sopenharmony_ci litest_pop_event_frame(d); 2740a46c0ec8Sopenharmony_ci} 2741a46c0ec8Sopenharmony_ci 2742a46c0ec8Sopenharmony_civoid 2743a46c0ec8Sopenharmony_cilitest_button_click(struct litest_device *d, 2744a46c0ec8Sopenharmony_ci unsigned int button, 2745a46c0ec8Sopenharmony_ci bool is_press) 2746a46c0ec8Sopenharmony_ci{ 2747a46c0ec8Sopenharmony_ci struct input_event click[] = { 2748a46c0ec8Sopenharmony_ci { .type = EV_KEY, .code = button, .value = is_press ? 1 : 0 }, 2749a46c0ec8Sopenharmony_ci { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, 2750a46c0ec8Sopenharmony_ci }; 2751a46c0ec8Sopenharmony_ci 2752a46c0ec8Sopenharmony_ci ARRAY_FOR_EACH(click, ev) 2753a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, ev->value); 2754a46c0ec8Sopenharmony_ci} 2755a46c0ec8Sopenharmony_ci 2756a46c0ec8Sopenharmony_civoid 2757a46c0ec8Sopenharmony_cilitest_button_click_debounced(struct litest_device *d, 2758a46c0ec8Sopenharmony_ci struct libinput *li, 2759a46c0ec8Sopenharmony_ci unsigned int button, 2760a46c0ec8Sopenharmony_ci bool is_press) 2761a46c0ec8Sopenharmony_ci{ 2762a46c0ec8Sopenharmony_ci litest_button_click(d, button, is_press); 2763a46c0ec8Sopenharmony_ci 2764a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2765a46c0ec8Sopenharmony_ci litest_timeout_debounce(); 2766a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2767a46c0ec8Sopenharmony_ci} 2768a46c0ec8Sopenharmony_ci 2769a46c0ec8Sopenharmony_civoid 2770a46c0ec8Sopenharmony_cilitest_button_scroll(struct litest_device *dev, 2771a46c0ec8Sopenharmony_ci unsigned int button, 2772a46c0ec8Sopenharmony_ci double dx, double dy) 2773a46c0ec8Sopenharmony_ci{ 2774a46c0ec8Sopenharmony_ci struct libinput *li = dev->libinput; 2775a46c0ec8Sopenharmony_ci 2776a46c0ec8Sopenharmony_ci litest_button_click_debounced(dev, li, button, 1); 2777a46c0ec8Sopenharmony_ci 2778a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2779a46c0ec8Sopenharmony_ci litest_timeout_buttonscroll(); 2780a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2781a46c0ec8Sopenharmony_ci 2782a46c0ec8Sopenharmony_ci litest_event(dev, EV_REL, REL_X, dx); 2783a46c0ec8Sopenharmony_ci litest_event(dev, EV_REL, REL_Y, dy); 2784a46c0ec8Sopenharmony_ci litest_event(dev, EV_SYN, SYN_REPORT, 0); 2785a46c0ec8Sopenharmony_ci 2786a46c0ec8Sopenharmony_ci litest_button_click_debounced(dev, li, button, 0); 2787a46c0ec8Sopenharmony_ci 2788a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2789a46c0ec8Sopenharmony_ci} 2790a46c0ec8Sopenharmony_ci 2791a46c0ec8Sopenharmony_civoid 2792a46c0ec8Sopenharmony_cilitest_button_scroll_locked(struct litest_device *dev, 2793a46c0ec8Sopenharmony_ci unsigned int button, 2794a46c0ec8Sopenharmony_ci double dx, double dy) 2795a46c0ec8Sopenharmony_ci{ 2796a46c0ec8Sopenharmony_ci struct libinput *li = dev->libinput; 2797a46c0ec8Sopenharmony_ci 2798a46c0ec8Sopenharmony_ci litest_button_click_debounced(dev, li, button, 1); 2799a46c0ec8Sopenharmony_ci litest_button_click_debounced(dev, li, button, 0); 2800a46c0ec8Sopenharmony_ci 2801a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2802a46c0ec8Sopenharmony_ci litest_timeout_buttonscroll(); 2803a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2804a46c0ec8Sopenharmony_ci 2805a46c0ec8Sopenharmony_ci litest_event(dev, EV_REL, REL_X, dx); 2806a46c0ec8Sopenharmony_ci litest_event(dev, EV_REL, REL_Y, dy); 2807a46c0ec8Sopenharmony_ci litest_event(dev, EV_SYN, SYN_REPORT, 0); 2808a46c0ec8Sopenharmony_ci 2809a46c0ec8Sopenharmony_ci libinput_dispatch(li); 2810a46c0ec8Sopenharmony_ci} 2811a46c0ec8Sopenharmony_ci 2812a46c0ec8Sopenharmony_civoid 2813a46c0ec8Sopenharmony_cilitest_keyboard_key(struct litest_device *d, unsigned int key, bool is_press) 2814a46c0ec8Sopenharmony_ci{ 2815a46c0ec8Sopenharmony_ci struct input_event click[] = { 2816a46c0ec8Sopenharmony_ci { .type = EV_KEY, .code = key, .value = is_press ? 1 : 0 }, 2817a46c0ec8Sopenharmony_ci { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, 2818a46c0ec8Sopenharmony_ci }; 2819a46c0ec8Sopenharmony_ci 2820a46c0ec8Sopenharmony_ci ARRAY_FOR_EACH(click, ev) 2821a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, ev->value); 2822a46c0ec8Sopenharmony_ci} 2823a46c0ec8Sopenharmony_ci 2824a46c0ec8Sopenharmony_civoid 2825a46c0ec8Sopenharmony_cilitest_switch_action(struct litest_device *dev, 2826a46c0ec8Sopenharmony_ci enum libinput_switch sw, 2827a46c0ec8Sopenharmony_ci enum libinput_switch_state state) 2828a46c0ec8Sopenharmony_ci{ 2829a46c0ec8Sopenharmony_ci unsigned int code; 2830a46c0ec8Sopenharmony_ci 2831a46c0ec8Sopenharmony_ci switch (sw) { 2832a46c0ec8Sopenharmony_ci case LIBINPUT_SWITCH_LID: 2833a46c0ec8Sopenharmony_ci code = SW_LID; 2834a46c0ec8Sopenharmony_ci break; 2835a46c0ec8Sopenharmony_ci case LIBINPUT_SWITCH_TABLET_MODE: 2836a46c0ec8Sopenharmony_ci code = SW_TABLET_MODE; 2837a46c0ec8Sopenharmony_ci break; 2838a46c0ec8Sopenharmony_ci default: 2839a46c0ec8Sopenharmony_ci litest_abort_msg("Invalid switch %d", sw); 2840a46c0ec8Sopenharmony_ci break; 2841a46c0ec8Sopenharmony_ci } 2842a46c0ec8Sopenharmony_ci litest_event(dev, EV_SW, code, state); 2843a46c0ec8Sopenharmony_ci litest_event(dev, EV_SYN, SYN_REPORT, 0); 2844a46c0ec8Sopenharmony_ci} 2845a46c0ec8Sopenharmony_ci 2846a46c0ec8Sopenharmony_cistatic int 2847a46c0ec8Sopenharmony_cilitest_scale_axis(const struct litest_device *d, 2848a46c0ec8Sopenharmony_ci unsigned int axis, 2849a46c0ec8Sopenharmony_ci double val) 2850a46c0ec8Sopenharmony_ci{ 2851a46c0ec8Sopenharmony_ci const struct input_absinfo *abs; 2852a46c0ec8Sopenharmony_ci 2853a46c0ec8Sopenharmony_ci litest_assert_double_ge(val, 0.0); 2854a46c0ec8Sopenharmony_ci /* major/minor must be able to beyond 100% for large fingers */ 2855a46c0ec8Sopenharmony_ci if (axis != ABS_MT_TOUCH_MAJOR && 2856a46c0ec8Sopenharmony_ci axis != ABS_MT_TOUCH_MINOR) { 2857a46c0ec8Sopenharmony_ci litest_assert_double_le(val, 100.0); 2858a46c0ec8Sopenharmony_ci } 2859a46c0ec8Sopenharmony_ci 2860a46c0ec8Sopenharmony_ci abs = libevdev_get_abs_info(d->evdev, axis); 2861a46c0ec8Sopenharmony_ci litest_assert_notnull(abs); 2862a46c0ec8Sopenharmony_ci 2863a46c0ec8Sopenharmony_ci return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum; 2864a46c0ec8Sopenharmony_ci} 2865a46c0ec8Sopenharmony_ci 2866a46c0ec8Sopenharmony_cistatic inline int 2867a46c0ec8Sopenharmony_cilitest_scale_range(int min, int max, double val) 2868a46c0ec8Sopenharmony_ci{ 2869a46c0ec8Sopenharmony_ci litest_assert_int_ge((int)val, 0); 2870a46c0ec8Sopenharmony_ci litest_assert_int_le((int)val, 100); 2871a46c0ec8Sopenharmony_ci 2872a46c0ec8Sopenharmony_ci return (max - min) * val/100.0 + min; 2873a46c0ec8Sopenharmony_ci} 2874a46c0ec8Sopenharmony_ci 2875a46c0ec8Sopenharmony_ciint 2876a46c0ec8Sopenharmony_cilitest_scale(const struct litest_device *d, unsigned int axis, double val) 2877a46c0ec8Sopenharmony_ci{ 2878a46c0ec8Sopenharmony_ci int min, max; 2879a46c0ec8Sopenharmony_ci 2880a46c0ec8Sopenharmony_ci litest_assert_double_ge(val, 0.0); 2881a46c0ec8Sopenharmony_ci /* major/minor must be able to beyond 100% for large fingers */ 2882a46c0ec8Sopenharmony_ci if (axis != ABS_MT_TOUCH_MAJOR && 2883a46c0ec8Sopenharmony_ci axis != ABS_MT_TOUCH_MINOR) 2884a46c0ec8Sopenharmony_ci litest_assert_double_le(val, 100.0); 2885a46c0ec8Sopenharmony_ci 2886a46c0ec8Sopenharmony_ci if (axis <= ABS_Y) { 2887a46c0ec8Sopenharmony_ci min = d->interface->min[axis]; 2888a46c0ec8Sopenharmony_ci max = d->interface->max[axis]; 2889a46c0ec8Sopenharmony_ci 2890a46c0ec8Sopenharmony_ci return litest_scale_range(min, max, val); 2891a46c0ec8Sopenharmony_ci } else { 2892a46c0ec8Sopenharmony_ci return litest_scale_axis(d, axis, val); 2893a46c0ec8Sopenharmony_ci } 2894a46c0ec8Sopenharmony_ci} 2895a46c0ec8Sopenharmony_ci 2896a46c0ec8Sopenharmony_cistatic inline int 2897a46c0ec8Sopenharmony_ciauto_assign_pad_value(struct litest_device *dev, 2898a46c0ec8Sopenharmony_ci struct input_event *ev, 2899a46c0ec8Sopenharmony_ci double value) 2900a46c0ec8Sopenharmony_ci{ 2901a46c0ec8Sopenharmony_ci const struct input_absinfo *abs; 2902a46c0ec8Sopenharmony_ci 2903a46c0ec8Sopenharmony_ci if (ev->value != LITEST_AUTO_ASSIGN || 2904a46c0ec8Sopenharmony_ci ev->type != EV_ABS) 2905a46c0ec8Sopenharmony_ci return value; 2906a46c0ec8Sopenharmony_ci 2907a46c0ec8Sopenharmony_ci abs = libevdev_get_abs_info(dev->evdev, ev->code); 2908a46c0ec8Sopenharmony_ci litest_assert_notnull(abs); 2909a46c0ec8Sopenharmony_ci 2910a46c0ec8Sopenharmony_ci if (ev->code == ABS_RX || ev->code == ABS_RY) { 2911a46c0ec8Sopenharmony_ci double min = abs->minimum != 0 ? log2(abs->minimum) : 0, 2912a46c0ec8Sopenharmony_ci max = abs->maximum != 0 ? log2(abs->maximum) : 0; 2913a46c0ec8Sopenharmony_ci 2914a46c0ec8Sopenharmony_ci /* Value 0 is reserved for finger up, so a value of 0% is 2915a46c0ec8Sopenharmony_ci * actually 1 */ 2916a46c0ec8Sopenharmony_ci if (value == 0.0) { 2917a46c0ec8Sopenharmony_ci return 1; 2918a46c0ec8Sopenharmony_ci } else { 2919a46c0ec8Sopenharmony_ci value = litest_scale_range(min, max, value); 2920a46c0ec8Sopenharmony_ci return pow(2, value); 2921a46c0ec8Sopenharmony_ci } 2922a46c0ec8Sopenharmony_ci } else { 2923a46c0ec8Sopenharmony_ci return litest_scale_range(abs->minimum, abs->maximum, value); 2924a46c0ec8Sopenharmony_ci } 2925a46c0ec8Sopenharmony_ci} 2926a46c0ec8Sopenharmony_ci 2927a46c0ec8Sopenharmony_civoid 2928a46c0ec8Sopenharmony_cilitest_pad_ring_start(struct litest_device *d, double value) 2929a46c0ec8Sopenharmony_ci{ 2930a46c0ec8Sopenharmony_ci struct input_event *ev; 2931a46c0ec8Sopenharmony_ci 2932a46c0ec8Sopenharmony_ci ev = d->interface->pad_ring_start_events; 2933a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2934a46c0ec8Sopenharmony_ci value = auto_assign_pad_value(d, ev, value); 2935a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2936a46c0ec8Sopenharmony_ci ev++; 2937a46c0ec8Sopenharmony_ci } 2938a46c0ec8Sopenharmony_ci} 2939a46c0ec8Sopenharmony_ci 2940a46c0ec8Sopenharmony_civoid 2941a46c0ec8Sopenharmony_cilitest_pad_ring_change(struct litest_device *d, double value) 2942a46c0ec8Sopenharmony_ci{ 2943a46c0ec8Sopenharmony_ci struct input_event *ev; 2944a46c0ec8Sopenharmony_ci 2945a46c0ec8Sopenharmony_ci ev = d->interface->pad_ring_change_events; 2946a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2947a46c0ec8Sopenharmony_ci value = auto_assign_pad_value(d, ev, value); 2948a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2949a46c0ec8Sopenharmony_ci ev++; 2950a46c0ec8Sopenharmony_ci } 2951a46c0ec8Sopenharmony_ci} 2952a46c0ec8Sopenharmony_ci 2953a46c0ec8Sopenharmony_civoid 2954a46c0ec8Sopenharmony_cilitest_pad_ring_end(struct litest_device *d) 2955a46c0ec8Sopenharmony_ci{ 2956a46c0ec8Sopenharmony_ci struct input_event *ev; 2957a46c0ec8Sopenharmony_ci 2958a46c0ec8Sopenharmony_ci ev = d->interface->pad_ring_end_events; 2959a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2960a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, ev->value); 2961a46c0ec8Sopenharmony_ci ev++; 2962a46c0ec8Sopenharmony_ci } 2963a46c0ec8Sopenharmony_ci} 2964a46c0ec8Sopenharmony_ci 2965a46c0ec8Sopenharmony_civoid 2966a46c0ec8Sopenharmony_cilitest_pad_strip_start(struct litest_device *d, double value) 2967a46c0ec8Sopenharmony_ci{ 2968a46c0ec8Sopenharmony_ci struct input_event *ev; 2969a46c0ec8Sopenharmony_ci 2970a46c0ec8Sopenharmony_ci ev = d->interface->pad_strip_start_events; 2971a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2972a46c0ec8Sopenharmony_ci value = auto_assign_pad_value(d, ev, value); 2973a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2974a46c0ec8Sopenharmony_ci ev++; 2975a46c0ec8Sopenharmony_ci } 2976a46c0ec8Sopenharmony_ci} 2977a46c0ec8Sopenharmony_ci 2978a46c0ec8Sopenharmony_civoid 2979a46c0ec8Sopenharmony_cilitest_pad_strip_change(struct litest_device *d, double value) 2980a46c0ec8Sopenharmony_ci{ 2981a46c0ec8Sopenharmony_ci struct input_event *ev; 2982a46c0ec8Sopenharmony_ci 2983a46c0ec8Sopenharmony_ci ev = d->interface->pad_strip_change_events; 2984a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2985a46c0ec8Sopenharmony_ci value = auto_assign_pad_value(d, ev, value); 2986a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, value); 2987a46c0ec8Sopenharmony_ci ev++; 2988a46c0ec8Sopenharmony_ci } 2989a46c0ec8Sopenharmony_ci} 2990a46c0ec8Sopenharmony_ci 2991a46c0ec8Sopenharmony_civoid 2992a46c0ec8Sopenharmony_cilitest_pad_strip_end(struct litest_device *d) 2993a46c0ec8Sopenharmony_ci{ 2994a46c0ec8Sopenharmony_ci struct input_event *ev; 2995a46c0ec8Sopenharmony_ci 2996a46c0ec8Sopenharmony_ci ev = d->interface->pad_strip_end_events; 2997a46c0ec8Sopenharmony_ci while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) { 2998a46c0ec8Sopenharmony_ci litest_event(d, ev->type, ev->code, ev->value); 2999a46c0ec8Sopenharmony_ci ev++; 3000a46c0ec8Sopenharmony_ci } 3001a46c0ec8Sopenharmony_ci} 3002a46c0ec8Sopenharmony_ci 3003a46c0ec8Sopenharmony_civoid 3004a46c0ec8Sopenharmony_cilitest_wait_for_event(struct libinput *li) 3005a46c0ec8Sopenharmony_ci{ 3006a46c0ec8Sopenharmony_ci return litest_wait_for_event_of_type(li, -1); 3007a46c0ec8Sopenharmony_ci} 3008a46c0ec8Sopenharmony_ci 3009a46c0ec8Sopenharmony_civoid 3010a46c0ec8Sopenharmony_cilitest_wait_for_event_of_type(struct libinput *li, ...) 3011a46c0ec8Sopenharmony_ci{ 3012a46c0ec8Sopenharmony_ci va_list args; 3013a46c0ec8Sopenharmony_ci enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE}; 3014a46c0ec8Sopenharmony_ci size_t ntypes = 0; 3015a46c0ec8Sopenharmony_ci enum libinput_event_type type; 3016a46c0ec8Sopenharmony_ci struct pollfd fds; 3017a46c0ec8Sopenharmony_ci 3018a46c0ec8Sopenharmony_ci va_start(args, li); 3019a46c0ec8Sopenharmony_ci type = va_arg(args, int); 3020a46c0ec8Sopenharmony_ci while ((int)type != -1) { 3021a46c0ec8Sopenharmony_ci litest_assert_int_gt(type, 0U); 3022a46c0ec8Sopenharmony_ci litest_assert_int_lt(ntypes, ARRAY_LENGTH(types)); 3023a46c0ec8Sopenharmony_ci types[ntypes++] = type; 3024a46c0ec8Sopenharmony_ci type = va_arg(args, int); 3025a46c0ec8Sopenharmony_ci } 3026a46c0ec8Sopenharmony_ci va_end(args); 3027a46c0ec8Sopenharmony_ci 3028a46c0ec8Sopenharmony_ci fds.fd = libinput_get_fd(li); 3029a46c0ec8Sopenharmony_ci fds.events = POLLIN; 3030a46c0ec8Sopenharmony_ci fds.revents = 0; 3031a46c0ec8Sopenharmony_ci 3032a46c0ec8Sopenharmony_ci while (1) { 3033a46c0ec8Sopenharmony_ci size_t i; 3034a46c0ec8Sopenharmony_ci struct libinput_event *event; 3035a46c0ec8Sopenharmony_ci 3036a46c0ec8Sopenharmony_ci while ((type = libinput_next_event_type(li)) == LIBINPUT_EVENT_NONE) { 3037a46c0ec8Sopenharmony_ci int rc = poll(&fds, 1, 2000); 3038a46c0ec8Sopenharmony_ci litest_assert_int_gt(rc, 0); 3039a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3040a46c0ec8Sopenharmony_ci } 3041a46c0ec8Sopenharmony_ci 3042a46c0ec8Sopenharmony_ci /* no event mask means wait for any event */ 3043a46c0ec8Sopenharmony_ci if (ntypes == 0) 3044a46c0ec8Sopenharmony_ci return; 3045a46c0ec8Sopenharmony_ci 3046a46c0ec8Sopenharmony_ci for (i = 0; i < ntypes; i++) { 3047a46c0ec8Sopenharmony_ci if (type == types[i]) 3048a46c0ec8Sopenharmony_ci return; 3049a46c0ec8Sopenharmony_ci } 3050a46c0ec8Sopenharmony_ci 3051a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3052a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3053a46c0ec8Sopenharmony_ci } 3054a46c0ec8Sopenharmony_ci} 3055a46c0ec8Sopenharmony_ci 3056a46c0ec8Sopenharmony_civoid 3057a46c0ec8Sopenharmony_cilitest_drain_events(struct libinput *li) 3058a46c0ec8Sopenharmony_ci{ 3059a46c0ec8Sopenharmony_ci struct libinput_event *event; 3060a46c0ec8Sopenharmony_ci 3061a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3062a46c0ec8Sopenharmony_ci while ((event = libinput_get_event(li))) { 3063a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3064a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3065a46c0ec8Sopenharmony_ci } 3066a46c0ec8Sopenharmony_ci} 3067a46c0ec8Sopenharmony_ci 3068a46c0ec8Sopenharmony_ci 3069a46c0ec8Sopenharmony_civoid 3070a46c0ec8Sopenharmony_cilitest_drain_events_of_type(struct libinput *li, ...) 3071a46c0ec8Sopenharmony_ci{ 3072a46c0ec8Sopenharmony_ci enum libinput_event_type type; 3073a46c0ec8Sopenharmony_ci enum libinput_event_type types[32] = {LIBINPUT_EVENT_NONE}; 3074a46c0ec8Sopenharmony_ci size_t ntypes = 0; 3075a46c0ec8Sopenharmony_ci va_list args; 3076a46c0ec8Sopenharmony_ci 3077a46c0ec8Sopenharmony_ci va_start(args, li); 3078a46c0ec8Sopenharmony_ci type = va_arg(args, int); 3079a46c0ec8Sopenharmony_ci while ((int)type != -1) { 3080a46c0ec8Sopenharmony_ci litest_assert_int_gt(type, 0U); 3081a46c0ec8Sopenharmony_ci litest_assert_int_lt(ntypes, ARRAY_LENGTH(types)); 3082a46c0ec8Sopenharmony_ci types[ntypes++] = type; 3083a46c0ec8Sopenharmony_ci type = va_arg(args, int); 3084a46c0ec8Sopenharmony_ci } 3085a46c0ec8Sopenharmony_ci va_end(args); 3086a46c0ec8Sopenharmony_ci 3087a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3088a46c0ec8Sopenharmony_ci type = libinput_next_event_type(li); 3089a46c0ec8Sopenharmony_ci while (type != LIBINPUT_EVENT_NONE) { 3090a46c0ec8Sopenharmony_ci struct libinput_event *event; 3091a46c0ec8Sopenharmony_ci bool found = false; 3092a46c0ec8Sopenharmony_ci 3093a46c0ec8Sopenharmony_ci type = libinput_next_event_type(li); 3094a46c0ec8Sopenharmony_ci 3095a46c0ec8Sopenharmony_ci for (size_t i = 0; i < ntypes; i++) { 3096a46c0ec8Sopenharmony_ci if (type == types[i]) { 3097a46c0ec8Sopenharmony_ci found = true; 3098a46c0ec8Sopenharmony_ci break; 3099a46c0ec8Sopenharmony_ci } 3100a46c0ec8Sopenharmony_ci } 3101a46c0ec8Sopenharmony_ci if (!found) 3102a46c0ec8Sopenharmony_ci return; 3103a46c0ec8Sopenharmony_ci 3104a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3105a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3106a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3107a46c0ec8Sopenharmony_ci } 3108a46c0ec8Sopenharmony_ci} 3109a46c0ec8Sopenharmony_ci 3110a46c0ec8Sopenharmony_cistatic const char * 3111a46c0ec8Sopenharmony_cilitest_event_type_str(enum libinput_event_type type) 3112a46c0ec8Sopenharmony_ci{ 3113a46c0ec8Sopenharmony_ci const char *str = NULL; 3114a46c0ec8Sopenharmony_ci 3115a46c0ec8Sopenharmony_ci switch (type) { 3116a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_NONE: 3117a46c0ec8Sopenharmony_ci abort(); 3118a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_DEVICE_ADDED: 3119a46c0ec8Sopenharmony_ci str = "ADDED"; 3120a46c0ec8Sopenharmony_ci break; 3121a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_DEVICE_REMOVED: 3122a46c0ec8Sopenharmony_ci str = "REMOVED"; 3123a46c0ec8Sopenharmony_ci break; 3124a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_KEYBOARD_KEY: 3125a46c0ec8Sopenharmony_ci str = "KEY"; 3126a46c0ec8Sopenharmony_ci break; 3127a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_MOTION: 3128a46c0ec8Sopenharmony_ci str = "MOTION"; 3129a46c0ec8Sopenharmony_ci break; 3130a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: 3131a46c0ec8Sopenharmony_ci str = "ABSOLUTE"; 3132a46c0ec8Sopenharmony_ci break; 3133a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_BUTTON: 3134a46c0ec8Sopenharmony_ci str = "BUTTON"; 3135a46c0ec8Sopenharmony_ci break; 3136a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_AXIS: 3137a46c0ec8Sopenharmony_ci str = "AXIS"; 3138a46c0ec8Sopenharmony_ci break; 3139a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: 3140a46c0ec8Sopenharmony_ci str = "SCROLL_WHEEL"; 3141a46c0ec8Sopenharmony_ci break; 3142a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: 3143a46c0ec8Sopenharmony_ci str = "SCROLL_FINGER"; 3144a46c0ec8Sopenharmony_ci break; 3145a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: 3146a46c0ec8Sopenharmony_ci str = "SCROLL_CONTINUOUS"; 3147a46c0ec8Sopenharmony_ci break; 3148a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_DOWN: 3149a46c0ec8Sopenharmony_ci str = "TOUCH DOWN"; 3150a46c0ec8Sopenharmony_ci break; 3151a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_UP: 3152a46c0ec8Sopenharmony_ci str = "TOUCH UP"; 3153a46c0ec8Sopenharmony_ci break; 3154a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_MOTION: 3155a46c0ec8Sopenharmony_ci str = "TOUCH MOTION"; 3156a46c0ec8Sopenharmony_ci break; 3157a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_CANCEL: 3158a46c0ec8Sopenharmony_ci str = "TOUCH CANCEL"; 3159a46c0ec8Sopenharmony_ci break; 3160a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_FRAME: 3161a46c0ec8Sopenharmony_ci str = "TOUCH FRAME"; 3162a46c0ec8Sopenharmony_ci break; 3163a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: 3164a46c0ec8Sopenharmony_ci str = "GESTURE SWIPE BEGIN"; 3165a46c0ec8Sopenharmony_ci break; 3166a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: 3167a46c0ec8Sopenharmony_ci str = "GESTURE SWIPE UPDATE"; 3168a46c0ec8Sopenharmony_ci break; 3169a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_SWIPE_END: 3170a46c0ec8Sopenharmony_ci str = "GESTURE SWIPE END"; 3171a46c0ec8Sopenharmony_ci break; 3172a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: 3173a46c0ec8Sopenharmony_ci str = "GESTURE PINCH BEGIN"; 3174a46c0ec8Sopenharmony_ci break; 3175a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: 3176a46c0ec8Sopenharmony_ci str = "GESTURE PINCH UPDATE"; 3177a46c0ec8Sopenharmony_ci break; 3178a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_PINCH_END: 3179a46c0ec8Sopenharmony_ci str = "GESTURE PINCH END"; 3180a46c0ec8Sopenharmony_ci break; 3181a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN: 3182a46c0ec8Sopenharmony_ci str = "GESTURE HOLD BEGIN"; 3183a46c0ec8Sopenharmony_ci break; 3184a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_GESTURE_HOLD_END: 3185a46c0ec8Sopenharmony_ci str = "GESTURE HOLD END"; 3186a46c0ec8Sopenharmony_ci break; 3187a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_AXIS: 3188a46c0ec8Sopenharmony_ci str = "TABLET TOOL AXIS"; 3189a46c0ec8Sopenharmony_ci break; 3190a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: 3191a46c0ec8Sopenharmony_ci str = "TABLET TOOL PROX"; 3192a46c0ec8Sopenharmony_ci break; 3193a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_TIP: 3194a46c0ec8Sopenharmony_ci str = "TABLET TOOL TIP"; 3195a46c0ec8Sopenharmony_ci break; 3196a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: 3197a46c0ec8Sopenharmony_ci str = "TABLET TOOL BUTTON"; 3198a46c0ec8Sopenharmony_ci break; 3199a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_BUTTON: 3200a46c0ec8Sopenharmony_ci str = "TABLET PAD BUTTON"; 3201a46c0ec8Sopenharmony_ci break; 3202a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_RING: 3203a46c0ec8Sopenharmony_ci str = "TABLET PAD RING"; 3204a46c0ec8Sopenharmony_ci break; 3205a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_STRIP: 3206a46c0ec8Sopenharmony_ci str = "TABLET PAD STRIP"; 3207a46c0ec8Sopenharmony_ci break; 3208a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_KEY: 3209a46c0ec8Sopenharmony_ci str = "TABLET PAD KEY"; 3210a46c0ec8Sopenharmony_ci break; 3211a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_SWITCH_TOGGLE: 3212a46c0ec8Sopenharmony_ci str = "SWITCH TOGGLE"; 3213a46c0ec8Sopenharmony_ci break; 3214a46c0ec8Sopenharmony_ci } 3215a46c0ec8Sopenharmony_ci return str; 3216a46c0ec8Sopenharmony_ci} 3217a46c0ec8Sopenharmony_ci 3218a46c0ec8Sopenharmony_cistatic const char * 3219a46c0ec8Sopenharmony_cilitest_event_get_type_str(struct libinput_event *event) 3220a46c0ec8Sopenharmony_ci{ 3221a46c0ec8Sopenharmony_ci return litest_event_type_str(libinput_event_get_type(event)); 3222a46c0ec8Sopenharmony_ci} 3223a46c0ec8Sopenharmony_ci 3224a46c0ec8Sopenharmony_cistatic void 3225a46c0ec8Sopenharmony_cilitest_print_event(struct libinput_event *event) 3226a46c0ec8Sopenharmony_ci{ 3227a46c0ec8Sopenharmony_ci struct libinput_event_pointer *p; 3228a46c0ec8Sopenharmony_ci struct libinput_event_tablet_tool *t; 3229a46c0ec8Sopenharmony_ci struct libinput_event_tablet_pad *pad; 3230a46c0ec8Sopenharmony_ci struct libinput_device *dev; 3231a46c0ec8Sopenharmony_ci enum libinput_event_type type; 3232a46c0ec8Sopenharmony_ci double x, y; 3233a46c0ec8Sopenharmony_ci 3234a46c0ec8Sopenharmony_ci dev = libinput_event_get_device(event); 3235a46c0ec8Sopenharmony_ci type = libinput_event_get_type(event); 3236a46c0ec8Sopenharmony_ci 3237a46c0ec8Sopenharmony_ci fprintf(stderr, 3238a46c0ec8Sopenharmony_ci "device %s (%s) type %s ", 3239a46c0ec8Sopenharmony_ci libinput_device_get_sysname(dev), 3240a46c0ec8Sopenharmony_ci libinput_device_get_name(dev), 3241a46c0ec8Sopenharmony_ci litest_event_get_type_str(event)); 3242a46c0ec8Sopenharmony_ci switch (type) { 3243a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_MOTION: 3244a46c0ec8Sopenharmony_ci p = libinput_event_get_pointer_event(event); 3245a46c0ec8Sopenharmony_ci x = libinput_event_pointer_get_dx(p); 3246a46c0ec8Sopenharmony_ci y = libinput_event_pointer_get_dy(p); 3247a46c0ec8Sopenharmony_ci fprintf(stderr, "%.2f/%.2f", x, y); 3248a46c0ec8Sopenharmony_ci break; 3249a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: 3250a46c0ec8Sopenharmony_ci p = libinput_event_get_pointer_event(event); 3251a46c0ec8Sopenharmony_ci x = libinput_event_pointer_get_absolute_x(p); 3252a46c0ec8Sopenharmony_ci y = libinput_event_pointer_get_absolute_y(p); 3253a46c0ec8Sopenharmony_ci fprintf(stderr, "%.2f/%.2f", x, y); 3254a46c0ec8Sopenharmony_ci break; 3255a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_BUTTON: 3256a46c0ec8Sopenharmony_ci p = libinput_event_get_pointer_event(event); 3257a46c0ec8Sopenharmony_ci fprintf(stderr, 3258a46c0ec8Sopenharmony_ci "button %d state %d", 3259a46c0ec8Sopenharmony_ci libinput_event_pointer_get_button(p), 3260a46c0ec8Sopenharmony_ci libinput_event_pointer_get_button_state(p)); 3261a46c0ec8Sopenharmony_ci break; 3262a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_AXIS: 3263a46c0ec8Sopenharmony_ci p = libinput_event_get_pointer_event(event); 3264a46c0ec8Sopenharmony_ci x = 0.0; 3265a46c0ec8Sopenharmony_ci y = 0.0; 3266a46c0ec8Sopenharmony_ci if (libinput_event_pointer_has_axis(p, 3267a46c0ec8Sopenharmony_ci LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) 3268a46c0ec8Sopenharmony_ci y = libinput_event_pointer_get_axis_value(p, 3269a46c0ec8Sopenharmony_ci LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); 3270a46c0ec8Sopenharmony_ci if (libinput_event_pointer_has_axis(p, 3271a46c0ec8Sopenharmony_ci LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) 3272a46c0ec8Sopenharmony_ci x = libinput_event_pointer_get_axis_value(p, 3273a46c0ec8Sopenharmony_ci LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); 3274a46c0ec8Sopenharmony_ci fprintf(stderr, "vert %.2f horiz %.2f", y, x); 3275a46c0ec8Sopenharmony_ci break; 3276a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: 3277a46c0ec8Sopenharmony_ci t = libinput_event_get_tablet_tool_event(event); 3278a46c0ec8Sopenharmony_ci fprintf(stderr, "proximity %d", 3279a46c0ec8Sopenharmony_ci libinput_event_tablet_tool_get_proximity_state(t)); 3280a46c0ec8Sopenharmony_ci break; 3281a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_TIP: 3282a46c0ec8Sopenharmony_ci t = libinput_event_get_tablet_tool_event(event); 3283a46c0ec8Sopenharmony_ci fprintf(stderr, "tip %d", 3284a46c0ec8Sopenharmony_ci libinput_event_tablet_tool_get_tip_state(t)); 3285a46c0ec8Sopenharmony_ci break; 3286a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: 3287a46c0ec8Sopenharmony_ci t = libinput_event_get_tablet_tool_event(event); 3288a46c0ec8Sopenharmony_ci fprintf(stderr, "button %d state %d", 3289a46c0ec8Sopenharmony_ci libinput_event_tablet_tool_get_button(t), 3290a46c0ec8Sopenharmony_ci libinput_event_tablet_tool_get_button_state(t)); 3291a46c0ec8Sopenharmony_ci break; 3292a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_BUTTON: 3293a46c0ec8Sopenharmony_ci pad = libinput_event_get_tablet_pad_event(event); 3294a46c0ec8Sopenharmony_ci fprintf(stderr, "button %d state %d", 3295a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_button_number(pad), 3296a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_button_state(pad)); 3297a46c0ec8Sopenharmony_ci break; 3298a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_RING: 3299a46c0ec8Sopenharmony_ci pad = libinput_event_get_tablet_pad_event(event); 3300a46c0ec8Sopenharmony_ci fprintf(stderr, "ring %d position %.2f source %d", 3301a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_number(pad), 3302a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_position(pad), 3303a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_source(pad)); 3304a46c0ec8Sopenharmony_ci break; 3305a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TABLET_PAD_STRIP: 3306a46c0ec8Sopenharmony_ci pad = libinput_event_get_tablet_pad_event(event); 3307a46c0ec8Sopenharmony_ci fprintf(stderr, "strip %d position %.2f source %d", 3308a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_number(pad), 3309a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_position(pad), 3310a46c0ec8Sopenharmony_ci libinput_event_tablet_pad_get_ring_source(pad)); 3311a46c0ec8Sopenharmony_ci break; 3312a46c0ec8Sopenharmony_ci default: 3313a46c0ec8Sopenharmony_ci break; 3314a46c0ec8Sopenharmony_ci } 3315a46c0ec8Sopenharmony_ci 3316a46c0ec8Sopenharmony_ci fprintf(stderr, "\n"); 3317a46c0ec8Sopenharmony_ci} 3318a46c0ec8Sopenharmony_ci 3319a46c0ec8Sopenharmony_ci#define litest_assert_event_type_is_one_of(...) \ 3320a46c0ec8Sopenharmony_ci _litest_assert_event_type_is_one_of(__VA_ARGS__, -1) 3321a46c0ec8Sopenharmony_ci 3322a46c0ec8Sopenharmony_cistatic void 3323a46c0ec8Sopenharmony_ci_litest_assert_event_type_is_one_of(struct libinput_event *event, ...) 3324a46c0ec8Sopenharmony_ci{ 3325a46c0ec8Sopenharmony_ci va_list args; 3326a46c0ec8Sopenharmony_ci enum libinput_event_type expected_type; 3327a46c0ec8Sopenharmony_ci enum libinput_event_type actual_type = libinput_event_get_type(event); 3328a46c0ec8Sopenharmony_ci bool match = false; 3329a46c0ec8Sopenharmony_ci 3330a46c0ec8Sopenharmony_ci va_start(args, event); 3331a46c0ec8Sopenharmony_ci expected_type = va_arg(args, int); 3332a46c0ec8Sopenharmony_ci while ((int)expected_type != -1 && !match) { 3333a46c0ec8Sopenharmony_ci match = (actual_type == expected_type); 3334a46c0ec8Sopenharmony_ci expected_type = va_arg(args, int); 3335a46c0ec8Sopenharmony_ci } 3336a46c0ec8Sopenharmony_ci va_end(args); 3337a46c0ec8Sopenharmony_ci 3338a46c0ec8Sopenharmony_ci if (match) 3339a46c0ec8Sopenharmony_ci return; 3340a46c0ec8Sopenharmony_ci 3341a46c0ec8Sopenharmony_ci fprintf(stderr, 3342a46c0ec8Sopenharmony_ci "FAILED EVENT TYPE: %s: have %s (%d) but want ", 3343a46c0ec8Sopenharmony_ci libinput_device_get_name(libinput_event_get_device(event)), 3344a46c0ec8Sopenharmony_ci litest_event_get_type_str(event), 3345a46c0ec8Sopenharmony_ci libinput_event_get_type(event)); 3346a46c0ec8Sopenharmony_ci 3347a46c0ec8Sopenharmony_ci va_start(args, event); 3348a46c0ec8Sopenharmony_ci expected_type = va_arg(args, int); 3349a46c0ec8Sopenharmony_ci while ((int)expected_type != -1) { 3350a46c0ec8Sopenharmony_ci fprintf(stderr, 3351a46c0ec8Sopenharmony_ci "%s (%d)", 3352a46c0ec8Sopenharmony_ci litest_event_type_str(expected_type), 3353a46c0ec8Sopenharmony_ci expected_type); 3354a46c0ec8Sopenharmony_ci expected_type = va_arg(args, int); 3355a46c0ec8Sopenharmony_ci 3356a46c0ec8Sopenharmony_ci if ((int)expected_type != -1) 3357a46c0ec8Sopenharmony_ci fprintf(stderr, " || "); 3358a46c0ec8Sopenharmony_ci } 3359a46c0ec8Sopenharmony_ci 3360a46c0ec8Sopenharmony_ci fprintf(stderr, "\nWrong event is: "); 3361a46c0ec8Sopenharmony_ci litest_print_event(event); 3362a46c0ec8Sopenharmony_ci litest_backtrace(); 3363a46c0ec8Sopenharmony_ci abort(); 3364a46c0ec8Sopenharmony_ci} 3365a46c0ec8Sopenharmony_ci 3366a46c0ec8Sopenharmony_civoid 3367a46c0ec8Sopenharmony_cilitest_assert_event_type(struct libinput_event *event, 3368a46c0ec8Sopenharmony_ci enum libinput_event_type want) 3369a46c0ec8Sopenharmony_ci{ 3370a46c0ec8Sopenharmony_ci litest_assert_event_type_is_one_of(event, want); 3371a46c0ec8Sopenharmony_ci} 3372a46c0ec8Sopenharmony_ci 3373a46c0ec8Sopenharmony_civoid 3374a46c0ec8Sopenharmony_cilitest_assert_empty_queue(struct libinput *li) 3375a46c0ec8Sopenharmony_ci{ 3376a46c0ec8Sopenharmony_ci bool empty_queue = true; 3377a46c0ec8Sopenharmony_ci struct libinput_event *event; 3378a46c0ec8Sopenharmony_ci 3379a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3380a46c0ec8Sopenharmony_ci while ((event = libinput_get_event(li))) { 3381a46c0ec8Sopenharmony_ci empty_queue = false; 3382a46c0ec8Sopenharmony_ci fprintf(stderr, 3383a46c0ec8Sopenharmony_ci "Unexpected event: "); 3384a46c0ec8Sopenharmony_ci litest_print_event(event); 3385a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3386a46c0ec8Sopenharmony_ci libinput_dispatch(li); 3387a46c0ec8Sopenharmony_ci } 3388a46c0ec8Sopenharmony_ci 3389a46c0ec8Sopenharmony_ci litest_assert(empty_queue); 3390a46c0ec8Sopenharmony_ci} 3391a46c0ec8Sopenharmony_ci 3392a46c0ec8Sopenharmony_cistatic struct libevdev_uinput * 3393a46c0ec8Sopenharmony_cilitest_create_uinput(const char *name, 3394a46c0ec8Sopenharmony_ci const struct input_id *id, 3395a46c0ec8Sopenharmony_ci const struct input_absinfo *abs_info, 3396a46c0ec8Sopenharmony_ci const int *events) 3397a46c0ec8Sopenharmony_ci{ 3398a46c0ec8Sopenharmony_ci struct libevdev_uinput *uinput; 3399a46c0ec8Sopenharmony_ci struct libevdev *dev; 3400a46c0ec8Sopenharmony_ci int type, code; 3401a46c0ec8Sopenharmony_ci int rc, fd; 3402a46c0ec8Sopenharmony_ci const struct input_absinfo *abs; 3403a46c0ec8Sopenharmony_ci const struct input_absinfo default_abs = { 3404a46c0ec8Sopenharmony_ci .value = 0, 3405a46c0ec8Sopenharmony_ci .minimum = 0, 3406a46c0ec8Sopenharmony_ci .maximum = 100, 3407a46c0ec8Sopenharmony_ci .fuzz = 0, 3408a46c0ec8Sopenharmony_ci .flat = 0, 3409a46c0ec8Sopenharmony_ci .resolution = 100 3410a46c0ec8Sopenharmony_ci }; 3411a46c0ec8Sopenharmony_ci char buf[512]; 3412a46c0ec8Sopenharmony_ci const char *devnode; 3413a46c0ec8Sopenharmony_ci 3414a46c0ec8Sopenharmony_ci dev = libevdev_new(); 3415a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(dev); 3416a46c0ec8Sopenharmony_ci 3417a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "litest %s", name); 3418a46c0ec8Sopenharmony_ci libevdev_set_name(dev, buf); 3419a46c0ec8Sopenharmony_ci if (id) { 3420a46c0ec8Sopenharmony_ci libevdev_set_id_bustype(dev, id->bustype); 3421a46c0ec8Sopenharmony_ci libevdev_set_id_vendor(dev, id->vendor); 3422a46c0ec8Sopenharmony_ci libevdev_set_id_product(dev, id->product); 3423a46c0ec8Sopenharmony_ci libevdev_set_id_version(dev, id->version); 3424a46c0ec8Sopenharmony_ci } 3425a46c0ec8Sopenharmony_ci 3426a46c0ec8Sopenharmony_ci abs = abs_info; 3427a46c0ec8Sopenharmony_ci while (abs && abs->value != -1) { 3428a46c0ec8Sopenharmony_ci struct input_absinfo a = *abs; 3429a46c0ec8Sopenharmony_ci 3430a46c0ec8Sopenharmony_ci /* abs_info->value is used for the code and may be outside 3431a46c0ec8Sopenharmony_ci of [min, max] */ 3432a46c0ec8Sopenharmony_ci a.value = abs->minimum; 3433a46c0ec8Sopenharmony_ci rc = libevdev_enable_event_code(dev, EV_ABS, abs->value, &a); 3434a46c0ec8Sopenharmony_ci litest_assert_int_eq(rc, 0); 3435a46c0ec8Sopenharmony_ci abs++; 3436a46c0ec8Sopenharmony_ci } 3437a46c0ec8Sopenharmony_ci 3438a46c0ec8Sopenharmony_ci while (events && 3439a46c0ec8Sopenharmony_ci (type = *events++) != -1 && 3440a46c0ec8Sopenharmony_ci (code = *events++) != -1) { 3441a46c0ec8Sopenharmony_ci if (type == INPUT_PROP_MAX) { 3442a46c0ec8Sopenharmony_ci rc = libevdev_enable_property(dev, code); 3443a46c0ec8Sopenharmony_ci } else { 3444a46c0ec8Sopenharmony_ci rc = libevdev_enable_event_code(dev, type, code, 3445a46c0ec8Sopenharmony_ci type == EV_ABS ? &default_abs : NULL); 3446a46c0ec8Sopenharmony_ci } 3447a46c0ec8Sopenharmony_ci litest_assert_int_eq(rc, 0); 3448a46c0ec8Sopenharmony_ci } 3449a46c0ec8Sopenharmony_ci 3450a46c0ec8Sopenharmony_ci rc = libevdev_uinput_create_from_device(dev, 3451a46c0ec8Sopenharmony_ci LIBEVDEV_UINPUT_OPEN_MANAGED, 3452a46c0ec8Sopenharmony_ci &uinput); 3453a46c0ec8Sopenharmony_ci /* workaround for a bug in libevdev pre-1.3 3454a46c0ec8Sopenharmony_ci http://cgit.freedesktop.org/libevdev/commit/?id=debe9b030c8069cdf78307888ef3b65830b25122 */ 3455a46c0ec8Sopenharmony_ci if (rc == -EBADF) 3456a46c0ec8Sopenharmony_ci rc = -EACCES; 3457a46c0ec8Sopenharmony_ci litest_assert_msg(rc == 0, "Failed to create uinput device: %s\n", strerror(-rc)); 3458a46c0ec8Sopenharmony_ci 3459a46c0ec8Sopenharmony_ci libevdev_free(dev); 3460a46c0ec8Sopenharmony_ci 3461a46c0ec8Sopenharmony_ci devnode = libevdev_uinput_get_devnode(uinput); 3462a46c0ec8Sopenharmony_ci litest_assert_notnull(devnode); 3463a46c0ec8Sopenharmony_ci fd = open(devnode, O_RDONLY); 3464a46c0ec8Sopenharmony_ci litest_assert_int_gt(fd, -1); 3465a46c0ec8Sopenharmony_ci rc = libevdev_new_from_fd(fd, &dev); 3466a46c0ec8Sopenharmony_ci litest_assert_int_eq(rc, 0); 3467a46c0ec8Sopenharmony_ci 3468a46c0ec8Sopenharmony_ci /* uinput before kernel 4.5 + libevdev 1.5.0 does not support 3469a46c0ec8Sopenharmony_ci * setting the resolution, so we set it afterwards. This is of 3470a46c0ec8Sopenharmony_ci * course racy as hell but the way we _generally_ use this function 3471a46c0ec8Sopenharmony_ci * by the time libinput uses the device, we're finished here. 3472a46c0ec8Sopenharmony_ci * 3473a46c0ec8Sopenharmony_ci * If you have kernel 4.5 and libevdev 1.5.0 or later, this code 3474a46c0ec8Sopenharmony_ci * just keeps the room warm. 3475a46c0ec8Sopenharmony_ci */ 3476a46c0ec8Sopenharmony_ci abs = abs_info; 3477a46c0ec8Sopenharmony_ci while (abs && abs->value != -1) { 3478a46c0ec8Sopenharmony_ci if (abs->resolution != 0) { 3479a46c0ec8Sopenharmony_ci if (libevdev_get_abs_resolution(dev, abs->value) == 3480a46c0ec8Sopenharmony_ci abs->resolution) 3481a46c0ec8Sopenharmony_ci break; 3482a46c0ec8Sopenharmony_ci 3483a46c0ec8Sopenharmony_ci rc = libevdev_kernel_set_abs_info(dev, 3484a46c0ec8Sopenharmony_ci abs->value, 3485a46c0ec8Sopenharmony_ci abs); 3486a46c0ec8Sopenharmony_ci litest_assert_int_eq(rc, 0); 3487a46c0ec8Sopenharmony_ci } 3488a46c0ec8Sopenharmony_ci abs++; 3489a46c0ec8Sopenharmony_ci } 3490a46c0ec8Sopenharmony_ci close(fd); 3491a46c0ec8Sopenharmony_ci libevdev_free(dev); 3492a46c0ec8Sopenharmony_ci 3493a46c0ec8Sopenharmony_ci return uinput; 3494a46c0ec8Sopenharmony_ci} 3495a46c0ec8Sopenharmony_ci 3496a46c0ec8Sopenharmony_cistruct libevdev_uinput * 3497a46c0ec8Sopenharmony_cilitest_create_uinput_device_from_description(const char *name, 3498a46c0ec8Sopenharmony_ci const struct input_id *id, 3499a46c0ec8Sopenharmony_ci const struct input_absinfo *abs_info, 3500a46c0ec8Sopenharmony_ci const int *events) 3501a46c0ec8Sopenharmony_ci{ 3502a46c0ec8Sopenharmony_ci struct libevdev_uinput *uinput; 3503a46c0ec8Sopenharmony_ci const char *syspath; 3504a46c0ec8Sopenharmony_ci char path[PATH_MAX]; 3505a46c0ec8Sopenharmony_ci 3506a46c0ec8Sopenharmony_ci struct udev_monitor *udev_monitor; 3507a46c0ec8Sopenharmony_ci struct udev_device *udev_device; 3508a46c0ec8Sopenharmony_ci 3509a46c0ec8Sopenharmony_ci udev_monitor = udev_setup_monitor(); 3510a46c0ec8Sopenharmony_ci 3511a46c0ec8Sopenharmony_ci uinput = litest_create_uinput(name, id, abs_info, events); 3512a46c0ec8Sopenharmony_ci 3513a46c0ec8Sopenharmony_ci syspath = libevdev_uinput_get_syspath(uinput); 3514a46c0ec8Sopenharmony_ci snprintf(path, sizeof(path), "%s/event", syspath); 3515a46c0ec8Sopenharmony_ci 3516a46c0ec8Sopenharmony_ci udev_device = udev_wait_for_device_event(udev_monitor, "add", path); 3517a46c0ec8Sopenharmony_ci 3518a46c0ec8Sopenharmony_ci litest_assert(udev_device_get_property_value(udev_device, "ID_INPUT")); 3519a46c0ec8Sopenharmony_ci 3520a46c0ec8Sopenharmony_ci udev_device_unref(udev_device); 3521a46c0ec8Sopenharmony_ci udev_monitor_unref(udev_monitor); 3522a46c0ec8Sopenharmony_ci 3523a46c0ec8Sopenharmony_ci return uinput; 3524a46c0ec8Sopenharmony_ci} 3525a46c0ec8Sopenharmony_ci 3526a46c0ec8Sopenharmony_cistatic struct libevdev_uinput * 3527a46c0ec8Sopenharmony_cilitest_create_uinput_abs_device_v(const char *name, 3528a46c0ec8Sopenharmony_ci struct input_id *id, 3529a46c0ec8Sopenharmony_ci const struct input_absinfo *abs, 3530a46c0ec8Sopenharmony_ci va_list args) 3531a46c0ec8Sopenharmony_ci{ 3532a46c0ec8Sopenharmony_ci int events[KEY_MAX * 2 + 2]; /* increase this if not sufficient */ 3533a46c0ec8Sopenharmony_ci int *event = events; 3534a46c0ec8Sopenharmony_ci int type, code; 3535a46c0ec8Sopenharmony_ci 3536a46c0ec8Sopenharmony_ci while ((type = va_arg(args, int)) != -1 && 3537a46c0ec8Sopenharmony_ci (code = va_arg(args, int)) != -1) { 3538a46c0ec8Sopenharmony_ci *event++ = type; 3539a46c0ec8Sopenharmony_ci *event++ = code; 3540a46c0ec8Sopenharmony_ci litest_assert(event < &events[ARRAY_LENGTH(events) - 2]); 3541a46c0ec8Sopenharmony_ci } 3542a46c0ec8Sopenharmony_ci 3543a46c0ec8Sopenharmony_ci *event++ = -1; 3544a46c0ec8Sopenharmony_ci *event++ = -1; 3545a46c0ec8Sopenharmony_ci 3546a46c0ec8Sopenharmony_ci return litest_create_uinput_device_from_description(name, id, 3547a46c0ec8Sopenharmony_ci abs, events); 3548a46c0ec8Sopenharmony_ci} 3549a46c0ec8Sopenharmony_ci 3550a46c0ec8Sopenharmony_cistruct libevdev_uinput * 3551a46c0ec8Sopenharmony_cilitest_create_uinput_abs_device(const char *name, 3552a46c0ec8Sopenharmony_ci struct input_id *id, 3553a46c0ec8Sopenharmony_ci const struct input_absinfo *abs, 3554a46c0ec8Sopenharmony_ci ...) 3555a46c0ec8Sopenharmony_ci{ 3556a46c0ec8Sopenharmony_ci struct libevdev_uinput *uinput; 3557a46c0ec8Sopenharmony_ci va_list args; 3558a46c0ec8Sopenharmony_ci 3559a46c0ec8Sopenharmony_ci va_start(args, abs); 3560a46c0ec8Sopenharmony_ci uinput = litest_create_uinput_abs_device_v(name, id, abs, args); 3561a46c0ec8Sopenharmony_ci va_end(args); 3562a46c0ec8Sopenharmony_ci 3563a46c0ec8Sopenharmony_ci return uinput; 3564a46c0ec8Sopenharmony_ci} 3565a46c0ec8Sopenharmony_ci 3566a46c0ec8Sopenharmony_cistruct libevdev_uinput * 3567a46c0ec8Sopenharmony_cilitest_create_uinput_device(const char *name, struct input_id *id, ...) 3568a46c0ec8Sopenharmony_ci{ 3569a46c0ec8Sopenharmony_ci struct libevdev_uinput *uinput; 3570a46c0ec8Sopenharmony_ci va_list args; 3571a46c0ec8Sopenharmony_ci 3572a46c0ec8Sopenharmony_ci va_start(args, id); 3573a46c0ec8Sopenharmony_ci uinput = litest_create_uinput_abs_device_v(name, id, NULL, args); 3574a46c0ec8Sopenharmony_ci va_end(args); 3575a46c0ec8Sopenharmony_ci 3576a46c0ec8Sopenharmony_ci return uinput; 3577a46c0ec8Sopenharmony_ci} 3578a46c0ec8Sopenharmony_ci 3579a46c0ec8Sopenharmony_cistruct libinput_event_pointer* 3580a46c0ec8Sopenharmony_cilitest_is_button_event(struct libinput_event *event, 3581a46c0ec8Sopenharmony_ci unsigned int button, 3582a46c0ec8Sopenharmony_ci enum libinput_button_state state) 3583a46c0ec8Sopenharmony_ci{ 3584a46c0ec8Sopenharmony_ci struct libinput_event_pointer *ptrev; 3585a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_POINTER_BUTTON; 3586a46c0ec8Sopenharmony_ci 3587a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3588a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3589a46c0ec8Sopenharmony_ci ptrev = libinput_event_get_pointer_event(event); 3590a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_pointer_get_button(ptrev), 3591a46c0ec8Sopenharmony_ci button); 3592a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_pointer_get_button_state(ptrev), 3593a46c0ec8Sopenharmony_ci state); 3594a46c0ec8Sopenharmony_ci 3595a46c0ec8Sopenharmony_ci return ptrev; 3596a46c0ec8Sopenharmony_ci} 3597a46c0ec8Sopenharmony_ci 3598a46c0ec8Sopenharmony_cistruct libinput_event_pointer * 3599a46c0ec8Sopenharmony_cilitest_is_axis_event(struct libinput_event *event, 3600a46c0ec8Sopenharmony_ci enum libinput_event_type axis_type, 3601a46c0ec8Sopenharmony_ci enum libinput_pointer_axis axis, 3602a46c0ec8Sopenharmony_ci enum libinput_pointer_axis_source source) 3603a46c0ec8Sopenharmony_ci{ 3604a46c0ec8Sopenharmony_ci struct libinput_event_pointer *ptrev; 3605a46c0ec8Sopenharmony_ci 3606a46c0ec8Sopenharmony_ci litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || 3607a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || 3608a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); 3609a46c0ec8Sopenharmony_ci 3610a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3611a46c0ec8Sopenharmony_ci litest_assert_event_type_is_one_of(event, 3612a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_AXIS, 3613a46c0ec8Sopenharmony_ci axis_type); 3614a46c0ec8Sopenharmony_ci ptrev = libinput_event_get_pointer_event(event); 3615a46c0ec8Sopenharmony_ci litest_assert(libinput_event_pointer_has_axis(ptrev, axis)); 3616a46c0ec8Sopenharmony_ci 3617a46c0ec8Sopenharmony_ci if (source != 0) 3618a46c0ec8Sopenharmony_ci litest_assert_int_eq(litest_event_pointer_get_axis_source(ptrev), 3619a46c0ec8Sopenharmony_ci source); 3620a46c0ec8Sopenharmony_ci 3621a46c0ec8Sopenharmony_ci return ptrev; 3622a46c0ec8Sopenharmony_ci} 3623a46c0ec8Sopenharmony_ci 3624a46c0ec8Sopenharmony_cibool 3625a46c0ec8Sopenharmony_cilitest_is_high_res_axis_event(struct libinput_event *event) 3626a46c0ec8Sopenharmony_ci{ 3627a46c0ec8Sopenharmony_ci litest_assert_event_type_is_one_of(event, 3628a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_AXIS, 3629a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_SCROLL_WHEEL, 3630a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_SCROLL_FINGER, 3631a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); 3632a46c0ec8Sopenharmony_ci 3633a46c0ec8Sopenharmony_ci return (libinput_event_get_type(event) != LIBINPUT_EVENT_POINTER_AXIS); 3634a46c0ec8Sopenharmony_ci} 3635a46c0ec8Sopenharmony_ci 3636a46c0ec8Sopenharmony_cistruct libinput_event_pointer * 3637a46c0ec8Sopenharmony_cilitest_is_motion_event(struct libinput_event *event) 3638a46c0ec8Sopenharmony_ci{ 3639a46c0ec8Sopenharmony_ci struct libinput_event_pointer *ptrev; 3640a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_POINTER_MOTION; 3641a46c0ec8Sopenharmony_ci double x, y, ux, uy; 3642a46c0ec8Sopenharmony_ci 3643a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3644a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3645a46c0ec8Sopenharmony_ci ptrev = libinput_event_get_pointer_event(event); 3646a46c0ec8Sopenharmony_ci 3647a46c0ec8Sopenharmony_ci x = libinput_event_pointer_get_dx(ptrev); 3648a46c0ec8Sopenharmony_ci y = libinput_event_pointer_get_dy(ptrev); 3649a46c0ec8Sopenharmony_ci ux = libinput_event_pointer_get_dx_unaccelerated(ptrev); 3650a46c0ec8Sopenharmony_ci uy = libinput_event_pointer_get_dy_unaccelerated(ptrev); 3651a46c0ec8Sopenharmony_ci 3652a46c0ec8Sopenharmony_ci /* No 0 delta motion events */ 3653a46c0ec8Sopenharmony_ci litest_assert(x != 0.0 || y != 0.0 || 3654a46c0ec8Sopenharmony_ci ux != 0.0 || uy != 0.0); 3655a46c0ec8Sopenharmony_ci 3656a46c0ec8Sopenharmony_ci return ptrev; 3657a46c0ec8Sopenharmony_ci} 3658a46c0ec8Sopenharmony_ci 3659a46c0ec8Sopenharmony_civoid 3660a46c0ec8Sopenharmony_cilitest_assert_key_event(struct libinput *li, unsigned int key, 3661a46c0ec8Sopenharmony_ci enum libinput_key_state state) 3662a46c0ec8Sopenharmony_ci{ 3663a46c0ec8Sopenharmony_ci struct libinput_event *event; 3664a46c0ec8Sopenharmony_ci 3665a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3666a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3667a46c0ec8Sopenharmony_ci 3668a46c0ec8Sopenharmony_ci litest_is_keyboard_event(event, key, state); 3669a46c0ec8Sopenharmony_ci 3670a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3671a46c0ec8Sopenharmony_ci} 3672a46c0ec8Sopenharmony_ci 3673a46c0ec8Sopenharmony_civoid 3674a46c0ec8Sopenharmony_cilitest_assert_button_event(struct libinput *li, unsigned int button, 3675a46c0ec8Sopenharmony_ci enum libinput_button_state state) 3676a46c0ec8Sopenharmony_ci{ 3677a46c0ec8Sopenharmony_ci struct libinput_event *event; 3678a46c0ec8Sopenharmony_ci 3679a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3680a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3681a46c0ec8Sopenharmony_ci 3682a46c0ec8Sopenharmony_ci litest_is_button_event(event, button, state); 3683a46c0ec8Sopenharmony_ci 3684a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3685a46c0ec8Sopenharmony_ci} 3686a46c0ec8Sopenharmony_ci 3687a46c0ec8Sopenharmony_cistruct libinput_event_touch * 3688a46c0ec8Sopenharmony_cilitest_is_touch_event(struct libinput_event *event, 3689a46c0ec8Sopenharmony_ci enum libinput_event_type type) 3690a46c0ec8Sopenharmony_ci{ 3691a46c0ec8Sopenharmony_ci struct libinput_event_touch *touch; 3692a46c0ec8Sopenharmony_ci 3693a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3694a46c0ec8Sopenharmony_ci 3695a46c0ec8Sopenharmony_ci if (type == 0) 3696a46c0ec8Sopenharmony_ci type = libinput_event_get_type(event); 3697a46c0ec8Sopenharmony_ci 3698a46c0ec8Sopenharmony_ci switch (type) { 3699a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_DOWN: 3700a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_UP: 3701a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_MOTION: 3702a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_FRAME: 3703a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_TOUCH_CANCEL: 3704a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3705a46c0ec8Sopenharmony_ci break; 3706a46c0ec8Sopenharmony_ci default: 3707a46c0ec8Sopenharmony_ci ck_abort_msg("%s: invalid touch type %d\n", __func__, type); 3708a46c0ec8Sopenharmony_ci } 3709a46c0ec8Sopenharmony_ci 3710a46c0ec8Sopenharmony_ci touch = libinput_event_get_touch_event(event); 3711a46c0ec8Sopenharmony_ci 3712a46c0ec8Sopenharmony_ci return touch; 3713a46c0ec8Sopenharmony_ci} 3714a46c0ec8Sopenharmony_ci 3715a46c0ec8Sopenharmony_cistruct libinput_event_keyboard * 3716a46c0ec8Sopenharmony_cilitest_is_keyboard_event(struct libinput_event *event, 3717a46c0ec8Sopenharmony_ci unsigned int key, 3718a46c0ec8Sopenharmony_ci enum libinput_key_state state) 3719a46c0ec8Sopenharmony_ci{ 3720a46c0ec8Sopenharmony_ci struct libinput_event_keyboard *kevent; 3721a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_KEYBOARD_KEY; 3722a46c0ec8Sopenharmony_ci 3723a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3724a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3725a46c0ec8Sopenharmony_ci 3726a46c0ec8Sopenharmony_ci kevent = libinput_event_get_keyboard_event(event); 3727a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(kevent); 3728a46c0ec8Sopenharmony_ci 3729a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_keyboard_get_key(kevent), key); 3730a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_keyboard_get_key_state(kevent), 3731a46c0ec8Sopenharmony_ci state); 3732a46c0ec8Sopenharmony_ci return kevent; 3733a46c0ec8Sopenharmony_ci} 3734a46c0ec8Sopenharmony_ci 3735a46c0ec8Sopenharmony_cistruct libinput_event_gesture * 3736a46c0ec8Sopenharmony_cilitest_is_gesture_event(struct libinput_event *event, 3737a46c0ec8Sopenharmony_ci enum libinput_event_type type, 3738a46c0ec8Sopenharmony_ci int nfingers) 3739a46c0ec8Sopenharmony_ci{ 3740a46c0ec8Sopenharmony_ci struct libinput_event_gesture *gevent; 3741a46c0ec8Sopenharmony_ci 3742a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3743a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3744a46c0ec8Sopenharmony_ci 3745a46c0ec8Sopenharmony_ci gevent = libinput_event_get_gesture_event(event); 3746a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(gevent); 3747a46c0ec8Sopenharmony_ci 3748a46c0ec8Sopenharmony_ci if (nfingers != -1) 3749a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_gesture_get_finger_count(gevent), 3750a46c0ec8Sopenharmony_ci nfingers); 3751a46c0ec8Sopenharmony_ci return gevent; 3752a46c0ec8Sopenharmony_ci} 3753a46c0ec8Sopenharmony_ci 3754a46c0ec8Sopenharmony_civoid 3755a46c0ec8Sopenharmony_cilitest_assert_gesture_event(struct libinput *li, 3756a46c0ec8Sopenharmony_ci enum libinput_event_type type, 3757a46c0ec8Sopenharmony_ci int nfingers) 3758a46c0ec8Sopenharmony_ci{ 3759a46c0ec8Sopenharmony_ci struct libinput_event *event; 3760a46c0ec8Sopenharmony_ci 3761a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3762a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3763a46c0ec8Sopenharmony_ci 3764a46c0ec8Sopenharmony_ci litest_is_gesture_event(event, type, nfingers); 3765a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3766a46c0ec8Sopenharmony_ci} 3767a46c0ec8Sopenharmony_ci 3768a46c0ec8Sopenharmony_cistruct libinput_event_tablet_tool * 3769a46c0ec8Sopenharmony_cilitest_is_tablet_event(struct libinput_event *event, 3770a46c0ec8Sopenharmony_ci enum libinput_event_type type) 3771a46c0ec8Sopenharmony_ci{ 3772a46c0ec8Sopenharmony_ci struct libinput_event_tablet_tool *tevent; 3773a46c0ec8Sopenharmony_ci 3774a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3775a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3776a46c0ec8Sopenharmony_ci 3777a46c0ec8Sopenharmony_ci tevent = libinput_event_get_tablet_tool_event(event); 3778a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(tevent); 3779a46c0ec8Sopenharmony_ci 3780a46c0ec8Sopenharmony_ci return tevent; 3781a46c0ec8Sopenharmony_ci} 3782a46c0ec8Sopenharmony_ci 3783a46c0ec8Sopenharmony_civoid 3784a46c0ec8Sopenharmony_cilitest_assert_tablet_button_event(struct libinput *li, unsigned int button, 3785a46c0ec8Sopenharmony_ci enum libinput_button_state state) 3786a46c0ec8Sopenharmony_ci{ 3787a46c0ec8Sopenharmony_ci struct libinput_event *event; 3788a46c0ec8Sopenharmony_ci struct libinput_event_tablet_tool *tev; 3789a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_BUTTON; 3790a46c0ec8Sopenharmony_ci 3791a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3792a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3793a46c0ec8Sopenharmony_ci 3794a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 3795a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3796a46c0ec8Sopenharmony_ci tev = libinput_event_get_tablet_tool_event(event); 3797a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_tool_get_button(tev), 3798a46c0ec8Sopenharmony_ci button); 3799a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev), 3800a46c0ec8Sopenharmony_ci state); 3801a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3802a46c0ec8Sopenharmony_ci} 3803a46c0ec8Sopenharmony_ci 3804a46c0ec8Sopenharmony_ci 3805a46c0ec8Sopenharmony_cistruct libinput_event_tablet_tool * 3806a46c0ec8Sopenharmony_cilitest_is_proximity_event(struct libinput_event *event, 3807a46c0ec8Sopenharmony_ci enum libinput_tablet_tool_proximity_state state) 3808a46c0ec8Sopenharmony_ci{ 3809a46c0ec8Sopenharmony_ci struct libinput_event_tablet_tool *tev; 3810a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY; 3811a46c0ec8Sopenharmony_ci 3812a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 3813a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3814a46c0ec8Sopenharmony_ci tev = libinput_event_get_tablet_tool_event(event); 3815a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev), 3816a46c0ec8Sopenharmony_ci state); 3817a46c0ec8Sopenharmony_ci return tev; 3818a46c0ec8Sopenharmony_ci} 3819a46c0ec8Sopenharmony_ci 3820a46c0ec8Sopenharmony_cidouble 3821a46c0ec8Sopenharmony_cilitest_event_pointer_get_value(struct libinput_event_pointer *ptrev, 3822a46c0ec8Sopenharmony_ci enum libinput_pointer_axis axis) 3823a46c0ec8Sopenharmony_ci{ 3824a46c0ec8Sopenharmony_ci struct libinput_event *event; 3825a46c0ec8Sopenharmony_ci enum libinput_event_type type; 3826a46c0ec8Sopenharmony_ci 3827a46c0ec8Sopenharmony_ci event = libinput_event_pointer_get_base_event(ptrev); 3828a46c0ec8Sopenharmony_ci type = libinput_event_get_type(event); 3829a46c0ec8Sopenharmony_ci 3830a46c0ec8Sopenharmony_ci switch (type) { 3831a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_AXIS: 3832a46c0ec8Sopenharmony_ci return libinput_event_pointer_get_axis_value(ptrev, axis); 3833a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: 3834a46c0ec8Sopenharmony_ci return libinput_event_pointer_get_scroll_value_v120(ptrev, axis); 3835a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: 3836a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: 3837a46c0ec8Sopenharmony_ci return libinput_event_pointer_get_scroll_value(ptrev, axis); 3838a46c0ec8Sopenharmony_ci default: 3839a46c0ec8Sopenharmony_ci abort(); 3840a46c0ec8Sopenharmony_ci } 3841a46c0ec8Sopenharmony_ci} 3842a46c0ec8Sopenharmony_ci 3843a46c0ec8Sopenharmony_cienum libinput_pointer_axis_source 3844a46c0ec8Sopenharmony_cilitest_event_pointer_get_axis_source(struct libinput_event_pointer *ptrev) 3845a46c0ec8Sopenharmony_ci{ 3846a46c0ec8Sopenharmony_ci struct libinput_event *event; 3847a46c0ec8Sopenharmony_ci enum libinput_event_type type; 3848a46c0ec8Sopenharmony_ci 3849a46c0ec8Sopenharmony_ci event = libinput_event_pointer_get_base_event(ptrev); 3850a46c0ec8Sopenharmony_ci type = libinput_event_get_type(event); 3851a46c0ec8Sopenharmony_ci 3852a46c0ec8Sopenharmony_ci if (type == LIBINPUT_EVENT_POINTER_AXIS) 3853a46c0ec8Sopenharmony_ci return libinput_event_pointer_get_axis_source(ptrev); 3854a46c0ec8Sopenharmony_ci 3855a46c0ec8Sopenharmony_ci switch (type) { 3856a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL: 3857a46c0ec8Sopenharmony_ci return LIBINPUT_POINTER_AXIS_SOURCE_WHEEL; 3858a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_FINGER: 3859a46c0ec8Sopenharmony_ci return LIBINPUT_POINTER_AXIS_SOURCE_FINGER; 3860a46c0ec8Sopenharmony_ci case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS: 3861a46c0ec8Sopenharmony_ci return LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS; 3862a46c0ec8Sopenharmony_ci default: 3863a46c0ec8Sopenharmony_ci abort(); 3864a46c0ec8Sopenharmony_ci } 3865a46c0ec8Sopenharmony_ci} 3866a46c0ec8Sopenharmony_ci 3867a46c0ec8Sopenharmony_civoid litest_assert_tablet_proximity_event(struct libinput *li, 3868a46c0ec8Sopenharmony_ci enum libinput_tablet_tool_proximity_state state) 3869a46c0ec8Sopenharmony_ci{ 3870a46c0ec8Sopenharmony_ci struct libinput_event *event; 3871a46c0ec8Sopenharmony_ci 3872a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3873a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3874a46c0ec8Sopenharmony_ci litest_is_proximity_event(event, state); 3875a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3876a46c0ec8Sopenharmony_ci} 3877a46c0ec8Sopenharmony_ci 3878a46c0ec8Sopenharmony_civoid litest_assert_tablet_tip_event(struct libinput *li, 3879a46c0ec8Sopenharmony_ci enum libinput_tablet_tool_tip_state state) 3880a46c0ec8Sopenharmony_ci{ 3881a46c0ec8Sopenharmony_ci struct libinput_event *event; 3882a46c0ec8Sopenharmony_ci struct libinput_event_tablet_tool *tev; 3883a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_TOOL_TIP; 3884a46c0ec8Sopenharmony_ci 3885a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 3886a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 3887a46c0ec8Sopenharmony_ci 3888a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 3889a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3890a46c0ec8Sopenharmony_ci tev = libinput_event_get_tablet_tool_event(event); 3891a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tev), 3892a46c0ec8Sopenharmony_ci state); 3893a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 3894a46c0ec8Sopenharmony_ci} 3895a46c0ec8Sopenharmony_ci 3896a46c0ec8Sopenharmony_cistruct libinput_event_tablet_pad * 3897a46c0ec8Sopenharmony_cilitest_is_pad_button_event(struct libinput_event *event, 3898a46c0ec8Sopenharmony_ci unsigned int button, 3899a46c0ec8Sopenharmony_ci enum libinput_button_state state) 3900a46c0ec8Sopenharmony_ci{ 3901a46c0ec8Sopenharmony_ci struct libinput_event_tablet_pad *p; 3902a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON; 3903a46c0ec8Sopenharmony_ci 3904a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3905a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3906a46c0ec8Sopenharmony_ci 3907a46c0ec8Sopenharmony_ci p = libinput_event_get_tablet_pad_event(event); 3908a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(p); 3909a46c0ec8Sopenharmony_ci 3910a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_button_number(p), 3911a46c0ec8Sopenharmony_ci button); 3912a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_button_state(p), 3913a46c0ec8Sopenharmony_ci state); 3914a46c0ec8Sopenharmony_ci 3915a46c0ec8Sopenharmony_ci return p; 3916a46c0ec8Sopenharmony_ci} 3917a46c0ec8Sopenharmony_ci 3918a46c0ec8Sopenharmony_cistruct libinput_event_tablet_pad * 3919a46c0ec8Sopenharmony_cilitest_is_pad_ring_event(struct libinput_event *event, 3920a46c0ec8Sopenharmony_ci unsigned int number, 3921a46c0ec8Sopenharmony_ci enum libinput_tablet_pad_ring_axis_source source) 3922a46c0ec8Sopenharmony_ci{ 3923a46c0ec8Sopenharmony_ci struct libinput_event_tablet_pad *p; 3924a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING; 3925a46c0ec8Sopenharmony_ci 3926a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3927a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3928a46c0ec8Sopenharmony_ci p = libinput_event_get_tablet_pad_event(event); 3929a46c0ec8Sopenharmony_ci 3930a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p), 3931a46c0ec8Sopenharmony_ci number); 3932a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p), 3933a46c0ec8Sopenharmony_ci source); 3934a46c0ec8Sopenharmony_ci 3935a46c0ec8Sopenharmony_ci return p; 3936a46c0ec8Sopenharmony_ci} 3937a46c0ec8Sopenharmony_ci 3938a46c0ec8Sopenharmony_cistruct libinput_event_tablet_pad * 3939a46c0ec8Sopenharmony_cilitest_is_pad_strip_event(struct libinput_event *event, 3940a46c0ec8Sopenharmony_ci unsigned int number, 3941a46c0ec8Sopenharmony_ci enum libinput_tablet_pad_strip_axis_source source) 3942a46c0ec8Sopenharmony_ci{ 3943a46c0ec8Sopenharmony_ci struct libinput_event_tablet_pad *p; 3944a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP; 3945a46c0ec8Sopenharmony_ci 3946a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 3947a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3948a46c0ec8Sopenharmony_ci p = libinput_event_get_tablet_pad_event(event); 3949a46c0ec8Sopenharmony_ci 3950a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p), 3951a46c0ec8Sopenharmony_ci number); 3952a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p), 3953a46c0ec8Sopenharmony_ci source); 3954a46c0ec8Sopenharmony_ci 3955a46c0ec8Sopenharmony_ci return p; 3956a46c0ec8Sopenharmony_ci} 3957a46c0ec8Sopenharmony_ci 3958a46c0ec8Sopenharmony_cistruct libinput_event_tablet_pad * 3959a46c0ec8Sopenharmony_cilitest_is_pad_key_event(struct libinput_event *event, 3960a46c0ec8Sopenharmony_ci unsigned int key, 3961a46c0ec8Sopenharmony_ci enum libinput_key_state state) 3962a46c0ec8Sopenharmony_ci{ 3963a46c0ec8Sopenharmony_ci struct libinput_event_tablet_pad *p; 3964a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_KEY; 3965a46c0ec8Sopenharmony_ci 3966a46c0ec8Sopenharmony_ci litest_assert(event != NULL); 3967a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3968a46c0ec8Sopenharmony_ci 3969a46c0ec8Sopenharmony_ci p = libinput_event_get_tablet_pad_event(event); 3970a46c0ec8Sopenharmony_ci litest_assert(p != NULL); 3971a46c0ec8Sopenharmony_ci 3972a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_key(p), key); 3973a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_tablet_pad_get_key_state(p), 3974a46c0ec8Sopenharmony_ci state); 3975a46c0ec8Sopenharmony_ci 3976a46c0ec8Sopenharmony_ci return p; 3977a46c0ec8Sopenharmony_ci} 3978a46c0ec8Sopenharmony_ci 3979a46c0ec8Sopenharmony_cistruct libinput_event_switch * 3980a46c0ec8Sopenharmony_cilitest_is_switch_event(struct libinput_event *event, 3981a46c0ec8Sopenharmony_ci enum libinput_switch sw, 3982a46c0ec8Sopenharmony_ci enum libinput_switch_state state) 3983a46c0ec8Sopenharmony_ci{ 3984a46c0ec8Sopenharmony_ci struct libinput_event_switch *swev; 3985a46c0ec8Sopenharmony_ci enum libinput_event_type type = LIBINPUT_EVENT_SWITCH_TOGGLE; 3986a46c0ec8Sopenharmony_ci 3987a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 3988a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 3989a46c0ec8Sopenharmony_ci swev = libinput_event_get_switch_event(event); 3990a46c0ec8Sopenharmony_ci 3991a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_switch_get_switch(swev), sw); 3992a46c0ec8Sopenharmony_ci litest_assert_int_eq(libinput_event_switch_get_switch_state(swev), 3993a46c0ec8Sopenharmony_ci state); 3994a46c0ec8Sopenharmony_ci 3995a46c0ec8Sopenharmony_ci return swev; 3996a46c0ec8Sopenharmony_ci} 3997a46c0ec8Sopenharmony_ci 3998a46c0ec8Sopenharmony_civoid 3999a46c0ec8Sopenharmony_cilitest_assert_switch_event(struct libinput *li, 4000a46c0ec8Sopenharmony_ci enum libinput_switch sw, 4001a46c0ec8Sopenharmony_ci enum libinput_switch_state state) 4002a46c0ec8Sopenharmony_ci{ 4003a46c0ec8Sopenharmony_ci struct libinput_event *event; 4004a46c0ec8Sopenharmony_ci 4005a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 4006a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4007a46c0ec8Sopenharmony_ci 4008a46c0ec8Sopenharmony_ci litest_is_switch_event(event, sw, state); 4009a46c0ec8Sopenharmony_ci 4010a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4011a46c0ec8Sopenharmony_ci} 4012a46c0ec8Sopenharmony_ci 4013a46c0ec8Sopenharmony_civoid 4014a46c0ec8Sopenharmony_cilitest_assert_pad_button_event(struct libinput *li, 4015a46c0ec8Sopenharmony_ci unsigned int button, 4016a46c0ec8Sopenharmony_ci enum libinput_button_state state) 4017a46c0ec8Sopenharmony_ci{ 4018a46c0ec8Sopenharmony_ci struct libinput_event *event; 4019a46c0ec8Sopenharmony_ci 4020a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 4021a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4022a46c0ec8Sopenharmony_ci 4023a46c0ec8Sopenharmony_ci litest_is_pad_button_event(event, button, state); 4024a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4025a46c0ec8Sopenharmony_ci} 4026a46c0ec8Sopenharmony_ci 4027a46c0ec8Sopenharmony_civoid 4028a46c0ec8Sopenharmony_cilitest_assert_pad_key_event(struct libinput *li, 4029a46c0ec8Sopenharmony_ci unsigned int key, 4030a46c0ec8Sopenharmony_ci enum libinput_key_state state) 4031a46c0ec8Sopenharmony_ci{ 4032a46c0ec8Sopenharmony_ci struct libinput_event *event; 4033a46c0ec8Sopenharmony_ci 4034a46c0ec8Sopenharmony_ci litest_wait_for_event(li); 4035a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4036a46c0ec8Sopenharmony_ci 4037a46c0ec8Sopenharmony_ci litest_is_pad_key_event(event, key, state); 4038a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4039a46c0ec8Sopenharmony_ci} 4040a46c0ec8Sopenharmony_ci 4041a46c0ec8Sopenharmony_civoid 4042a46c0ec8Sopenharmony_cilitest_assert_scroll(struct libinput *li, 4043a46c0ec8Sopenharmony_ci enum libinput_event_type axis_type, 4044a46c0ec8Sopenharmony_ci enum libinput_pointer_axis axis, 4045a46c0ec8Sopenharmony_ci int minimum_movement) 4046a46c0ec8Sopenharmony_ci{ 4047a46c0ec8Sopenharmony_ci struct libinput_event *event; 4048a46c0ec8Sopenharmony_ci struct libinput_event_pointer *ptrev; 4049a46c0ec8Sopenharmony_ci bool last_hi_res_event_found, last_low_res_event_found; 4050a46c0ec8Sopenharmony_ci int value; 4051a46c0ec8Sopenharmony_ci int nevents = 0; 4052a46c0ec8Sopenharmony_ci 4053a46c0ec8Sopenharmony_ci litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || 4054a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || 4055a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); 4056a46c0ec8Sopenharmony_ci 4057a46c0ec8Sopenharmony_ci last_hi_res_event_found = false; 4058a46c0ec8Sopenharmony_ci last_low_res_event_found = false; 4059a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4060a46c0ec8Sopenharmony_ci litest_assert_ptr_notnull(event); 4061a46c0ec8Sopenharmony_ci 4062a46c0ec8Sopenharmony_ci while (event) { 4063a46c0ec8Sopenharmony_ci int min = minimum_movement; 4064a46c0ec8Sopenharmony_ci 4065a46c0ec8Sopenharmony_ci ptrev = litest_is_axis_event(event, axis_type, axis, 0); 4066a46c0ec8Sopenharmony_ci nevents++; 4067a46c0ec8Sopenharmony_ci 4068a46c0ec8Sopenharmony_ci /* Due to how the hysteresis works on touchpad 4069a46c0ec8Sopenharmony_ci * events, the first event is reduced by the 4070a46c0ec8Sopenharmony_ci * hysteresis margin that can cause the first event 4071a46c0ec8Sopenharmony_ci * go under the minimum we expect for all other 4072a46c0ec8Sopenharmony_ci * events */ 4073a46c0ec8Sopenharmony_ci if (nevents == 1) 4074a46c0ec8Sopenharmony_ci min = minimum_movement/2; 4075a46c0ec8Sopenharmony_ci 4076a46c0ec8Sopenharmony_ci value = litest_event_pointer_get_value(ptrev, axis); 4077a46c0ec8Sopenharmony_ci if (litest_is_high_res_axis_event(event)) { 4078a46c0ec8Sopenharmony_ci litest_assert(!last_hi_res_event_found); 4079a46c0ec8Sopenharmony_ci 4080a46c0ec8Sopenharmony_ci if (axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL) 4081a46c0ec8Sopenharmony_ci min *= 120; 4082a46c0ec8Sopenharmony_ci 4083a46c0ec8Sopenharmony_ci if (value == 0) 4084a46c0ec8Sopenharmony_ci last_hi_res_event_found = true; 4085a46c0ec8Sopenharmony_ci } else { 4086a46c0ec8Sopenharmony_ci litest_assert(!last_low_res_event_found); 4087a46c0ec8Sopenharmony_ci 4088a46c0ec8Sopenharmony_ci if (value == 0) 4089a46c0ec8Sopenharmony_ci last_low_res_event_found = true; 4090a46c0ec8Sopenharmony_ci } 4091a46c0ec8Sopenharmony_ci 4092a46c0ec8Sopenharmony_ci if (value != 0) { 4093a46c0ec8Sopenharmony_ci if (minimum_movement > 0) 4094a46c0ec8Sopenharmony_ci litest_assert_int_ge(value, min); 4095a46c0ec8Sopenharmony_ci else 4096a46c0ec8Sopenharmony_ci litest_assert_int_le(value, min); 4097a46c0ec8Sopenharmony_ci } 4098a46c0ec8Sopenharmony_ci 4099a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4100a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4101a46c0ec8Sopenharmony_ci } 4102a46c0ec8Sopenharmony_ci 4103a46c0ec8Sopenharmony_ci litest_assert(last_low_res_event_found); 4104a46c0ec8Sopenharmony_ci litest_assert(last_hi_res_event_found); 4105a46c0ec8Sopenharmony_ci} 4106a46c0ec8Sopenharmony_ci 4107a46c0ec8Sopenharmony_civoid 4108a46c0ec8Sopenharmony_cilitest_assert_axis_end_sequence(struct libinput *li, 4109a46c0ec8Sopenharmony_ci enum libinput_event_type axis_type, 4110a46c0ec8Sopenharmony_ci enum libinput_pointer_axis axis, 4111a46c0ec8Sopenharmony_ci enum libinput_pointer_axis_source source) 4112a46c0ec8Sopenharmony_ci{ 4113a46c0ec8Sopenharmony_ci struct libinput_event *event; 4114a46c0ec8Sopenharmony_ci struct libinput_event_pointer *ptrev; 4115a46c0ec8Sopenharmony_ci bool last_hi_res_event_found, last_low_res_event_found; 4116a46c0ec8Sopenharmony_ci double val; 4117a46c0ec8Sopenharmony_ci int i; 4118a46c0ec8Sopenharmony_ci 4119a46c0ec8Sopenharmony_ci litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || 4120a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || 4121a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); 4122a46c0ec8Sopenharmony_ci 4123a46c0ec8Sopenharmony_ci last_hi_res_event_found = false; 4124a46c0ec8Sopenharmony_ci last_low_res_event_found = false; 4125a46c0ec8Sopenharmony_ci 4126a46c0ec8Sopenharmony_ci /* both high and low scroll end events must be sent */ 4127a46c0ec8Sopenharmony_ci for (i = 0; i < 2; i++) { 4128a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4129a46c0ec8Sopenharmony_ci ptrev = litest_is_axis_event(event, axis_type, axis, source); 4130a46c0ec8Sopenharmony_ci val = litest_event_pointer_get_value(ptrev, axis); 4131a46c0ec8Sopenharmony_ci ck_assert(val == 0.0); 4132a46c0ec8Sopenharmony_ci 4133a46c0ec8Sopenharmony_ci if (litest_is_high_res_axis_event(event)) { 4134a46c0ec8Sopenharmony_ci litest_assert(!last_hi_res_event_found); 4135a46c0ec8Sopenharmony_ci last_hi_res_event_found = true; 4136a46c0ec8Sopenharmony_ci } else { 4137a46c0ec8Sopenharmony_ci litest_assert(!last_low_res_event_found); 4138a46c0ec8Sopenharmony_ci last_low_res_event_found = true; 4139a46c0ec8Sopenharmony_ci } 4140a46c0ec8Sopenharmony_ci 4141a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4142a46c0ec8Sopenharmony_ci } 4143a46c0ec8Sopenharmony_ci 4144a46c0ec8Sopenharmony_ci litest_assert(last_low_res_event_found); 4145a46c0ec8Sopenharmony_ci litest_assert(last_hi_res_event_found); 4146a46c0ec8Sopenharmony_ci} 4147a46c0ec8Sopenharmony_ci 4148a46c0ec8Sopenharmony_civoid 4149a46c0ec8Sopenharmony_cilitest_assert_only_typed_events(struct libinput *li, 4150a46c0ec8Sopenharmony_ci enum libinput_event_type type) 4151a46c0ec8Sopenharmony_ci{ 4152a46c0ec8Sopenharmony_ci struct libinput_event *event; 4153a46c0ec8Sopenharmony_ci 4154a46c0ec8Sopenharmony_ci litest_assert(type != LIBINPUT_EVENT_NONE); 4155a46c0ec8Sopenharmony_ci 4156a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4157a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4158a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 4159a46c0ec8Sopenharmony_ci 4160a46c0ec8Sopenharmony_ci while (event) { 4161a46c0ec8Sopenharmony_ci litest_assert_event_type(event, type); 4162a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4163a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4164a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4165a46c0ec8Sopenharmony_ci } 4166a46c0ec8Sopenharmony_ci} 4167a46c0ec8Sopenharmony_ci 4168a46c0ec8Sopenharmony_civoid 4169a46c0ec8Sopenharmony_cilitest_assert_only_axis_events(struct libinput *li, 4170a46c0ec8Sopenharmony_ci enum libinput_event_type axis_type) 4171a46c0ec8Sopenharmony_ci{ 4172a46c0ec8Sopenharmony_ci struct libinput_event *event; 4173a46c0ec8Sopenharmony_ci 4174a46c0ec8Sopenharmony_ci litest_assert(axis_type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL || 4175a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_FINGER || 4176a46c0ec8Sopenharmony_ci axis_type == LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS); 4177a46c0ec8Sopenharmony_ci 4178a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4179a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4180a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 4181a46c0ec8Sopenharmony_ci 4182a46c0ec8Sopenharmony_ci while (event) { 4183a46c0ec8Sopenharmony_ci litest_assert_event_type_is_one_of(event, 4184a46c0ec8Sopenharmony_ci LIBINPUT_EVENT_POINTER_AXIS, 4185a46c0ec8Sopenharmony_ci axis_type); 4186a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4187a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4188a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4189a46c0ec8Sopenharmony_ci } 4190a46c0ec8Sopenharmony_ci} 4191a46c0ec8Sopenharmony_ci 4192a46c0ec8Sopenharmony_civoid 4193a46c0ec8Sopenharmony_cilitest_assert_no_typed_events(struct libinput *li, 4194a46c0ec8Sopenharmony_ci enum libinput_event_type type) 4195a46c0ec8Sopenharmony_ci{ 4196a46c0ec8Sopenharmony_ci struct libinput_event *event; 4197a46c0ec8Sopenharmony_ci 4198a46c0ec8Sopenharmony_ci litest_assert(type != LIBINPUT_EVENT_NONE); 4199a46c0ec8Sopenharmony_ci 4200a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4201a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4202a46c0ec8Sopenharmony_ci 4203a46c0ec8Sopenharmony_ci while (event) { 4204a46c0ec8Sopenharmony_ci litest_assert_int_ne(libinput_event_get_type(event), 4205a46c0ec8Sopenharmony_ci type); 4206a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4207a46c0ec8Sopenharmony_ci libinput_dispatch(li); 4208a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4209a46c0ec8Sopenharmony_ci } 4210a46c0ec8Sopenharmony_ci} 4211a46c0ec8Sopenharmony_ci 4212a46c0ec8Sopenharmony_civoid 4213a46c0ec8Sopenharmony_cilitest_assert_touch_sequence(struct libinput *li) 4214a46c0ec8Sopenharmony_ci{ 4215a46c0ec8Sopenharmony_ci struct libinput_event *event; 4216a46c0ec8Sopenharmony_ci struct libinput_event_touch *tev; 4217a46c0ec8Sopenharmony_ci int slot; 4218a46c0ec8Sopenharmony_ci 4219a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4220a46c0ec8Sopenharmony_ci tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN); 4221a46c0ec8Sopenharmony_ci slot = libinput_event_touch_get_slot(tev); 4222a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4223a46c0ec8Sopenharmony_ci 4224a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4225a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4226a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4227a46c0ec8Sopenharmony_ci 4228a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4229a46c0ec8Sopenharmony_ci do { 4230a46c0ec8Sopenharmony_ci tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION); 4231a46c0ec8Sopenharmony_ci litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev)); 4232a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4233a46c0ec8Sopenharmony_ci 4234a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4235a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4236a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4237a46c0ec8Sopenharmony_ci 4238a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4239a46c0ec8Sopenharmony_ci litest_assert_notnull(event); 4240a46c0ec8Sopenharmony_ci } while (libinput_event_get_type(event) != LIBINPUT_EVENT_TOUCH_UP); 4241a46c0ec8Sopenharmony_ci 4242a46c0ec8Sopenharmony_ci tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP); 4243a46c0ec8Sopenharmony_ci litest_assert_int_eq(slot, libinput_event_touch_get_slot(tev)); 4244a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4245a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4246a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4247a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4248a46c0ec8Sopenharmony_ci} 4249a46c0ec8Sopenharmony_ci 4250a46c0ec8Sopenharmony_civoid 4251a46c0ec8Sopenharmony_cilitest_assert_touch_motion_frame(struct libinput *li) 4252a46c0ec8Sopenharmony_ci{ 4253a46c0ec8Sopenharmony_ci struct libinput_event *event; 4254a46c0ec8Sopenharmony_ci 4255a46c0ec8Sopenharmony_ci /* expect at least one, but maybe more */ 4256a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4257a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION); 4258a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4259a46c0ec8Sopenharmony_ci 4260a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4261a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4262a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4263a46c0ec8Sopenharmony_ci 4264a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4265a46c0ec8Sopenharmony_ci while (event) { 4266a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_MOTION); 4267a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4268a46c0ec8Sopenharmony_ci 4269a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4270a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4271a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4272a46c0ec8Sopenharmony_ci 4273a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4274a46c0ec8Sopenharmony_ci } 4275a46c0ec8Sopenharmony_ci} 4276a46c0ec8Sopenharmony_ci 4277a46c0ec8Sopenharmony_civoid 4278a46c0ec8Sopenharmony_cilitest_assert_touch_down_frame(struct libinput *li) 4279a46c0ec8Sopenharmony_ci{ 4280a46c0ec8Sopenharmony_ci struct libinput_event *event; 4281a46c0ec8Sopenharmony_ci 4282a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4283a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN); 4284a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4285a46c0ec8Sopenharmony_ci 4286a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4287a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4288a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4289a46c0ec8Sopenharmony_ci} 4290a46c0ec8Sopenharmony_ci 4291a46c0ec8Sopenharmony_civoid 4292a46c0ec8Sopenharmony_cilitest_assert_touch_up_frame(struct libinput *li) 4293a46c0ec8Sopenharmony_ci{ 4294a46c0ec8Sopenharmony_ci struct libinput_event *event; 4295a46c0ec8Sopenharmony_ci 4296a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4297a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_UP); 4298a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4299a46c0ec8Sopenharmony_ci 4300a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4301a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4302a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4303a46c0ec8Sopenharmony_ci} 4304a46c0ec8Sopenharmony_ci 4305a46c0ec8Sopenharmony_civoid 4306a46c0ec8Sopenharmony_cilitest_assert_touch_cancel(struct libinput *li) 4307a46c0ec8Sopenharmony_ci{ 4308a46c0ec8Sopenharmony_ci struct libinput_event *event; 4309a46c0ec8Sopenharmony_ci 4310a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4311a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_CANCEL); 4312a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4313a46c0ec8Sopenharmony_ci 4314a46c0ec8Sopenharmony_ci event = libinput_get_event(li); 4315a46c0ec8Sopenharmony_ci litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_FRAME); 4316a46c0ec8Sopenharmony_ci libinput_event_destroy(event); 4317a46c0ec8Sopenharmony_ci} 4318a46c0ec8Sopenharmony_ci 4319a46c0ec8Sopenharmony_civoid 4320a46c0ec8Sopenharmony_cilitest_timeout_tap(void) 4321a46c0ec8Sopenharmony_ci{ 4322a46c0ec8Sopenharmony_ci msleep(300); 4323a46c0ec8Sopenharmony_ci} 4324a46c0ec8Sopenharmony_ci 4325a46c0ec8Sopenharmony_civoid 4326a46c0ec8Sopenharmony_cilitest_timeout_tapndrag(void) 4327a46c0ec8Sopenharmony_ci{ 4328a46c0ec8Sopenharmony_ci msleep(520); 4329a46c0ec8Sopenharmony_ci} 4330a46c0ec8Sopenharmony_ci 4331a46c0ec8Sopenharmony_civoid 4332a46c0ec8Sopenharmony_cilitest_timeout_debounce(void) 4333a46c0ec8Sopenharmony_ci{ 4334a46c0ec8Sopenharmony_ci msleep(30); 4335a46c0ec8Sopenharmony_ci} 4336a46c0ec8Sopenharmony_ci 4337a46c0ec8Sopenharmony_civoid 4338a46c0ec8Sopenharmony_cilitest_timeout_softbuttons(void) 4339a46c0ec8Sopenharmony_ci{ 4340a46c0ec8Sopenharmony_ci msleep(300); 4341a46c0ec8Sopenharmony_ci} 4342a46c0ec8Sopenharmony_ci 4343a46c0ec8Sopenharmony_civoid 4344a46c0ec8Sopenharmony_cilitest_timeout_buttonscroll(void) 4345a46c0ec8Sopenharmony_ci{ 4346a46c0ec8Sopenharmony_ci msleep(300); 4347a46c0ec8Sopenharmony_ci} 4348a46c0ec8Sopenharmony_ci 4349a46c0ec8Sopenharmony_civoid 4350a46c0ec8Sopenharmony_cilitest_timeout_finger_switch(void) 4351a46c0ec8Sopenharmony_ci{ 4352a46c0ec8Sopenharmony_ci msleep(120); 4353a46c0ec8Sopenharmony_ci} 4354a46c0ec8Sopenharmony_ci 4355a46c0ec8Sopenharmony_civoid 4356a46c0ec8Sopenharmony_cilitest_timeout_wheel_scroll(void) 4357a46c0ec8Sopenharmony_ci{ 4358a46c0ec8Sopenharmony_ci msleep(600); 4359a46c0ec8Sopenharmony_ci} 4360a46c0ec8Sopenharmony_ci 4361a46c0ec8Sopenharmony_civoid 4362a46c0ec8Sopenharmony_cilitest_timeout_edgescroll(void) 4363a46c0ec8Sopenharmony_ci{ 4364a46c0ec8Sopenharmony_ci msleep(300); 4365a46c0ec8Sopenharmony_ci} 4366a46c0ec8Sopenharmony_ci 4367a46c0ec8Sopenharmony_civoid 4368a46c0ec8Sopenharmony_cilitest_timeout_middlebutton(void) 4369a46c0ec8Sopenharmony_ci{ 4370a46c0ec8Sopenharmony_ci msleep(70); 4371a46c0ec8Sopenharmony_ci} 4372a46c0ec8Sopenharmony_ci 4373a46c0ec8Sopenharmony_civoid 4374a46c0ec8Sopenharmony_cilitest_timeout_dwt_short(void) 4375a46c0ec8Sopenharmony_ci{ 4376a46c0ec8Sopenharmony_ci msleep(220); 4377a46c0ec8Sopenharmony_ci} 4378a46c0ec8Sopenharmony_ci 4379a46c0ec8Sopenharmony_civoid 4380a46c0ec8Sopenharmony_cilitest_timeout_dwt_long(void) 4381a46c0ec8Sopenharmony_ci{ 4382a46c0ec8Sopenharmony_ci msleep(520); 4383a46c0ec8Sopenharmony_ci} 4384a46c0ec8Sopenharmony_ci 4385a46c0ec8Sopenharmony_civoid 4386a46c0ec8Sopenharmony_cilitest_timeout_gesture(void) 4387a46c0ec8Sopenharmony_ci{ 4388a46c0ec8Sopenharmony_ci msleep(120); 4389a46c0ec8Sopenharmony_ci} 4390a46c0ec8Sopenharmony_ci 4391a46c0ec8Sopenharmony_civoid 4392a46c0ec8Sopenharmony_cilitest_timeout_gesture_scroll(void) 4393a46c0ec8Sopenharmony_ci{ 4394a46c0ec8Sopenharmony_ci msleep(180); 4395a46c0ec8Sopenharmony_ci} 4396a46c0ec8Sopenharmony_ci 4397a46c0ec8Sopenharmony_civoid 4398a46c0ec8Sopenharmony_cilitest_timeout_gesture_hold(void) 4399a46c0ec8Sopenharmony_ci{ 4400a46c0ec8Sopenharmony_ci msleep(300); 4401a46c0ec8Sopenharmony_ci} 4402a46c0ec8Sopenharmony_ci 4403a46c0ec8Sopenharmony_civoid 4404a46c0ec8Sopenharmony_cilitest_timeout_gesture_quick_hold(void) 4405a46c0ec8Sopenharmony_ci{ 4406a46c0ec8Sopenharmony_ci msleep(60); 4407a46c0ec8Sopenharmony_ci} 4408a46c0ec8Sopenharmony_ci 4409a46c0ec8Sopenharmony_civoid 4410a46c0ec8Sopenharmony_cilitest_timeout_trackpoint(void) 4411a46c0ec8Sopenharmony_ci{ 4412a46c0ec8Sopenharmony_ci msleep(320); 4413a46c0ec8Sopenharmony_ci} 4414a46c0ec8Sopenharmony_ci 4415a46c0ec8Sopenharmony_civoid 4416a46c0ec8Sopenharmony_cilitest_timeout_tablet_proxout(void) 4417a46c0ec8Sopenharmony_ci{ 4418a46c0ec8Sopenharmony_ci msleep(170); 4419a46c0ec8Sopenharmony_ci} 4420a46c0ec8Sopenharmony_ci 4421a46c0ec8Sopenharmony_civoid 4422a46c0ec8Sopenharmony_cilitest_timeout_touch_arbitration(void) 4423a46c0ec8Sopenharmony_ci{ 4424a46c0ec8Sopenharmony_ci msleep(100); 4425a46c0ec8Sopenharmony_ci} 4426a46c0ec8Sopenharmony_ci 4427a46c0ec8Sopenharmony_civoid 4428a46c0ec8Sopenharmony_cilitest_timeout_hysteresis(void) 4429a46c0ec8Sopenharmony_ci{ 4430a46c0ec8Sopenharmony_ci msleep(90); 4431a46c0ec8Sopenharmony_ci} 4432a46c0ec8Sopenharmony_ci 4433a46c0ec8Sopenharmony_civoid 4434a46c0ec8Sopenharmony_cilitest_push_event_frame(struct litest_device *dev) 4435a46c0ec8Sopenharmony_ci{ 4436a46c0ec8Sopenharmony_ci litest_assert_int_ge(dev->skip_ev_syn, 0); 4437a46c0ec8Sopenharmony_ci dev->skip_ev_syn++; 4438a46c0ec8Sopenharmony_ci} 4439a46c0ec8Sopenharmony_ci 4440a46c0ec8Sopenharmony_civoid 4441a46c0ec8Sopenharmony_cilitest_pop_event_frame(struct litest_device *dev) 4442a46c0ec8Sopenharmony_ci{ 4443a46c0ec8Sopenharmony_ci litest_assert_int_gt(dev->skip_ev_syn, 0); 4444a46c0ec8Sopenharmony_ci dev->skip_ev_syn--; 4445a46c0ec8Sopenharmony_ci if (dev->skip_ev_syn == 0) 4446a46c0ec8Sopenharmony_ci litest_event(dev, EV_SYN, SYN_REPORT, 0); 4447a46c0ec8Sopenharmony_ci} 4448a46c0ec8Sopenharmony_ci 4449a46c0ec8Sopenharmony_civoid 4450a46c0ec8Sopenharmony_cilitest_filter_event(struct litest_device *dev, 4451a46c0ec8Sopenharmony_ci unsigned int type, 4452a46c0ec8Sopenharmony_ci unsigned int code) 4453a46c0ec8Sopenharmony_ci{ 4454a46c0ec8Sopenharmony_ci libevdev_disable_event_code(dev->evdev, type, code); 4455a46c0ec8Sopenharmony_ci} 4456a46c0ec8Sopenharmony_ci 4457a46c0ec8Sopenharmony_civoid 4458a46c0ec8Sopenharmony_cilitest_unfilter_event(struct litest_device *dev, 4459a46c0ec8Sopenharmony_ci unsigned int type, 4460a46c0ec8Sopenharmony_ci unsigned int code) 4461a46c0ec8Sopenharmony_ci{ 4462a46c0ec8Sopenharmony_ci /* would need an non-NULL argument for re-enabling, so simply abort 4463a46c0ec8Sopenharmony_ci * until we need to be more sophisticated */ 4464a46c0ec8Sopenharmony_ci litest_assert_int_ne(type, (unsigned int)EV_ABS); 4465a46c0ec8Sopenharmony_ci 4466a46c0ec8Sopenharmony_ci libevdev_enable_event_code(dev->evdev, type, code, NULL); 4467a46c0ec8Sopenharmony_ci} 4468a46c0ec8Sopenharmony_ci 4469a46c0ec8Sopenharmony_cistatic void 4470a46c0ec8Sopenharmony_cisend_abs_xy(struct litest_device *d, double x, double y) 4471a46c0ec8Sopenharmony_ci{ 4472a46c0ec8Sopenharmony_ci struct input_event e; 4473a46c0ec8Sopenharmony_ci int val; 4474a46c0ec8Sopenharmony_ci 4475a46c0ec8Sopenharmony_ci e.type = EV_ABS; 4476a46c0ec8Sopenharmony_ci e.code = ABS_X; 4477a46c0ec8Sopenharmony_ci e.value = LITEST_AUTO_ASSIGN; 4478a46c0ec8Sopenharmony_ci val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true); 4479a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_X, val); 4480a46c0ec8Sopenharmony_ci 4481a46c0ec8Sopenharmony_ci e.code = ABS_Y; 4482a46c0ec8Sopenharmony_ci val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true); 4483a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_Y, val); 4484a46c0ec8Sopenharmony_ci} 4485a46c0ec8Sopenharmony_ci 4486a46c0ec8Sopenharmony_cistatic void 4487a46c0ec8Sopenharmony_cisend_abs_mt_xy(struct litest_device *d, double x, double y) 4488a46c0ec8Sopenharmony_ci{ 4489a46c0ec8Sopenharmony_ci struct input_event e; 4490a46c0ec8Sopenharmony_ci int val; 4491a46c0ec8Sopenharmony_ci 4492a46c0ec8Sopenharmony_ci e.type = EV_ABS; 4493a46c0ec8Sopenharmony_ci e.code = ABS_MT_POSITION_X; 4494a46c0ec8Sopenharmony_ci e.value = LITEST_AUTO_ASSIGN; 4495a46c0ec8Sopenharmony_ci val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true); 4496a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_POSITION_X, val); 4497a46c0ec8Sopenharmony_ci 4498a46c0ec8Sopenharmony_ci e.code = ABS_MT_POSITION_Y; 4499a46c0ec8Sopenharmony_ci e.value = LITEST_AUTO_ASSIGN; 4500a46c0ec8Sopenharmony_ci val = litest_auto_assign_value(d, &e, 0, x, y, NULL, true); 4501a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_POSITION_Y, val); 4502a46c0ec8Sopenharmony_ci} 4503a46c0ec8Sopenharmony_ci 4504a46c0ec8Sopenharmony_civoid 4505a46c0ec8Sopenharmony_cilitest_semi_mt_touch_down(struct litest_device *d, 4506a46c0ec8Sopenharmony_ci struct litest_semi_mt *semi_mt, 4507a46c0ec8Sopenharmony_ci unsigned int slot, 4508a46c0ec8Sopenharmony_ci double x, double y) 4509a46c0ec8Sopenharmony_ci{ 4510a46c0ec8Sopenharmony_ci double t, l, r = 0, b = 0; /* top, left, right, bottom */ 4511a46c0ec8Sopenharmony_ci 4512a46c0ec8Sopenharmony_ci if (d->ntouches_down > 2 || slot > 1) 4513a46c0ec8Sopenharmony_ci return; 4514a46c0ec8Sopenharmony_ci 4515a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) { 4516a46c0ec8Sopenharmony_ci l = x; 4517a46c0ec8Sopenharmony_ci t = y; 4518a46c0ec8Sopenharmony_ci } else { 4519a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 4520a46c0ec8Sopenharmony_ci l = min(x, semi_mt->touches[other].x); 4521a46c0ec8Sopenharmony_ci t = min(y, semi_mt->touches[other].y); 4522a46c0ec8Sopenharmony_ci r = max(x, semi_mt->touches[other].x); 4523a46c0ec8Sopenharmony_ci b = max(y, semi_mt->touches[other].y); 4524a46c0ec8Sopenharmony_ci } 4525a46c0ec8Sopenharmony_ci 4526a46c0ec8Sopenharmony_ci send_abs_xy(d, l, t); 4527a46c0ec8Sopenharmony_ci 4528a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, 0); 4529a46c0ec8Sopenharmony_ci 4530a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) 4531a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id); 4532a46c0ec8Sopenharmony_ci 4533a46c0ec8Sopenharmony_ci send_abs_mt_xy(d, l, t); 4534a46c0ec8Sopenharmony_ci 4535a46c0ec8Sopenharmony_ci if (d->ntouches_down == 2) { 4536a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, 1); 4537a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, ++semi_mt->tracking_id); 4538a46c0ec8Sopenharmony_ci 4539a46c0ec8Sopenharmony_ci send_abs_mt_xy(d, r, b); 4540a46c0ec8Sopenharmony_ci } 4541a46c0ec8Sopenharmony_ci 4542a46c0ec8Sopenharmony_ci litest_event(d, EV_SYN, SYN_REPORT, 0); 4543a46c0ec8Sopenharmony_ci 4544a46c0ec8Sopenharmony_ci semi_mt->touches[slot].x = x; 4545a46c0ec8Sopenharmony_ci semi_mt->touches[slot].y = y; 4546a46c0ec8Sopenharmony_ci} 4547a46c0ec8Sopenharmony_ci 4548a46c0ec8Sopenharmony_civoid 4549a46c0ec8Sopenharmony_cilitest_semi_mt_touch_move(struct litest_device *d, 4550a46c0ec8Sopenharmony_ci struct litest_semi_mt *semi_mt, 4551a46c0ec8Sopenharmony_ci unsigned int slot, 4552a46c0ec8Sopenharmony_ci double x, double y) 4553a46c0ec8Sopenharmony_ci{ 4554a46c0ec8Sopenharmony_ci double t, l, r = 0, b = 0; /* top, left, right, bottom */ 4555a46c0ec8Sopenharmony_ci 4556a46c0ec8Sopenharmony_ci if (d->ntouches_down > 2 || slot > 1) 4557a46c0ec8Sopenharmony_ci return; 4558a46c0ec8Sopenharmony_ci 4559a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) { 4560a46c0ec8Sopenharmony_ci l = x; 4561a46c0ec8Sopenharmony_ci t = y; 4562a46c0ec8Sopenharmony_ci } else { 4563a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 4564a46c0ec8Sopenharmony_ci l = min(x, semi_mt->touches[other].x); 4565a46c0ec8Sopenharmony_ci t = min(y, semi_mt->touches[other].y); 4566a46c0ec8Sopenharmony_ci r = max(x, semi_mt->touches[other].x); 4567a46c0ec8Sopenharmony_ci b = max(y, semi_mt->touches[other].y); 4568a46c0ec8Sopenharmony_ci } 4569a46c0ec8Sopenharmony_ci 4570a46c0ec8Sopenharmony_ci send_abs_xy(d, l, t); 4571a46c0ec8Sopenharmony_ci 4572a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, 0); 4573a46c0ec8Sopenharmony_ci send_abs_mt_xy(d, l, t); 4574a46c0ec8Sopenharmony_ci 4575a46c0ec8Sopenharmony_ci if (d->ntouches_down == 2) { 4576a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, 1); 4577a46c0ec8Sopenharmony_ci send_abs_mt_xy(d, r, b); 4578a46c0ec8Sopenharmony_ci } 4579a46c0ec8Sopenharmony_ci 4580a46c0ec8Sopenharmony_ci litest_event(d, EV_SYN, SYN_REPORT, 0); 4581a46c0ec8Sopenharmony_ci 4582a46c0ec8Sopenharmony_ci semi_mt->touches[slot].x = x; 4583a46c0ec8Sopenharmony_ci semi_mt->touches[slot].y = y; 4584a46c0ec8Sopenharmony_ci} 4585a46c0ec8Sopenharmony_ci 4586a46c0ec8Sopenharmony_civoid 4587a46c0ec8Sopenharmony_cilitest_semi_mt_touch_up(struct litest_device *d, 4588a46c0ec8Sopenharmony_ci struct litest_semi_mt *semi_mt, 4589a46c0ec8Sopenharmony_ci unsigned int slot) 4590a46c0ec8Sopenharmony_ci{ 4591a46c0ec8Sopenharmony_ci /* note: ntouches_down is decreased before we get here */ 4592a46c0ec8Sopenharmony_ci if (d->ntouches_down >= 2 || slot > 1) 4593a46c0ec8Sopenharmony_ci return; 4594a46c0ec8Sopenharmony_ci 4595a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, d->ntouches_down); 4596a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_TRACKING_ID, -1); 4597a46c0ec8Sopenharmony_ci 4598a46c0ec8Sopenharmony_ci /* if we have one finger left, send x/y coords for that finger left. 4599a46c0ec8Sopenharmony_ci this is likely to happen with a real touchpad */ 4600a46c0ec8Sopenharmony_ci if (d->ntouches_down == 1) { 4601a46c0ec8Sopenharmony_ci int other = (slot + 1) % 2; 4602a46c0ec8Sopenharmony_ci send_abs_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y); 4603a46c0ec8Sopenharmony_ci litest_event(d, EV_ABS, ABS_MT_SLOT, 0); 4604a46c0ec8Sopenharmony_ci send_abs_mt_xy(d, semi_mt->touches[other].x, semi_mt->touches[other].y); 4605a46c0ec8Sopenharmony_ci } 4606a46c0ec8Sopenharmony_ci 4607a46c0ec8Sopenharmony_ci litest_event(d, EV_SYN, SYN_REPORT, 0); 4608a46c0ec8Sopenharmony_ci} 4609a46c0ec8Sopenharmony_ci 4610a46c0ec8Sopenharmony_cienum litest_mode { 4611a46c0ec8Sopenharmony_ci LITEST_MODE_ERROR, 4612a46c0ec8Sopenharmony_ci LITEST_MODE_TEST, 4613a46c0ec8Sopenharmony_ci LITEST_MODE_LIST, 4614a46c0ec8Sopenharmony_ci}; 4615a46c0ec8Sopenharmony_ci 4616a46c0ec8Sopenharmony_cistatic inline enum litest_mode 4617a46c0ec8Sopenharmony_cilitest_parse_argv(int argc, char **argv) 4618a46c0ec8Sopenharmony_ci{ 4619a46c0ec8Sopenharmony_ci enum { 4620a46c0ec8Sopenharmony_ci OPT_FILTER_TEST, 4621a46c0ec8Sopenharmony_ci OPT_FILTER_DEVICE, 4622a46c0ec8Sopenharmony_ci OPT_FILTER_GROUP, 4623a46c0ec8Sopenharmony_ci OPT_FILTER_DEVICELESS, 4624a46c0ec8Sopenharmony_ci OPT_XML_PREFIX, 4625a46c0ec8Sopenharmony_ci OPT_JOBS, 4626a46c0ec8Sopenharmony_ci OPT_LIST, 4627a46c0ec8Sopenharmony_ci OPT_VERBOSE, 4628a46c0ec8Sopenharmony_ci }; 4629a46c0ec8Sopenharmony_ci static const struct option opts[] = { 4630a46c0ec8Sopenharmony_ci { "filter-test", 1, 0, OPT_FILTER_TEST }, 4631a46c0ec8Sopenharmony_ci { "filter-device", 1, 0, OPT_FILTER_DEVICE }, 4632a46c0ec8Sopenharmony_ci { "filter-group", 1, 0, OPT_FILTER_GROUP }, 4633a46c0ec8Sopenharmony_ci { "filter-deviceless", 0, 0, OPT_FILTER_DEVICELESS }, 4634a46c0ec8Sopenharmony_ci { "xml-output", 1, 0, OPT_XML_PREFIX }, 4635a46c0ec8Sopenharmony_ci { "jobs", 1, 0, OPT_JOBS }, 4636a46c0ec8Sopenharmony_ci { "list", 0, 0, OPT_LIST }, 4637a46c0ec8Sopenharmony_ci { "verbose", 0, 0, OPT_VERBOSE }, 4638a46c0ec8Sopenharmony_ci { "help", 0, 0, 'h'}, 4639a46c0ec8Sopenharmony_ci { 0, 0, 0, 0} 4640a46c0ec8Sopenharmony_ci }; 4641a46c0ec8Sopenharmony_ci enum { 4642a46c0ec8Sopenharmony_ci JOBS_DEFAULT, 4643a46c0ec8Sopenharmony_ci JOBS_SINGLE, 4644a46c0ec8Sopenharmony_ci JOBS_CUSTOM 4645a46c0ec8Sopenharmony_ci } want_jobs = JOBS_DEFAULT; 4646a46c0ec8Sopenharmony_ci char *builddir; 4647a46c0ec8Sopenharmony_ci char *jobs_env; 4648a46c0ec8Sopenharmony_ci 4649a46c0ec8Sopenharmony_ci /* If we are not running from the builddir, we assume we're running 4650a46c0ec8Sopenharmony_ci * against the system as installed */ 4651a46c0ec8Sopenharmony_ci builddir = builddir_lookup(); 4652a46c0ec8Sopenharmony_ci if (!builddir) 4653a46c0ec8Sopenharmony_ci use_system_rules_quirks = true; 4654a46c0ec8Sopenharmony_ci free(builddir); 4655a46c0ec8Sopenharmony_ci 4656a46c0ec8Sopenharmony_ci if (in_debugger) 4657a46c0ec8Sopenharmony_ci want_jobs = JOBS_SINGLE; 4658a46c0ec8Sopenharmony_ci 4659a46c0ec8Sopenharmony_ci if ((jobs_env = getenv("LITEST_JOBS"))) { 4660a46c0ec8Sopenharmony_ci if (!safe_atoi(jobs_env, &jobs)) { 4661a46c0ec8Sopenharmony_ci fprintf(stderr, "LITEST_JOBS environment variable must be positive integer\n"); 4662a46c0ec8Sopenharmony_ci exit(EXIT_FAILURE); 4663a46c0ec8Sopenharmony_ci } 4664a46c0ec8Sopenharmony_ci } 4665a46c0ec8Sopenharmony_ci 4666a46c0ec8Sopenharmony_ci while(1) { 4667a46c0ec8Sopenharmony_ci int c; 4668a46c0ec8Sopenharmony_ci int option_index = 0; 4669a46c0ec8Sopenharmony_ci 4670a46c0ec8Sopenharmony_ci c = getopt_long(argc, argv, "j:", opts, &option_index); 4671a46c0ec8Sopenharmony_ci if (c == -1) 4672a46c0ec8Sopenharmony_ci break; 4673a46c0ec8Sopenharmony_ci switch(c) { 4674a46c0ec8Sopenharmony_ci default: 4675a46c0ec8Sopenharmony_ci case 'h': 4676a46c0ec8Sopenharmony_ci printf("Usage: %s [--verbose] [--jobs] [--filter-...]\n" 4677a46c0ec8Sopenharmony_ci "\n" 4678a46c0ec8Sopenharmony_ci "Options:\n" 4679a46c0ec8Sopenharmony_ci " --filter-test=.... \n" 4680a46c0ec8Sopenharmony_ci " Glob to filter on test names\n" 4681a46c0ec8Sopenharmony_ci " --filter-device=.... \n" 4682a46c0ec8Sopenharmony_ci " Glob to filter on device names\n" 4683a46c0ec8Sopenharmony_ci " --filter-group=.... \n" 4684a46c0ec8Sopenharmony_ci " Glob to filter on test groups\n" 4685a46c0ec8Sopenharmony_ci " --filter-deviceless=.... \n" 4686a46c0ec8Sopenharmony_ci " Glob to filter on tests that do not create test devices\n" 4687a46c0ec8Sopenharmony_ci " --xml-output=/path/to/file-XXXXXXX.xml\n" 4688a46c0ec8Sopenharmony_ci " Write test output in libcheck's XML format\n" 4689a46c0ec8Sopenharmony_ci " to the given files. The file must match the format\n" 4690a46c0ec8Sopenharmony_ci " prefix-XXXXXX.xml and only the prefix is your choice.\n" 4691a46c0ec8Sopenharmony_ci " --verbose\n" 4692a46c0ec8Sopenharmony_ci " Enable verbose output\n" 4693a46c0ec8Sopenharmony_ci " --jobs 8\n" 4694a46c0ec8Sopenharmony_ci " Number of parallel test suites to run (default: 8).\n" 4695a46c0ec8Sopenharmony_ci " This overrides the LITEST_JOBS environment variable.\n" 4696a46c0ec8Sopenharmony_ci " --list\n" 4697a46c0ec8Sopenharmony_ci " List all tests\n" 4698a46c0ec8Sopenharmony_ci "\n" 4699a46c0ec8Sopenharmony_ci "See the libinput-test-suite(1) man page for details.\n", 4700a46c0ec8Sopenharmony_ci program_invocation_short_name); 4701a46c0ec8Sopenharmony_ci exit(c != 'h'); 4702a46c0ec8Sopenharmony_ci break; 4703a46c0ec8Sopenharmony_ci case OPT_FILTER_TEST: 4704a46c0ec8Sopenharmony_ci filter_test = optarg; 4705a46c0ec8Sopenharmony_ci if (want_jobs == JOBS_DEFAULT) 4706a46c0ec8Sopenharmony_ci want_jobs = JOBS_SINGLE; 4707a46c0ec8Sopenharmony_ci break; 4708a46c0ec8Sopenharmony_ci case OPT_FILTER_DEVICE: 4709a46c0ec8Sopenharmony_ci filter_device = optarg; 4710a46c0ec8Sopenharmony_ci if (want_jobs == JOBS_DEFAULT) 4711a46c0ec8Sopenharmony_ci want_jobs = JOBS_SINGLE; 4712a46c0ec8Sopenharmony_ci break; 4713a46c0ec8Sopenharmony_ci case OPT_FILTER_GROUP: 4714a46c0ec8Sopenharmony_ci filter_group = optarg; 4715a46c0ec8Sopenharmony_ci break; 4716a46c0ec8Sopenharmony_ci case OPT_XML_PREFIX: 4717a46c0ec8Sopenharmony_ci xml_prefix = optarg; 4718a46c0ec8Sopenharmony_ci break; 4719a46c0ec8Sopenharmony_ci case 'j': 4720a46c0ec8Sopenharmony_ci case OPT_JOBS: 4721a46c0ec8Sopenharmony_ci jobs = atoi(optarg); 4722a46c0ec8Sopenharmony_ci want_jobs = JOBS_CUSTOM; 4723a46c0ec8Sopenharmony_ci break; 4724a46c0ec8Sopenharmony_ci case OPT_LIST: 4725a46c0ec8Sopenharmony_ci return LITEST_MODE_LIST; 4726a46c0ec8Sopenharmony_ci case OPT_VERBOSE: 4727a46c0ec8Sopenharmony_ci verbose = true; 4728a46c0ec8Sopenharmony_ci break; 4729a46c0ec8Sopenharmony_ci case OPT_FILTER_DEVICELESS: 4730a46c0ec8Sopenharmony_ci run_deviceless = true; 4731a46c0ec8Sopenharmony_ci break; 4732a46c0ec8Sopenharmony_ci } 4733a46c0ec8Sopenharmony_ci } 4734a46c0ec8Sopenharmony_ci 4735a46c0ec8Sopenharmony_ci if (want_jobs == JOBS_SINGLE) 4736a46c0ec8Sopenharmony_ci jobs = 1; 4737a46c0ec8Sopenharmony_ci 4738a46c0ec8Sopenharmony_ci return LITEST_MODE_TEST; 4739a46c0ec8Sopenharmony_ci} 4740a46c0ec8Sopenharmony_ci 4741a46c0ec8Sopenharmony_ci#ifndef LITEST_NO_MAIN 4742a46c0ec8Sopenharmony_cistatic bool 4743a46c0ec8Sopenharmony_ciis_debugger_attached(void) 4744a46c0ec8Sopenharmony_ci{ 4745a46c0ec8Sopenharmony_ci int status; 4746a46c0ec8Sopenharmony_ci bool rc; 4747a46c0ec8Sopenharmony_ci int pid = fork(); 4748a46c0ec8Sopenharmony_ci 4749a46c0ec8Sopenharmony_ci if (pid == -1) 4750a46c0ec8Sopenharmony_ci return 0; 4751a46c0ec8Sopenharmony_ci 4752a46c0ec8Sopenharmony_ci if (pid == 0) { 4753a46c0ec8Sopenharmony_ci int ppid = getppid(); 4754a46c0ec8Sopenharmony_ci if (ptrace(PTRACE_ATTACH, ppid, NULL, 0) == 0) { 4755a46c0ec8Sopenharmony_ci waitpid(ppid, NULL, 0); 4756a46c0ec8Sopenharmony_ci ptrace(PTRACE_CONT, ppid, NULL, 0); 4757a46c0ec8Sopenharmony_ci ptrace(PTRACE_DETACH, ppid, NULL, 0); 4758a46c0ec8Sopenharmony_ci rc = false; 4759a46c0ec8Sopenharmony_ci } else { 4760a46c0ec8Sopenharmony_ci rc = true; 4761a46c0ec8Sopenharmony_ci } 4762a46c0ec8Sopenharmony_ci _exit(rc); 4763a46c0ec8Sopenharmony_ci } else { 4764a46c0ec8Sopenharmony_ci waitpid(pid, &status, 0); 4765a46c0ec8Sopenharmony_ci rc = WEXITSTATUS(status); 4766a46c0ec8Sopenharmony_ci } 4767a46c0ec8Sopenharmony_ci 4768a46c0ec8Sopenharmony_ci return !!rc; 4769a46c0ec8Sopenharmony_ci} 4770a46c0ec8Sopenharmony_ci 4771a46c0ec8Sopenharmony_cistatic void 4772a46c0ec8Sopenharmony_cilitest_list_tests(struct list *tests) 4773a46c0ec8Sopenharmony_ci{ 4774a46c0ec8Sopenharmony_ci struct suite *s; 4775a46c0ec8Sopenharmony_ci const char *last_test_name = NULL; 4776a46c0ec8Sopenharmony_ci 4777a46c0ec8Sopenharmony_ci list_for_each(s, tests, node) { 4778a46c0ec8Sopenharmony_ci struct test *t; 4779a46c0ec8Sopenharmony_ci printf("%s:\n", s->name); 4780a46c0ec8Sopenharmony_ci list_for_each(t, &s->tests, node) { 4781a46c0ec8Sopenharmony_ci if (!last_test_name || 4782a46c0ec8Sopenharmony_ci !streq(last_test_name, t->name)) 4783a46c0ec8Sopenharmony_ci printf(" %s:\n", t->name); 4784a46c0ec8Sopenharmony_ci 4785a46c0ec8Sopenharmony_ci last_test_name = t->name; 4786a46c0ec8Sopenharmony_ci 4787a46c0ec8Sopenharmony_ci printf(" %s\n", t->devname); 4788a46c0ec8Sopenharmony_ci } 4789a46c0ec8Sopenharmony_ci } 4790a46c0ec8Sopenharmony_ci} 4791a46c0ec8Sopenharmony_ci 4792a46c0ec8Sopenharmony_ciextern const struct test_device __start_test_section, __stop_test_section; 4793a46c0ec8Sopenharmony_ci 4794a46c0ec8Sopenharmony_cistatic void 4795a46c0ec8Sopenharmony_cilitest_init_test_devices(void) 4796a46c0ec8Sopenharmony_ci{ 4797a46c0ec8Sopenharmony_ci const struct test_device *t; 4798a46c0ec8Sopenharmony_ci 4799a46c0ec8Sopenharmony_ci list_init(&devices); 4800a46c0ec8Sopenharmony_ci 4801a46c0ec8Sopenharmony_ci for (t = &__start_test_section; t < &__stop_test_section; t++) 4802a46c0ec8Sopenharmony_ci list_append(&devices, &t->device->node); 4803a46c0ec8Sopenharmony_ci} 4804a46c0ec8Sopenharmony_ci 4805a46c0ec8Sopenharmony_ciextern const struct test_collection __start_test_collection_section, 4806a46c0ec8Sopenharmony_ci __stop_test_collection_section; 4807a46c0ec8Sopenharmony_ci 4808a46c0ec8Sopenharmony_cistatic void 4809a46c0ec8Sopenharmony_cisetup_tests(void) 4810a46c0ec8Sopenharmony_ci{ 4811a46c0ec8Sopenharmony_ci const struct test_collection *c; 4812a46c0ec8Sopenharmony_ci 4813a46c0ec8Sopenharmony_ci for (c = &__start_test_collection_section; 4814a46c0ec8Sopenharmony_ci c < &__stop_test_collection_section; 4815a46c0ec8Sopenharmony_ci c++) { 4816a46c0ec8Sopenharmony_ci c->setup(); 4817a46c0ec8Sopenharmony_ci } 4818a46c0ec8Sopenharmony_ci} 4819a46c0ec8Sopenharmony_ci 4820a46c0ec8Sopenharmony_cistatic int 4821a46c0ec8Sopenharmony_cicheck_device_access(void) 4822a46c0ec8Sopenharmony_ci{ 4823a46c0ec8Sopenharmony_ci if (getuid() != 0) { 4824a46c0ec8Sopenharmony_ci fprintf(stderr, 4825a46c0ec8Sopenharmony_ci "%s must be run as root.\n", 4826a46c0ec8Sopenharmony_ci program_invocation_short_name); 4827a46c0ec8Sopenharmony_ci return 77; 4828a46c0ec8Sopenharmony_ci } 4829a46c0ec8Sopenharmony_ci 4830a46c0ec8Sopenharmony_ci if (access("/dev/uinput", F_OK) == -1 && 4831a46c0ec8Sopenharmony_ci access("/dev/input/uinput", F_OK) == -1) { 4832a46c0ec8Sopenharmony_ci fprintf(stderr, 4833a46c0ec8Sopenharmony_ci "uinput device is missing, skipping tests.\n"); 4834a46c0ec8Sopenharmony_ci return 77; 4835a46c0ec8Sopenharmony_ci } 4836a46c0ec8Sopenharmony_ci 4837a46c0ec8Sopenharmony_ci return 0; 4838a46c0ec8Sopenharmony_ci} 4839a46c0ec8Sopenharmony_ci 4840a46c0ec8Sopenharmony_cistatic int 4841a46c0ec8Sopenharmony_cidisable_tty(void) 4842a46c0ec8Sopenharmony_ci{ 4843a46c0ec8Sopenharmony_ci int tty_mode = -1; 4844a46c0ec8Sopenharmony_ci 4845a46c0ec8Sopenharmony_ci /* If we're running 'normally' on the VT, disable the keyboard to 4846a46c0ec8Sopenharmony_ci * avoid messing up our host. But if we're inside gdb or running 4847a46c0ec8Sopenharmony_ci * without forking, leave it as-is. 4848a46c0ec8Sopenharmony_ci */ 4849a46c0ec8Sopenharmony_ci if (!run_deviceless && 4850a46c0ec8Sopenharmony_ci jobs > 1 && 4851a46c0ec8Sopenharmony_ci !in_debugger && 4852a46c0ec8Sopenharmony_ci getenv("CK_FORK") == NULL && 4853a46c0ec8Sopenharmony_ci isatty(STDIN_FILENO) && 4854a46c0ec8Sopenharmony_ci ioctl(STDIN_FILENO, KDGKBMODE, &tty_mode) == 0) { 4855a46c0ec8Sopenharmony_ci#ifdef __linux__ 4856a46c0ec8Sopenharmony_ci ioctl(STDIN_FILENO, KDSKBMODE, K_OFF); 4857a46c0ec8Sopenharmony_ci#elif __FreeBSD__ 4858a46c0ec8Sopenharmony_ci ioctl(STDIN_FILENO, KDSKBMODE, K_RAW); 4859a46c0ec8Sopenharmony_ci 4860a46c0ec8Sopenharmony_ci /* Put the tty into raw mode */ 4861a46c0ec8Sopenharmony_ci struct termios tios; 4862a46c0ec8Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &tios)) 4863a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno)); 4864a46c0ec8Sopenharmony_ci cfmakeraw(&tios); 4865a46c0ec8Sopenharmony_ci if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios)) 4866a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno)); 4867a46c0ec8Sopenharmony_ci#endif 4868a46c0ec8Sopenharmony_ci } 4869a46c0ec8Sopenharmony_ci 4870a46c0ec8Sopenharmony_ci return tty_mode; 4871a46c0ec8Sopenharmony_ci} 4872a46c0ec8Sopenharmony_ci 4873a46c0ec8Sopenharmony_ciint 4874a46c0ec8Sopenharmony_cimain(int argc, char **argv) 4875a46c0ec8Sopenharmony_ci{ 4876a46c0ec8Sopenharmony_ci const struct rlimit corelimit = { 0, 0 }; 4877a46c0ec8Sopenharmony_ci enum litest_mode mode; 4878a46c0ec8Sopenharmony_ci int tty_mode = -1; 4879a46c0ec8Sopenharmony_ci int failed_tests; 4880a46c0ec8Sopenharmony_ci int rc; 4881a46c0ec8Sopenharmony_ci const char *meson_testthreads; 4882a46c0ec8Sopenharmony_ci 4883a46c0ec8Sopenharmony_ci in_debugger = is_debugger_attached(); 4884a46c0ec8Sopenharmony_ci if (in_debugger || RUNNING_ON_VALGRIND) 4885a46c0ec8Sopenharmony_ci setenv("CK_FORK", "no", 0); 4886a46c0ec8Sopenharmony_ci 4887a46c0ec8Sopenharmony_ci if ((meson_testthreads = getenv("MESON_TESTTHREADS")) == NULL || 4888a46c0ec8Sopenharmony_ci !safe_atoi(meson_testthreads, &jobs)) { 4889a46c0ec8Sopenharmony_ci jobs = get_nprocs(); 4890a46c0ec8Sopenharmony_ci if (!RUNNING_ON_VALGRIND) 4891a46c0ec8Sopenharmony_ci jobs *= 2; 4892a46c0ec8Sopenharmony_ci } 4893a46c0ec8Sopenharmony_ci 4894a46c0ec8Sopenharmony_ci mode = litest_parse_argv(argc, argv); 4895a46c0ec8Sopenharmony_ci if (mode == LITEST_MODE_ERROR) 4896a46c0ec8Sopenharmony_ci return EXIT_FAILURE; 4897a46c0ec8Sopenharmony_ci 4898a46c0ec8Sopenharmony_ci litest_init_test_devices(); 4899a46c0ec8Sopenharmony_ci list_init(&all_tests); 4900a46c0ec8Sopenharmony_ci setup_tests(); 4901a46c0ec8Sopenharmony_ci if (mode == LITEST_MODE_LIST) { 4902a46c0ec8Sopenharmony_ci litest_list_tests(&all_tests); 4903a46c0ec8Sopenharmony_ci return EXIT_SUCCESS; 4904a46c0ec8Sopenharmony_ci } 4905a46c0ec8Sopenharmony_ci 4906a46c0ec8Sopenharmony_ci if (!run_deviceless && (rc = check_device_access()) != 0) 4907a46c0ec8Sopenharmony_ci return rc; 4908a46c0ec8Sopenharmony_ci 4909a46c0ec8Sopenharmony_ci setenv("CK_DEFAULT_TIMEOUT", "30", 0); 4910a46c0ec8Sopenharmony_ci setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1); 4911a46c0ec8Sopenharmony_ci 4912a46c0ec8Sopenharmony_ci if (setrlimit(RLIMIT_CORE, &corelimit) != 0) 4913a46c0ec8Sopenharmony_ci perror("WARNING: Core dumps not disabled"); 4914a46c0ec8Sopenharmony_ci 4915a46c0ec8Sopenharmony_ci tty_mode = disable_tty(); 4916a46c0ec8Sopenharmony_ci 4917a46c0ec8Sopenharmony_ci failed_tests = litest_run(argc, argv); 4918a46c0ec8Sopenharmony_ci 4919a46c0ec8Sopenharmony_ci if (tty_mode != -1) { 4920a46c0ec8Sopenharmony_ci ioctl(STDIN_FILENO, KDSKBMODE, tty_mode); 4921a46c0ec8Sopenharmony_ci#ifdef __FreeBSD__ 4922a46c0ec8Sopenharmony_ci /* Put the tty into "sane" mode */ 4923a46c0ec8Sopenharmony_ci struct termios tios; 4924a46c0ec8Sopenharmony_ci if (tcgetattr(STDIN_FILENO, &tios)) 4925a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to get terminal attribute: %d - %s\n", errno, strerror(errno)); 4926a46c0ec8Sopenharmony_ci cfmakesane(&tios); 4927a46c0ec8Sopenharmony_ci if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios)) 4928a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to set terminal attribute: %d - %s\n", errno, strerror(errno)); 4929a46c0ec8Sopenharmony_ci#endif 4930a46c0ec8Sopenharmony_ci } 4931a46c0ec8Sopenharmony_ci 4932a46c0ec8Sopenharmony_ci return min(failed_tests, 255); 4933a46c0ec8Sopenharmony_ci} 4934a46c0ec8Sopenharmony_ci#endif 4935