make minix lwip make explicit use of 'int'
[minix3.git] / test / scancodes / test-scancodes.c
blob599bc2a12608ee131a55f2ad1373de32bd966120
1 #include <errno.h>
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <termios.h>
7 #include <unistd.h>
9 /* list of scancodes to demonstrate whether the keycodes are correct;
10 * source: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
12 static char *keydescr[] = {
13 NULL, /* 0x00 */
14 "Esc", /* 0x01 */
15 "1!", /* 0x02 */
16 "2@", /* 0x03 */
17 "3#", /* 0x04 */
18 "4$", /* 0x05 */
19 "5%", /* 0x06 */
20 "6^", /* 0x07 */
21 "7&", /* 0x08 */
22 "8*", /* 0x09 */
23 "9(", /* 0x0a */
24 "0)", /* 0x0b */
25 "-_", /* 0x0c */
26 "=+", /* 0x0d */
27 "Backspace", /* 0x0e */
28 "Tab", /* 0x0f */
29 "Q", /* 0x10 */
30 "W", /* 0x11 */
31 "E", /* 0x12 */
32 "R", /* 0x13 */
33 "T", /* 0x14 */
34 "Y", /* 0x15 */
35 "U", /* 0x16 */
36 "I", /* 0x17 */
37 "O", /* 0x18 */
38 "P", /* 0x19 */
39 "[{", /* 0x1a */
40 "]}", /* 0x1b */
41 "Enter", /* 0x1c */
42 "LCtrl", /* 0x1d */
43 "A", /* 0x1e */
44 "S", /* 0x1f */
45 "D", /* 0x20 */
46 "F", /* 0x21 */
47 "G", /* 0x22 */
48 "H", /* 0x23 */
49 "J", /* 0x24 */
50 "K", /* 0x25 */
51 "L", /* 0x26 */
52 ";:", /* 0x27 */
53 "'\"", /* 0x28 */
54 "`~", /* 0x29 */
55 "LShift", /* 0x2a */
56 "\\|", /* 0x2b */
57 "Z", /* 0x2c */
58 "X", /* 0x2d */
59 "C", /* 0x2e */
60 "V", /* 0x2f */
61 "B", /* 0x30 */
62 "N", /* 0x31 */
63 "M", /* 0x32 */
64 ",<", /* 0x33 */
65 ".>", /* 0x34 */
66 "/?", /* 0x35 */
67 "RShift", /* 0x36 */
68 "Keypad-*", /* 0x37 */
69 "LAlt", /* 0x38 */
70 "Space bar", /* 0x39 */
71 "CapsLock", /* 0x3a */
72 "F1", /* 0x3b */
73 "F2", /* 0x3c */
74 "F3", /* 0x3d */
75 "F4", /* 0x3e */
76 "F5", /* 0x3f */
77 "F6", /* 0x40 */
78 "F7", /* 0x41 */
79 "F8", /* 0x42 */
80 "F9", /* 0x43 */
81 "F10", /* 0x44 */
82 "NumLock", /* 0x45 */
83 "ScrollLock", /* 0x46 */
84 "Keypad-7/Home",/* 0x47 */
85 "Keypad-8/Up", /* 0x48 */
86 "Keypad-9/PgUp",/* 0x49 */
87 "Keypad--", /* 0x4a */
88 "Keypad-4/Left",/* 0x4b */
89 "Keypad-5", /* 0x4c */
90 "Keypad-6/Right",/* 0x4d */
91 "Keypad-+", /* 0x4e */
92 "Keypad-1/End", /* 0x4f */
93 "Keypad-2/Down",/* 0x50 */
94 "Keypad-3/PgDn",/* 0x51 */
95 "Keypad-0/Ins", /* 0x52 */
96 "Keypad-./Del", /* 0x53 */
97 "Alt-SysRq", /* 0x54 */
98 NULL, /* 0x55 */
99 NULL, /* 0x56 */
100 "F11", /* 0x57 */
101 "F12", /* 0x58 */
102 NULL, /* 0x59 */
103 NULL, /* 0x5a */
104 NULL, /* 0x5b */
105 NULL, /* 0x5c */
106 NULL, /* 0x5d */
107 NULL, /* 0x5e */
108 NULL, /* 0x5f */
109 NULL, /* 0x60 */
110 NULL, /* 0x61 */
111 NULL, /* 0x62 */
112 NULL, /* 0x63 */
113 NULL, /* 0x64 */
114 NULL, /* 0x65 */
115 NULL, /* 0x66 */
116 NULL, /* 0x67 */
117 NULL, /* 0x68 */
118 NULL, /* 0x69 */
119 NULL, /* 0x6a */
120 NULL, /* 0x6b */
121 NULL, /* 0x6c */
122 NULL, /* 0x6d */
123 NULL, /* 0x6e */
124 NULL, /* 0x6f */
125 NULL, /* 0x70 */
126 NULL, /* 0x71 */
127 NULL, /* 0x72 */
128 NULL, /* 0x73 */
129 NULL, /* 0x74 */
130 NULL, /* 0x75 */
131 NULL, /* 0x76 */
132 NULL, /* 0x77 */
133 NULL, /* 0x78 */
134 NULL, /* 0x79 */
135 NULL, /* 0x7a */
136 NULL, /* 0x7b */
137 NULL, /* 0x7c */
138 NULL, /* 0x7d */
139 NULL, /* 0x7e */
140 NULL, /* 0x7f */
143 static char *keydescresc[] = {
144 NULL, /* 0xe0 0x00 */
145 NULL, /* 0xe0 0x01 */
146 NULL, /* 0xe0 0x02 */
147 NULL, /* 0xe0 0x03 */
148 NULL, /* 0xe0 0x04 */
149 NULL, /* 0xe0 0x05 */
150 NULL, /* 0xe0 0x06 */
151 NULL, /* 0xe0 0x07 */
152 NULL, /* 0xe0 0x08 */
153 NULL, /* 0xe0 0x09 */
154 NULL, /* 0xe0 0x0a */
155 NULL, /* 0xe0 0x0b */
156 NULL, /* 0xe0 0x0c */
157 NULL, /* 0xe0 0x0d */
158 NULL, /* 0xe0 0x0e */
159 NULL, /* 0xe0 0x0f */
160 NULL, /* 0xe0 0x10 */
161 NULL, /* 0xe0 0x11 */
162 NULL, /* 0xe0 0x12 */
163 NULL, /* 0xe0 0x13 */
164 NULL, /* 0xe0 0x14 */
165 NULL, /* 0xe0 0x15 */
166 NULL, /* 0xe0 0x16 */
167 NULL, /* 0xe0 0x17 */
168 NULL, /* 0xe0 0x18 */
169 NULL, /* 0xe0 0x19 */
170 NULL, /* 0xe0 0x1a */
171 NULL, /* 0xe0 0x1b */
172 "Keypad Enter", /* 0xe0 0x1c */
173 "RCtrl", /* 0xe0 0x1d */
174 NULL, /* 0xe0 0x1e */
175 NULL, /* 0xe0 0x1f */
176 NULL, /* 0xe0 0x20 */
177 NULL, /* 0xe0 0x21 */
178 NULL, /* 0xe0 0x22 */
179 NULL, /* 0xe0 0x23 */
180 NULL, /* 0xe0 0x24 */
181 NULL, /* 0xe0 0x25 */
182 NULL, /* 0xe0 0x26 */
183 NULL, /* 0xe0 0x27 */
184 NULL, /* 0xe0 0x28 */
185 NULL, /* 0xe0 0x29 */
186 "fake LShift", /* 0xe0 0x2a */
187 NULL, /* 0xe0 0x2b */
188 NULL, /* 0xe0 0x2c */
189 NULL, /* 0xe0 0x2d */
190 NULL, /* 0xe0 0x2e */
191 NULL, /* 0xe0 0x2f */
192 NULL, /* 0xe0 0x30 */
193 NULL, /* 0xe0 0x31 */
194 NULL, /* 0xe0 0x32 */
195 NULL, /* 0xe0 0x33 */
196 NULL, /* 0xe0 0x34 */
197 "Keypad-/", /* 0xe0 0x35 */
198 "fake RShift", /* 0xe0 0x36 */
199 "Ctrl-PrtScn", /* 0xe0 0x37 */
200 "RAlt", /* 0xe0 0x38 */
201 NULL, /* 0xe0 0x39 */
202 NULL, /* 0xe0 0x3a */
203 NULL, /* 0xe0 0x3b */
204 NULL, /* 0xe0 0x3c */
205 NULL, /* 0xe0 0x3d */
206 NULL, /* 0xe0 0x3e */
207 NULL, /* 0xe0 0x3f */
208 NULL, /* 0xe0 0x40 */
209 NULL, /* 0xe0 0x41 */
210 NULL, /* 0xe0 0x42 */
211 NULL, /* 0xe0 0x43 */
212 NULL, /* 0xe0 0x44 */
213 NULL, /* 0xe0 0x45 */
214 "Ctrl-Break", /* 0xe0 0x46 */
215 "Grey Home", /* 0xe0 0x47 */
216 "Grey Up", /* 0xe0 0x48 */
217 "Grey PgUp", /* 0xe0 0x49 */
218 NULL, /* 0xe0 0x4a */
219 "Grey Left", /* 0xe0 0x4b */
220 NULL, /* 0xe0 0x4c */
221 "Grey Right", /* 0xe0 0x4d */
222 NULL, /* 0xe0 0x4e */
223 "Grey End", /* 0xe0 0x4f */
224 "Grey Down", /* 0xe0 0x50 */
225 "Grey PgDn", /* 0xe0 0x51 */
226 "Grey Insert", /* 0xe0 0x52 */
227 "Grey Delete", /* 0xe0 0x53 */
228 NULL, /* 0xe0 0x54 */
229 NULL, /* 0xe0 0x55 */
230 NULL, /* 0xe0 0x56 */
231 NULL, /* 0xe0 0x57 */
232 NULL, /* 0xe0 0x58 */
233 NULL, /* 0xe0 0x59 */
234 NULL, /* 0xe0 0x5a */
235 "LeftWindow", /* 0xe0 0x5b */
236 "RightWindow", /* 0xe0 0x5c */
237 "Menu", /* 0xe0 0x5d */
238 "Power", /* 0xe0 0x5e */
239 "Sleep", /* 0xe0 0x5f */
240 NULL, /* 0xe0 0x60 */
241 NULL, /* 0xe0 0x61 */
242 NULL, /* 0xe0 0x62 */
243 "Wake", /* 0xe0 0x63 */
244 NULL, /* 0xe0 0x64 */
245 NULL, /* 0xe0 0x65 */
246 NULL, /* 0xe0 0x66 */
247 NULL, /* 0xe0 0x67 */
248 NULL, /* 0xe0 0x68 */
249 NULL, /* 0xe0 0x69 */
250 NULL, /* 0xe0 0x6a */
251 NULL, /* 0xe0 0x6b */
252 NULL, /* 0xe0 0x6c */
253 NULL, /* 0xe0 0x6d */
254 NULL, /* 0xe0 0x6e */
255 NULL, /* 0xe0 0x6f */
256 NULL, /* 0xe0 0x70 */
257 NULL, /* 0xe0 0x71 */
258 NULL, /* 0xe0 0x72 */
259 NULL, /* 0xe0 0x73 */
260 NULL, /* 0xe0 0x74 */
261 NULL, /* 0xe0 0x75 */
262 NULL, /* 0xe0 0x76 */
263 NULL, /* 0xe0 0x77 */
264 NULL, /* 0xe0 0x78 */
265 NULL, /* 0xe0 0x79 */
266 NULL, /* 0xe0 0x7a */
267 NULL, /* 0xe0 0x7b */
268 NULL, /* 0xe0 0x7c */
269 NULL, /* 0xe0 0x7d */
270 NULL, /* 0xe0 0x7e */
271 NULL, /* 0xe0 0x7f */
274 #define CHECK(r) check((r), #r, __FILE__, __LINE__)
276 int check(long r, const char *expr, const char *file, int line)
278 char buffer[256];
279 if (r < 0) {
280 snprintf(buffer, sizeof(buffer), "%s:%d: %s: result %ld, %s",
281 file, line, expr, r, strerror(errno));
282 exit(-1);
284 return r;
287 #define SCODE_ESC 0xe0
288 #define SCODE_BREAK 0x80
290 static int testscancode(int fd)
292 static int escape, lctrl, rctrl;
293 ssize_t count;
294 unsigned char scode;
295 char *scodedescr;
297 /* read a scancode and test for EOF */
298 CHECK(count = read(fd, &scode, sizeof(scode)));
299 if (count < sizeof(scode)) {
300 return 0;
303 /* print scancode */
304 printf("0x%.2x ", scode);
305 fflush(stdout);
307 /* test for escape */
308 if (!escape && scode == SCODE_ESC) {
309 escape = 1;
310 return 1;
313 /* describe scancode */
314 scodedescr = (escape ? keydescresc : keydescr)[scode & ~SCODE_BREAK];
315 if (scodedescr)
316 printf("[%s] ", scodedescr);
318 if (scode & SCODE_BREAK)
319 printf("up\n");
320 else
321 printf("down\n");
323 fflush(stdout);
325 /* exit on ctrl-C */
326 if ((scode & ~SCODE_BREAK) == 0x1d) {
327 if (escape)
328 rctrl = !(scode & SCODE_BREAK);
329 else
330 lctrl = !(scode & SCODE_BREAK);
332 if ((lctrl || rctrl) && !escape && scode == 0x2e) {
333 return 0;
336 /* next key is not escaped */
337 escape = 0;
339 return 1;
342 static volatile int terminate;
344 static void set_terminate(int signum)
346 terminate = signum;
349 static int testscancodes(int fd)
351 struct termios termios_old, termios_scan;
353 /* this test only works with a TTY as stdin */
354 if (!CHECK(isatty(fd))) {
355 printf("warning: this test can only be run from a console\n");
356 return 0;
359 /* catch fatal signals to restore the console */
360 CHECK((signal(SIGHUP, set_terminate) == SIG_ERR) ? -1 : 0);
361 CHECK((signal(SIGINT, set_terminate) == SIG_ERR) ? -1 : 0);
362 CHECK((signal(SIGQUIT, set_terminate) == SIG_ERR) ? -1 : 0);
363 CHECK((signal(SIGABRT, set_terminate) == SIG_ERR) ? -1 : 0);
364 CHECK((signal(SIGPIPE, set_terminate) == SIG_ERR) ? -1 : 0);
365 CHECK((signal(SIGTERM, set_terminate) == SIG_ERR) ? -1 : 0);
367 /* configure tty in raw input mode with scancodes and no echo */
368 CHECK(tcgetattr(fd, &termios_old));
369 termios_scan = termios_old;
370 termios_scan.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR);
371 termios_scan.c_iflag &= ~(INLCR | INPCK | ISTRIP);
372 termios_scan.c_iflag &= ~(IXOFF | IXON | PARMRK);
373 termios_scan.c_iflag |= SCANCODES;
374 termios_scan.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
375 termios_scan.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH);
376 CHECK(tcsetattr(fd, TCSANOW, &termios_scan));
378 /* test: is scancode input supported? */
379 CHECK(tcgetattr(fd, &termios_scan));
380 if (termios_scan.c_iflag & SCANCODES) {
381 while (!terminate && CHECK(testscancode(fd))) ;
382 } else {
383 printf("warning: cannot enable SCANCODES "
384 "(are you running from a console?)\n");
387 /* report if closed by a signal */
388 if (terminate) {
389 printf("received signal %d, shutting down\n", terminate);
392 /* restore original input mode */
393 CHECK(tcsetattr(fd, TCSANOW, &termios_old));
395 /* clear buffered input */
396 CHECK(tcflush(fd, TCIFLUSH));
399 int main(void)
401 printf("try out some keys to find out whether SCANCODES works\n");
402 printf("press CTRL+C to end this test\n");
403 printf("please note that this test only works from a console tty\n");
405 /* perform test using stdin */
406 if (testscancodes(STDIN_FILENO) < 0)
407 return -1;
408 else
409 return 0;