1 /* 2 * Copyright (c) 2015 Cedric Hnyda <chnyda (at) 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 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 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 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 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 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 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