// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2015 Cedric Hnyda * Copyright (c) 2019 Cyril Hrubis */ #include #include #include #include #define TST_NO_DEFAULT_MAIN #include "tst_test.h" #include "tst_uinput.h" #define VIRTUAL_DEVICE "virtual-device-ltp" static const char *uinput_paths[] = { "/dev/input/uinput", "/dev/uinput", }; int open_uinput(void) { unsigned int i; int fd; for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) { fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK); if (fd > 0) { tst_res(TINFO, "Found uinput dev at %s", uinput_paths[i]); return fd; } if (fd < 0 && errno != ENOENT) { tst_brk(TBROK | TERRNO, "open(%s)", uinput_paths[i]); } } return -1; } #define SYSFS_PREFIX "Sysfs=" #define HANDLERS_PREFIX "Handlers=" static char *parse_field(char *line, char field) { char *value; switch (field) { case 'H': value = strstr(line, HANDLERS_PREFIX) + sizeof(HANDLERS_PREFIX) - 1; break; case 'S': value = strstr(line, SYSFS_PREFIX) + sizeof(SYSFS_PREFIX) - 1; break; default: return NULL; } value[strlen(value) - 1] = 0; return strdup(value); } char *get_input_field_value(char field) { FILE *file; char line[1024]; int flag = 0; file = fopen("/proc/bus/input/devices", "r"); if (!file) return NULL; while (fgets(line, sizeof(line), file)) { if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\"")) flag = 1; if (flag) { if (line[0] == field) return parse_field(line, field); if (line[0] == '\n') flag = 0; } } fclose(file); return NULL; } static int check_device(void) { FILE *file; char line[256]; file = fopen("/proc/bus/input/devices", "r"); if (!file) return 0; while (fgets(line, sizeof(line), file)) { if (strstr(line, "Name=\""VIRTUAL_DEVICE"\"")) return 1; } fclose(file); return 0; } void setup_mouse_events(int fd) { SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY); SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT); SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL); SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X); SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y); } void destroy_input_device(int fd) { SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL); SAFE_CLOSE(fd); } void create_input_device(int fd) { int nb; struct uinput_user_dev uidev = { .name = VIRTUAL_DEVICE, .id = { .bustype = BUS_USB, .vendor = 0x1, .product = 0x1, .version = 1, } }; SAFE_WRITE(1, fd, &uidev, sizeof(uidev)); SAFE_IOCTL(fd, UI_DEV_CREATE, NULL); for (nb = 100; nb > 0; nb--) { if (check_device()) return; usleep(10000); } destroy_input_device(fd); tst_brk(TBROK, "Failed to create device"); }