1 /*
2 * Copyright (c) 2015 Cedric Hnyda <chnyda@suse.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /*
20 * Create a virtual device (mouse), send events to /dev/uinput
21 * and check that the events are well received in /dev/input/eventX
22 */
23
24 #include <linux/input.h>
25
26 #include "input_helper.h"
27 #include "test.h"
28 #include "safe_macros.h"
29 #include "lapi/fcntl.h"
30
31 #define NB_TEST 20
32
33 static void setup(void);
34 static void send_events(void);
35 static int verify_data(struct input_event *iev, int nb);
36 static int check_events(void);
37 static void cleanup(void);
38
39 static int fd;
40 static int fd2;
41
42 char *TCID = "input01";
43
main(int ac,char ** av)44 int main(int ac, char **av)
45 {
46 int lc;
47 int pid;
48
49 tst_parse_opts(ac, av, NULL, NULL);
50
51 setup();
52
53 for (lc = 0; TEST_LOOPING(lc); ++lc) {
54 pid = tst_fork();
55
56 switch (pid) {
57 case 0:
58 send_events();
59 exit(0);
60 case -1:
61 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
62 default:
63 if (check_events())
64 tst_resm(TFAIL, "Wrong data read from eventX");
65 else
66 tst_resm(TPASS, "Data received from eventX");
67 break;
68 }
69
70 SAFE_WAITPID(NULL, pid, NULL, 0);
71 }
72
73 cleanup();
74 tst_exit();
75 }
76
setup(void)77 static void setup(void)
78 {
79 tst_require_root();
80
81 fd = open_uinput();
82 setup_mouse_events(fd);
83 create_device(fd);
84
85 fd2 = open_device();
86 }
87
send_events(void)88 static void send_events(void)
89 {
90 int nb;
91
92 for (nb = 0; nb < NB_TEST; ++nb) {
93 send_rel_move(fd, 10, 1);
94 usleep(1000);
95 }
96 }
97
check_events(void)98 static int check_events(void)
99 {
100 int nb, rd;
101 unsigned int i;
102 struct input_event iev[64];
103
104 nb = 0;
105
106 while (nb < NB_TEST * 3) {
107 rd = read(fd2, iev, sizeof(iev));
108
109 if (rd < 0)
110 tst_brkm(TBROK | TERRNO, cleanup, "read()");
111
112 if (rd == 0 || rd % sizeof(struct input_event)) {
113 tst_resm(TINFO, "read() returned unexpected %i", rd);
114 return 1;
115 }
116
117 for (i = 0; i < rd / sizeof(struct input_event); i++) {
118 if (verify_data(&iev[i], nb++))
119 return 1;
120 }
121 }
122
123 return 0;
124 }
125
verify_data(struct input_event * iev,int nb)126 static int verify_data(struct input_event *iev, int nb)
127 {
128 if (nb % 3 == 0) {
129 if (iev->type != EV_REL) {
130 tst_resm(TINFO,
131 "%i: Unexpected event type %i expected %i",
132 nb, iev->type, EV_REL);
133 return 1;
134 }
135
136 if (iev->code != REL_X)
137 return 1;
138
139 if (iev->value != 10)
140 return 1;
141
142 return 0;
143 }
144
145 if (nb % 3 == 1) {
146 if (iev->type != EV_REL) {
147 tst_resm(TINFO,
148 "%i: Unexpected event type %i expected %i",
149 nb, iev->type, EV_REL);
150 return 1;
151 }
152
153 if (iev->code != REL_Y)
154 return 1;
155
156 if (iev->value != 1)
157 return 1;
158
159 return 0;
160 }
161
162 if (nb % 3 == 2) {
163 if (iev->type != EV_SYN) {
164 tst_resm(TINFO,
165 "%i: Unexpected event type %i expected %i",
166 nb, iev->type, EV_SYN);
167 return 1;
168 }
169
170 if (iev->code != 0)
171 return 1;
172
173 if (iev->value != 0)
174 return 1;
175
176 return 0;
177 }
178 return 1;
179 }
180
cleanup(void)181 static void cleanup(void)
182 {
183 if (fd2 > 0 && close(fd2))
184 tst_resm(TWARN | TERRNO, "close(fd2)");
185
186 destroy_device(fd);
187 }
188