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, activate auto-repeat and 21 * and check that auto repeat is working 22 */ 23 24 #include <linux/input.h> 25 #include <linux/uinput.h> 26 #include <linux/kd.h> 27 28 #include "test.h" 29 #include "safe_macros.h" 30 #include "lapi/fcntl.h" 31 #include "input_helper.h" 32 33 static void setup(void); 34 static void send_events(void); 35 static int check_events(void); 36 static void cleanup(void); 37 38 static int fd; 39 static int fd2; 40 struct input_event events[64]; 41 static int num_events; 42 static int ev_iter; 43 44 char *TCID = "input06"; 45 46 int main(int ac, char **av) 47 { 48 int lc; 49 int pid; 50 51 tst_parse_opts(ac, av, NULL, NULL); 52 53 setup(); 54 55 for (lc = 0; TEST_LOOPING(lc); ++lc) { 56 pid = tst_fork(); 57 58 switch (pid) { 59 case 0: 60 send_events(); 61 exit(0); 62 case -1: 63 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed"); 64 default: 65 if (!check_events()) 66 tst_resm(TFAIL, 67 "Wrong data received in eventX"); 68 else 69 tst_resm(TPASS, "Data received in eventX"); 70 break; 71 } 72 73 SAFE_WAITPID(NULL, pid, NULL, 0); 74 } 75 76 cleanup(); 77 tst_exit(); 78 } 79 80 static void setup(void) 81 { 82 tst_require_root(); 83 84 fd = open_uinput(); 85 86 SAFE_IOCTL(NULL, fd, UI_SET_EVBIT, EV_KEY); 87 SAFE_IOCTL(NULL, fd, UI_SET_EVBIT, EV_REP); 88 SAFE_IOCTL(NULL, fd, UI_SET_KEYBIT, KEY_X); 89 90 create_device(fd); 91 92 fd2 = open_device(); 93 SAFE_IOCTL(NULL, fd2, EVIOCGRAB, 1); 94 } 95 96 static void send_events(void) 97 { 98 send_event(fd, EV_KEY, KEY_X, 1); 99 send_event(fd, EV_SYN, 0, 0); 100 101 /* 102 * Sleep long enough to keep the key pressed for some time 103 * (auto-repeat). Default kernel delay to start auto-repeat is 250ms 104 * and the period is 33ms. So, we wait for a generous 500ms to make 105 * sure we get the auto-repeated keys 106 */ 107 usleep(500000); 108 109 send_event(fd, EV_KEY, KEY_X, 0); 110 send_event(fd, EV_SYN, 0, 0); 111 } 112 113 static int check_event(struct input_event *iev, int event, int code, int value) 114 { 115 return iev->type == event && iev->code == code && iev->value == value; 116 } 117 118 static void read_events(void) 119 { 120 int rd = read(fd2, events, sizeof(events)); 121 if (rd < 0) 122 tst_brkm(TBROK | TERRNO, cleanup, "read() failed"); 123 124 if (rd == 0) 125 tst_brkm(TBROK, cleanup, "Failed to read events"); 126 127 if (rd % sizeof(struct input_event) != 0) { 128 tst_brkm(TBROK, cleanup, "read size %i not multiple of %zu", 129 rd, sizeof(struct input_event)); 130 } 131 132 ev_iter = 0; 133 num_events = rd / sizeof(struct input_event); 134 } 135 136 static int have_events(void) 137 { 138 return num_events && ev_iter < num_events; 139 } 140 141 static struct input_event *next_event(void) 142 { 143 if (!have_events()) 144 read_events(); 145 146 return &events[ev_iter++]; 147 } 148 149 static int parse_autorepeat_config(struct input_event *iev) 150 { 151 if (!check_event_code(iev, EV_REP, REP_DELAY)) { 152 tst_resm(TFAIL, 153 "Didn't get EV_REP configuration with code REP_DELAY"); 154 return 0; 155 } 156 157 if (!check_event_code(next_event(), EV_REP, REP_PERIOD)) { 158 tst_resm(TFAIL, 159 "Didn't get EV_REP configuration with code REP_PERIOD"); 160 return 0; 161 } 162 163 return 1; 164 } 165 166 static int parse_key(struct input_event *iev) 167 { 168 int autorep_count = 0; 169 170 if (!check_event(iev, EV_KEY, KEY_X, 1) || !check_sync_event(next_event())) { 171 tst_resm(TFAIL, "Didn't get expected key press for KEY_X"); 172 return 0; 173 } 174 175 iev = next_event(); 176 while (check_event(iev, EV_KEY, KEY_X, 2) && check_sync_event(next_event())) { 177 autorep_count++; 178 iev = next_event(); 179 } 180 181 /* make sure we have atleast one auto-repeated key event */ 182 if (!autorep_count) { 183 tst_resm(TFAIL, 184 "Didn't get autorepeat events for the key - KEY_X"); 185 return 0; 186 } 187 188 if (!check_event(iev, EV_KEY, KEY_X, 0) || !check_sync_event(next_event())) { 189 tst_resm(TFAIL, 190 "Didn't get expected key release for KEY_X"); 191 return 0; 192 } 193 194 tst_resm(TINFO, 195 "Received %d repititions for KEY_X", autorep_count); 196 197 return 1; 198 } 199 200 static int check_events(void) 201 { 202 struct input_event *iev; 203 int ret = 0; 204 int rep_config_done = 0; 205 int rep_keys_done = 0; 206 207 read_events(); 208 209 while (have_events()) { 210 iev = next_event(); 211 switch (iev->type) { 212 case EV_REP: 213 ret = parse_autorepeat_config(iev); 214 rep_config_done = 1; 215 break; 216 case EV_KEY: 217 ret = parse_key(iev); 218 rep_keys_done = 1; 219 break; 220 default: 221 tst_resm(TFAIL, 222 "Unexpected event type '0x%04x' received", 223 iev->type); 224 ret = 0; 225 break; 226 } 227 228 if (!ret || (rep_config_done && rep_keys_done)) 229 break; 230 } 231 232 return ret; 233 } 234 235 static void cleanup(void) 236 { 237 if (fd2 > 0 && close(fd2)) 238 tst_resm(TWARN | TERRNO, "close(fd2) failed"); 239 240 destroy_device(fd); 241 } 242