• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
4  */
5 
6 /*
7  * Very simple uevent netlink socket test.
8  *
9  * We fork a child that listens for a kernel events while parents creates and
10  * removes a virtual mouse which produces add and remove event for the device
11  * itself and for two event handlers called eventX and mouseY.
12  */
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <sys/wait.h>
17 #include <sys/sysmacros.h>
18 #include <linux/uinput.h>
19 #include "tst_test.h"
20 #include "tst_uinput.h"
21 #include "uevent.h"
22 
23 static int mouse_fd;
24 
create_uinput_mouse(void)25 static void create_uinput_mouse(void)
26 {
27 	mouse_fd = open_uinput();
28 	setup_mouse_events(mouse_fd);
29 	create_input_device(mouse_fd);
30 }
31 
destroy_uinput_mouse(void)32 static void destroy_uinput_mouse(void)
33 {
34 	destroy_input_device(mouse_fd);
35 }
36 
get_minor_major(char * device,char * minor,char * major,size_t buf_sizes)37 static void get_minor_major(char *device, char *minor, char *major, size_t buf_sizes)
38 {
39 	char path[1024];
40 	struct stat stbuf;
41 
42 	snprintf(path, sizeof(path), "/dev/input/%s", device);
43 
44 	SAFE_STAT(path, &stbuf);
45 
46 	snprintf(major, buf_sizes, "MAJOR=%i", major(stbuf.st_rdev));
47 	snprintf(minor, buf_sizes, "MINOR=%i", minor(stbuf.st_rdev));
48 }
49 
50 #define MINOR_MAJOR_SIZE 32
51 
verify_uevent(void)52 static void verify_uevent(void)
53 {
54 	int pid, fd;
55 	char add_msg[1024];
56 	char rem_msg[1024];
57 	char dev_path[1024];
58 	char add_msg_event1[1024];
59 	char rem_msg_event1[1024];
60 	char dev_path_event1[1024];
61 	char add_msg_event2[1024];
62 	char rem_msg_event2[1024];
63 	char dev_path_event2[1024];
64 	char dev_name1[1024];
65 	char dev_name2[1024];
66 
67 	char minor_event1[MINOR_MAJOR_SIZE];
68 	char minor_event2[MINOR_MAJOR_SIZE];
69 	char major_event1[MINOR_MAJOR_SIZE];
70 	char major_event2[MINOR_MAJOR_SIZE];
71 
72 	char *handlers, *handler1, *handler2, *sysname;
73 	struct uevent_desc add = {
74 		.msg = add_msg,
75 		.value_cnt = 7,
76 		.values = (const char*[]) {
77 			"ACTION=add",
78 			dev_path,
79 			"SUBSYSTEM=input",
80 			"NAME=\"virtual-device-ltp\"",
81 			"PROP=0",
82 			"EV=7",
83 			"REL=3",
84 		}
85 	};
86 
87 	struct uevent_desc add_event1 = {
88 		.msg = add_msg_event1,
89 		.value_cnt = 6,
90 		.values = (const char*[]) {
91 			"ACTION=add",
92 			"SUBSYSTEM=input",
93 			dev_name1,
94 			dev_path_event1,
95 			minor_event1,
96 			major_event1,
97 		}
98 	};
99 
100 	struct uevent_desc add_event2 = {
101 		.msg = add_msg_event2,
102 		.value_cnt = 6,
103 		.values = (const char*[]) {
104 			"ACTION=add",
105 			"SUBSYSTEM=input",
106 			dev_name2,
107 			dev_path_event2,
108 			minor_event2,
109 			major_event2,
110 		}
111 	};
112 
113 	struct uevent_desc rem_event1 = {
114 		.msg = rem_msg_event1,
115 		.value_cnt = 6,
116 		.values = (const char*[]) {
117 			"ACTION=remove",
118 			"SUBSYSTEM=input",
119 			dev_name1,
120 			dev_path_event1,
121 			minor_event1,
122 			major_event1,
123 		}
124 	};
125 
126 	struct uevent_desc rem_event2 = {
127 		.msg = rem_msg_event2,
128 		.value_cnt = 6,
129 		.values = (const char*[]) {
130 			"ACTION=remove",
131 			"SUBSYSTEM=input",
132 			dev_name2,
133 			dev_path_event2,
134 			minor_event2,
135 			major_event2,
136 		}
137 	};
138 
139 	struct uevent_desc rem = {
140 		.msg = rem_msg,
141 		.value_cnt = 7,
142 		.values = (const char*[]) {
143 			"ACTION=remove",
144 			dev_path,
145 			"SUBSYSTEM=input",
146 			"NAME=\"virtual-device-ltp\"",
147 			"PROP=0",
148 			"EV=7",
149 			"REL=3",
150 		}
151 	};
152 
153 	const struct uevent_desc *const uevents[] = {
154 		&add,
155 		&add_event1,
156 		&add_event2,
157 		&rem_event1,
158 		&rem_event2,
159 		&rem,
160 		NULL
161 	};
162 
163 	fd = open_uevent_netlink();
164 
165 	create_uinput_mouse();
166 
167 	sysname = get_input_field_value('S');
168 	handlers = get_input_field_value('H');
169 
170 	if (!sysname)
171 		tst_brk(TBROK, "Expected /devices/virtual/input/inputN sysname!");
172 
173 	tst_res(TINFO, "Sysname: %s", sysname);
174 	tst_res(TINFO, "Handlers: %s", handlers);
175 
176 	handler1 = strtok(handlers, " ");
177 	if (!handler1)
178 		tst_brk(TBROK, "Expected mouseX and eventY handlers!");
179 
180 	get_minor_major(handler1, minor_event1, major_event1, MINOR_MAJOR_SIZE);
181 
182 	handler2 = strtok(NULL, " ");
183 	if (!handler2)
184 		tst_brk(TBROK, "Expected mouseX and eventY handlers!");
185 
186 	get_minor_major(handler2, minor_event2, major_event2, MINOR_MAJOR_SIZE);
187 
188 	destroy_uinput_mouse();
189 
190 	snprintf(add_msg, sizeof(add_msg), "add@%s", sysname);
191 
192 	snprintf(rem_msg, sizeof(rem_msg), "remove@%s", sysname);
193 
194 	snprintf(dev_path, sizeof(dev_path), "DEVPATH=%s", sysname);
195 
196 	snprintf(add_msg_event1, sizeof(add_msg_event1),
197 		"add@%s/%s", sysname, handler1);
198 
199 	snprintf(rem_msg_event1, sizeof(rem_msg_event1),
200 		"remove@%s/%s", sysname, handler1);
201 
202 	snprintf(dev_path_event1, sizeof(dev_path_event1),
203 		"DEVPATH=%s/%s", sysname, handler1);
204 
205 	snprintf(dev_name1, sizeof(dev_name1),
206 		"DEVNAME=input/%s", handler1);
207 
208 
209 	snprintf(add_msg_event2, sizeof(add_msg_event2),
210 		"add@%s/%s", sysname, handler2);
211 
212 	snprintf(rem_msg_event2, sizeof(rem_msg_event2),
213 		"remove@%s/%s", sysname, handler2);
214 
215 	snprintf(dev_path_event2, sizeof(dev_path_event2),
216 		"DEVPATH=%s/%s", sysname, handler2);
217 
218 	snprintf(dev_name2, sizeof(dev_name2),
219 		"DEVNAME=input/%s", handler2);
220 
221 	free(sysname);
222 	free(handlers);
223 
224 	pid = SAFE_FORK();
225 	if (!pid) {
226 		wait_for_uevents(fd, uevents);
227 		exit(0);
228 	}
229 
230 	SAFE_CLOSE(fd);
231 	wait_for_pid(pid);
232 }
233 
234 static struct tst_test test = {
235 	.test_all = verify_uevent,
236 	.forks_child = 1,
237 	.needs_checkpoints = 1,
238 	.needs_drivers = (const char *const[]) {
239 		"uinput",
240 		NULL
241 	},
242 	.needs_root = 1,
243 };
244