xref: /aosp_15_r20/external/ltp/testcases/kernel/input/input06.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2015 Cedric Hnyda <[email protected]>
3*49cdfc7eSAndroid Build Coastguard Worker  *
4*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
5*49cdfc7eSAndroid Build Coastguard Worker  * modify it under the terms of the GNU General Public License as
6*49cdfc7eSAndroid Build Coastguard Worker  * published by the Free Software Foundation; either version 2 of
7*49cdfc7eSAndroid Build Coastguard Worker  * the License, or (at your option) any later version.
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it would be useful,
10*49cdfc7eSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*49cdfc7eSAndroid Build Coastguard Worker  * GNU General Public License for more details.
13*49cdfc7eSAndroid Build Coastguard Worker  *
14*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
15*49cdfc7eSAndroid Build Coastguard Worker  * along with this program; if not, write the Free Software Foundation,
16*49cdfc7eSAndroid Build Coastguard Worker  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17*49cdfc7eSAndroid Build Coastguard Worker  */
18*49cdfc7eSAndroid Build Coastguard Worker 
19*49cdfc7eSAndroid Build Coastguard Worker  /*
20*49cdfc7eSAndroid Build Coastguard Worker   *  Create a virtual device, activate auto-repeat and
21*49cdfc7eSAndroid Build Coastguard Worker   *  and check that auto repeat is working
22*49cdfc7eSAndroid Build Coastguard Worker   */
23*49cdfc7eSAndroid Build Coastguard Worker 
24*49cdfc7eSAndroid Build Coastguard Worker #include <linux/input.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <linux/uinput.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <linux/kd.h>
27*49cdfc7eSAndroid Build Coastguard Worker 
28*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
29*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
30*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/fcntl.h"
31*49cdfc7eSAndroid Build Coastguard Worker #include "input_helper.h"
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker static void setup(void);
34*49cdfc7eSAndroid Build Coastguard Worker static void send_events(void);
35*49cdfc7eSAndroid Build Coastguard Worker static int check_events(void);
36*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void);
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker static int fd;
39*49cdfc7eSAndroid Build Coastguard Worker static int fd2;
40*49cdfc7eSAndroid Build Coastguard Worker struct input_event events[64];
41*49cdfc7eSAndroid Build Coastguard Worker static int num_events;
42*49cdfc7eSAndroid Build Coastguard Worker static int ev_iter;
43*49cdfc7eSAndroid Build Coastguard Worker 
44*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "input06";
45*49cdfc7eSAndroid Build Coastguard Worker 
main(int ac,char ** av)46*49cdfc7eSAndroid Build Coastguard Worker int main(int ac, char **av)
47*49cdfc7eSAndroid Build Coastguard Worker {
48*49cdfc7eSAndroid Build Coastguard Worker 	int lc;
49*49cdfc7eSAndroid Build Coastguard Worker 	int pid;
50*49cdfc7eSAndroid Build Coastguard Worker 
51*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(ac, av, NULL, NULL);
52*49cdfc7eSAndroid Build Coastguard Worker 
53*49cdfc7eSAndroid Build Coastguard Worker 	setup();
54*49cdfc7eSAndroid Build Coastguard Worker 
55*49cdfc7eSAndroid Build Coastguard Worker 	for (lc = 0; TEST_LOOPING(lc); ++lc) {
56*49cdfc7eSAndroid Build Coastguard Worker 		pid = tst_fork();
57*49cdfc7eSAndroid Build Coastguard Worker 
58*49cdfc7eSAndroid Build Coastguard Worker 		switch (pid) {
59*49cdfc7eSAndroid Build Coastguard Worker 		case 0:
60*49cdfc7eSAndroid Build Coastguard Worker 			send_events();
61*49cdfc7eSAndroid Build Coastguard Worker 			exit(0);
62*49cdfc7eSAndroid Build Coastguard Worker 		case -1:
63*49cdfc7eSAndroid Build Coastguard Worker 			tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
64*49cdfc7eSAndroid Build Coastguard Worker 		default:
65*49cdfc7eSAndroid Build Coastguard Worker 			if (!check_events())
66*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TFAIL,
67*49cdfc7eSAndroid Build Coastguard Worker 					"Wrong data received in eventX");
68*49cdfc7eSAndroid Build Coastguard Worker 			else
69*49cdfc7eSAndroid Build Coastguard Worker 				tst_resm(TPASS, "Data received in eventX");
70*49cdfc7eSAndroid Build Coastguard Worker 		break;
71*49cdfc7eSAndroid Build Coastguard Worker 		}
72*49cdfc7eSAndroid Build Coastguard Worker 
73*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_WAITPID(NULL, pid, NULL, 0);
74*49cdfc7eSAndroid Build Coastguard Worker 	}
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker 	cleanup();
77*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
78*49cdfc7eSAndroid Build Coastguard Worker }
79*49cdfc7eSAndroid Build Coastguard Worker 
setup(void)80*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
81*49cdfc7eSAndroid Build Coastguard Worker {
82*49cdfc7eSAndroid Build Coastguard Worker 	tst_require_root();
83*49cdfc7eSAndroid Build Coastguard Worker 
84*49cdfc7eSAndroid Build Coastguard Worker 	fd = open_uinput();
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(NULL, fd, UI_SET_EVBIT, EV_KEY);
87*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(NULL, fd, UI_SET_EVBIT, EV_REP);
88*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(NULL, fd, UI_SET_KEYBIT, KEY_X);
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	create_device(fd);
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker 	fd2 = open_device();
93*49cdfc7eSAndroid Build Coastguard Worker 	SAFE_IOCTL(NULL, fd2, EVIOCGRAB, 1);
94*49cdfc7eSAndroid Build Coastguard Worker }
95*49cdfc7eSAndroid Build Coastguard Worker 
send_events(void)96*49cdfc7eSAndroid Build Coastguard Worker static void send_events(void)
97*49cdfc7eSAndroid Build Coastguard Worker {
98*49cdfc7eSAndroid Build Coastguard Worker 	send_event(fd, EV_KEY, KEY_X, 1);
99*49cdfc7eSAndroid Build Coastguard Worker 	send_event(fd, EV_SYN, 0, 0);
100*49cdfc7eSAndroid Build Coastguard Worker 
101*49cdfc7eSAndroid Build Coastguard Worker 	/*
102*49cdfc7eSAndroid Build Coastguard Worker 	 * Sleep long enough to keep the key pressed for some time
103*49cdfc7eSAndroid Build Coastguard Worker 	 * (auto-repeat).  Default kernel delay to start auto-repeat is 250ms
104*49cdfc7eSAndroid Build Coastguard Worker 	 * and the period is 33ms. So, we wait for a generous 500ms to make
105*49cdfc7eSAndroid Build Coastguard Worker 	 * sure we get the auto-repeated keys
106*49cdfc7eSAndroid Build Coastguard Worker 	 */
107*49cdfc7eSAndroid Build Coastguard Worker 	usleep(500000);
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	send_event(fd, EV_KEY, KEY_X, 0);
110*49cdfc7eSAndroid Build Coastguard Worker 	send_event(fd, EV_SYN, 0, 0);
111*49cdfc7eSAndroid Build Coastguard Worker }
112*49cdfc7eSAndroid Build Coastguard Worker 
check_event(struct input_event * iev,int event,int code,int value)113*49cdfc7eSAndroid Build Coastguard Worker static int check_event(struct input_event *iev, int event, int code, int value)
114*49cdfc7eSAndroid Build Coastguard Worker {
115*49cdfc7eSAndroid Build Coastguard Worker 	return iev->type == event && iev->code == code && iev->value == value;
116*49cdfc7eSAndroid Build Coastguard Worker }
117*49cdfc7eSAndroid Build Coastguard Worker 
read_events(void)118*49cdfc7eSAndroid Build Coastguard Worker static void read_events(void)
119*49cdfc7eSAndroid Build Coastguard Worker {
120*49cdfc7eSAndroid Build Coastguard Worker 	int rd = read(fd2, events, sizeof(events));
121*49cdfc7eSAndroid Build Coastguard Worker 	if (rd < 0)
122*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK | TERRNO, cleanup, "read() failed");
123*49cdfc7eSAndroid Build Coastguard Worker 
124*49cdfc7eSAndroid Build Coastguard Worker 	if (rd == 0)
125*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, cleanup, "Failed to read events");
126*49cdfc7eSAndroid Build Coastguard Worker 
127*49cdfc7eSAndroid Build Coastguard Worker 	if (rd % sizeof(struct input_event) != 0) {
128*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, cleanup, "read size %i not multiple of %zu",
129*49cdfc7eSAndroid Build Coastguard Worker 		         rd, sizeof(struct input_event));
130*49cdfc7eSAndroid Build Coastguard Worker 	}
131*49cdfc7eSAndroid Build Coastguard Worker 
132*49cdfc7eSAndroid Build Coastguard Worker 	ev_iter = 0;
133*49cdfc7eSAndroid Build Coastguard Worker 	num_events = rd / sizeof(struct input_event);
134*49cdfc7eSAndroid Build Coastguard Worker }
135*49cdfc7eSAndroid Build Coastguard Worker 
have_events(void)136*49cdfc7eSAndroid Build Coastguard Worker static int have_events(void)
137*49cdfc7eSAndroid Build Coastguard Worker {
138*49cdfc7eSAndroid Build Coastguard Worker 	return num_events && ev_iter < num_events;
139*49cdfc7eSAndroid Build Coastguard Worker }
140*49cdfc7eSAndroid Build Coastguard Worker 
next_event(void)141*49cdfc7eSAndroid Build Coastguard Worker static struct input_event *next_event(void)
142*49cdfc7eSAndroid Build Coastguard Worker {
143*49cdfc7eSAndroid Build Coastguard Worker 	if (!have_events())
144*49cdfc7eSAndroid Build Coastguard Worker 		read_events();
145*49cdfc7eSAndroid Build Coastguard Worker 
146*49cdfc7eSAndroid Build Coastguard Worker 	return &events[ev_iter++];
147*49cdfc7eSAndroid Build Coastguard Worker }
148*49cdfc7eSAndroid Build Coastguard Worker 
parse_autorepeat_config(struct input_event * iev)149*49cdfc7eSAndroid Build Coastguard Worker static int parse_autorepeat_config(struct input_event *iev)
150*49cdfc7eSAndroid Build Coastguard Worker {
151*49cdfc7eSAndroid Build Coastguard Worker 	if (!check_event_code(iev, EV_REP, REP_DELAY)) {
152*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL,
153*49cdfc7eSAndroid Build Coastguard Worker 			 "Didn't get EV_REP configuration with code REP_DELAY");
154*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
155*49cdfc7eSAndroid Build Coastguard Worker 	}
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker 	if (!check_event_code(next_event(), EV_REP, REP_PERIOD)) {
158*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL,
159*49cdfc7eSAndroid Build Coastguard Worker 			 "Didn't get EV_REP configuration with code REP_PERIOD");
160*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
161*49cdfc7eSAndroid Build Coastguard Worker 	}
162*49cdfc7eSAndroid Build Coastguard Worker 
163*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker 
parse_key(struct input_event * iev)166*49cdfc7eSAndroid Build Coastguard Worker static int parse_key(struct input_event *iev)
167*49cdfc7eSAndroid Build Coastguard Worker {
168*49cdfc7eSAndroid Build Coastguard Worker 	int autorep_count = 0;
169*49cdfc7eSAndroid Build Coastguard Worker 
170*49cdfc7eSAndroid Build Coastguard Worker 	if (!check_event(iev, EV_KEY, KEY_X, 1) || !check_sync_event(next_event())) {
171*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL, "Didn't get expected key press for KEY_X");
172*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
173*49cdfc7eSAndroid Build Coastguard Worker 	}
174*49cdfc7eSAndroid Build Coastguard Worker 
175*49cdfc7eSAndroid Build Coastguard Worker 	iev = next_event();
176*49cdfc7eSAndroid Build Coastguard Worker 	while (check_event(iev, EV_KEY, KEY_X, 2) && check_sync_event(next_event())) {
177*49cdfc7eSAndroid Build Coastguard Worker 		autorep_count++;
178*49cdfc7eSAndroid Build Coastguard Worker 		iev = next_event();
179*49cdfc7eSAndroid Build Coastguard Worker 	}
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 	/* make sure we have at least one auto-repeated key event */
182*49cdfc7eSAndroid Build Coastguard Worker 	if (!autorep_count) {
183*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL,
184*49cdfc7eSAndroid Build Coastguard Worker 			 "Didn't get autorepeat events for the key - KEY_X");
185*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
186*49cdfc7eSAndroid Build Coastguard Worker 	}
187*49cdfc7eSAndroid Build Coastguard Worker 
188*49cdfc7eSAndroid Build Coastguard Worker 	if (!check_event(iev, EV_KEY, KEY_X, 0) || !check_sync_event(next_event())) {
189*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL,
190*49cdfc7eSAndroid Build Coastguard Worker 			 "Didn't get expected key release for KEY_X");
191*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
192*49cdfc7eSAndroid Build Coastguard Worker 	}
193*49cdfc7eSAndroid Build Coastguard Worker 
194*49cdfc7eSAndroid Build Coastguard Worker 	tst_resm(TINFO,
195*49cdfc7eSAndroid Build Coastguard Worker 		 "Received %d repititions for KEY_X", autorep_count);
196*49cdfc7eSAndroid Build Coastguard Worker 
197*49cdfc7eSAndroid Build Coastguard Worker 	return 1;
198*49cdfc7eSAndroid Build Coastguard Worker }
199*49cdfc7eSAndroid Build Coastguard Worker 
check_events(void)200*49cdfc7eSAndroid Build Coastguard Worker static int check_events(void)
201*49cdfc7eSAndroid Build Coastguard Worker {
202*49cdfc7eSAndroid Build Coastguard Worker 	struct input_event *iev;
203*49cdfc7eSAndroid Build Coastguard Worker 	int ret = 0;
204*49cdfc7eSAndroid Build Coastguard Worker 	int rep_config_done = 0;
205*49cdfc7eSAndroid Build Coastguard Worker 	int rep_keys_done = 0;
206*49cdfc7eSAndroid Build Coastguard Worker 
207*49cdfc7eSAndroid Build Coastguard Worker 	read_events();
208*49cdfc7eSAndroid Build Coastguard Worker 
209*49cdfc7eSAndroid Build Coastguard Worker 	while (have_events()) {
210*49cdfc7eSAndroid Build Coastguard Worker 		iev = next_event();
211*49cdfc7eSAndroid Build Coastguard Worker 		switch (iev->type) {
212*49cdfc7eSAndroid Build Coastguard Worker 		case EV_REP:
213*49cdfc7eSAndroid Build Coastguard Worker 			ret = parse_autorepeat_config(iev);
214*49cdfc7eSAndroid Build Coastguard Worker 			rep_config_done = 1;
215*49cdfc7eSAndroid Build Coastguard Worker 			break;
216*49cdfc7eSAndroid Build Coastguard Worker 		case EV_KEY:
217*49cdfc7eSAndroid Build Coastguard Worker 			ret = parse_key(iev);
218*49cdfc7eSAndroid Build Coastguard Worker 			rep_keys_done = 1;
219*49cdfc7eSAndroid Build Coastguard Worker 			break;
220*49cdfc7eSAndroid Build Coastguard Worker 		default:
221*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TFAIL,
222*49cdfc7eSAndroid Build Coastguard Worker 				 "Unexpected event type '0x%04x' received",
223*49cdfc7eSAndroid Build Coastguard Worker 				iev->type);
224*49cdfc7eSAndroid Build Coastguard Worker 			ret = 0;
225*49cdfc7eSAndroid Build Coastguard Worker 			break;
226*49cdfc7eSAndroid Build Coastguard Worker 		}
227*49cdfc7eSAndroid Build Coastguard Worker 
228*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret || (rep_config_done && rep_keys_done))
229*49cdfc7eSAndroid Build Coastguard Worker 			break;
230*49cdfc7eSAndroid Build Coastguard Worker 	}
231*49cdfc7eSAndroid Build Coastguard Worker 
232*49cdfc7eSAndroid Build Coastguard Worker 	return ret;
233*49cdfc7eSAndroid Build Coastguard Worker }
234*49cdfc7eSAndroid Build Coastguard Worker 
cleanup(void)235*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
236*49cdfc7eSAndroid Build Coastguard Worker {
237*49cdfc7eSAndroid Build Coastguard Worker 	if (fd2 > 0 && close(fd2))
238*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TWARN | TERRNO, "close(fd2) failed");
239*49cdfc7eSAndroid Build Coastguard Worker 
240*49cdfc7eSAndroid Build Coastguard Worker 	destroy_device(fd);
241*49cdfc7eSAndroid Build Coastguard Worker }
242