1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com> 4 * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz> 5 */ 6 7#include <linux/input.h> 8#include <linux/uinput.h> 9#include <stdio.h> 10#include <string.h> 11 12#define TST_NO_DEFAULT_MAIN 13#include "tst_test.h" 14 15#include "tst_uinput.h" 16 17#define VIRTUAL_DEVICE "virtual-device-ltp" 18 19static const char *uinput_paths[] = { 20 "/dev/input/uinput", 21 "/dev/uinput", 22}; 23 24int open_uinput(void) 25{ 26 unsigned int i; 27 int fd; 28 29 for (i = 0; i < ARRAY_SIZE(uinput_paths); i++) { 30 fd = open(uinput_paths[i], O_WRONLY | O_NONBLOCK); 31 32 if (fd > 0) { 33 tst_res(TINFO, "Found uinput dev at %s", uinput_paths[i]); 34 return fd; 35 } 36 37 if (fd < 0 && errno != ENOENT) { 38 tst_brk(TBROK | TERRNO, "open(%s)", uinput_paths[i]); 39 } 40 } 41 42 return -1; 43} 44 45 46#define SYSFS_PREFIX "Sysfs=" 47#define HANDLERS_PREFIX "Handlers=" 48 49static char *parse_field(char *line, char field) 50{ 51 char *value; 52 53 switch (field) { 54 case 'H': 55 value = strstr(line, HANDLERS_PREFIX) + sizeof(HANDLERS_PREFIX) - 1; 56 break; 57 case 'S': 58 value = strstr(line, SYSFS_PREFIX) + sizeof(SYSFS_PREFIX) - 1; 59 break; 60 default: 61 return NULL; 62 } 63 64 value[strlen(value) - 1] = 0; 65 66 return strdup(value); 67} 68 69char *get_input_field_value(char field) 70{ 71 FILE *file; 72 char line[1024]; 73 int flag = 0; 74 75 file = fopen("/proc/bus/input/devices", "r"); 76 if (!file) 77 return NULL; 78 79 while (fgets(line, sizeof(line), file)) { 80 if (strstr(line, "N: Name=\""VIRTUAL_DEVICE"\"")) 81 flag = 1; 82 83 if (flag) { 84 if (line[0] == field) 85 return parse_field(line, field); 86 87 if (line[0] == '\n') 88 flag = 0; 89 } 90 } 91 92 fclose(file); 93 return NULL; 94} 95 96static int check_device(void) 97{ 98 FILE *file; 99 char line[256]; 100 101 file = fopen("/proc/bus/input/devices", "r"); 102 if (!file) 103 return 0; 104 105 while (fgets(line, sizeof(line), file)) { 106 if (strstr(line, "Name=\""VIRTUAL_DEVICE"\"")) 107 return 1; 108 } 109 110 fclose(file); 111 112 return 0; 113} 114 115void setup_mouse_events(int fd) 116{ 117 SAFE_IOCTL(fd, UI_SET_EVBIT, EV_KEY); 118 SAFE_IOCTL(fd, UI_SET_KEYBIT, BTN_LEFT); 119 SAFE_IOCTL(fd, UI_SET_EVBIT, EV_REL); 120 SAFE_IOCTL(fd, UI_SET_RELBIT, REL_X); 121 SAFE_IOCTL(fd, UI_SET_RELBIT, REL_Y); 122} 123 124void destroy_input_device(int fd) 125{ 126 SAFE_IOCTL(fd, UI_DEV_DESTROY, NULL); 127 SAFE_CLOSE(fd); 128} 129 130void create_input_device(int fd) 131{ 132 int nb; 133 struct uinput_user_dev uidev = { 134 .name = VIRTUAL_DEVICE, 135 .id = { 136 .bustype = BUS_USB, 137 .vendor = 0x1, 138 .product = 0x1, 139 .version = 1, 140 } 141 }; 142 143 SAFE_WRITE(SAFE_WRITE_ALL, fd, &uidev, sizeof(uidev)); 144 SAFE_IOCTL(fd, UI_DEV_CREATE, NULL); 145 146 for (nb = 100; nb > 0; nb--) { 147 if (check_device()) 148 return; 149 usleep(10000); 150 } 151 152 destroy_input_device(fd); 153 tst_brk(TBROK, "Failed to create device"); 154} 155