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