Contents of /tags/mkinitrd-6_3_0/busybox/console-tools/showkey.c
Parent Directory | Revision Log
Revision 1139 -
(show annotations)
(download)
Thu Aug 19 10:14:02 2010 UTC (14 years, 1 month ago) by niro
File MIME type: text/plain
File size: 3302 byte(s)
Thu Aug 19 10:14:02 2010 UTC (14 years, 1 month ago) by niro
File MIME type: text/plain
File size: 3302 byte(s)
tagged 'mkinitrd-6_3_0'
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * shows keys pressed. inspired by kbd package |
4 | * |
5 | * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com> |
6 | * |
7 | * Licensed under GPLv2, see file LICENSE in this tarball for details. |
8 | */ |
9 | |
10 | #include "libbb.h" |
11 | #include <linux/kd.h> |
12 | |
13 | // set raw tty mode |
14 | // also used by microcom |
15 | // libbb candidates? |
16 | static void xget1(int fd, struct termios *t, struct termios *oldt) |
17 | { |
18 | tcgetattr(fd, oldt); |
19 | *t = *oldt; |
20 | cfmakeraw(t); |
21 | } |
22 | |
23 | static int xset1(int fd, struct termios *tio, const char *device) |
24 | { |
25 | int ret = tcsetattr(fd, TCSAFLUSH, tio); |
26 | |
27 | if (ret) { |
28 | bb_perror_msg("can't tcsetattr for %s", device); |
29 | } |
30 | return ret; |
31 | } |
32 | |
33 | /* |
34 | * GLOBALS |
35 | */ |
36 | struct globals { |
37 | int kbmode; |
38 | struct termios tio, tio0; |
39 | }; |
40 | #define G (*ptr_to_globals) |
41 | #define kbmode (G.kbmode) |
42 | #define tio (G.tio) |
43 | #define tio0 (G.tio0) |
44 | #define INIT_G() do { \ |
45 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
46 | } while (0) |
47 | |
48 | |
49 | static void signal_handler(int signo) |
50 | { |
51 | // restore keyboard and console settings |
52 | xset1(STDIN_FILENO, &tio0, "stdin"); |
53 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode); |
54 | // alarmed? -> exit 0 |
55 | exit(SIGALRM == signo); |
56 | } |
57 | |
58 | int showkey_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
59 | int showkey_main(int argc UNUSED_PARAM, char **argv) |
60 | { |
61 | enum { |
62 | OPT_a = (1<<0), // display the decimal/octal/hex values of the keys |
63 | OPT_k = (1<<1), // display only the interpreted keycodes (default) |
64 | OPT_s = (1<<2), // display only the raw scan-codes |
65 | }; |
66 | |
67 | // FIXME: aks are all mutually exclusive |
68 | getopt32(argv, "aks"); |
69 | |
70 | INIT_G(); |
71 | |
72 | // get keyboard settings |
73 | xioctl(STDIN_FILENO, KDGKBMODE, &kbmode); |
74 | printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n", |
75 | kbmode == K_RAW ? "RAW" : |
76 | (kbmode == K_XLATE ? "XLATE" : |
77 | (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" : |
78 | (kbmode == K_UNICODE ? "UNICODE" : "?UNKNOWN?"))) |
79 | , (option_mask32 & OPT_a) ? "when CTRL+D pressed" : "10s after last keypress" |
80 | ); |
81 | // prepare for raw mode |
82 | xget1(STDIN_FILENO, &tio, &tio0); |
83 | // put stdin in raw mode |
84 | xset1(STDIN_FILENO, &tio, "stdin"); |
85 | |
86 | if (option_mask32 & OPT_a) { |
87 | char c; |
88 | // just read stdin char by char |
89 | while (1 == safe_read(STDIN_FILENO, &c, 1)) { |
90 | printf("%3d 0%03o 0x%02x\r\n", c, c, c); |
91 | if (04 /*CTRL-D*/ == c) |
92 | break; |
93 | } |
94 | } else { |
95 | // we should exit on any signal |
96 | bb_signals(BB_FATAL_SIGS, signal_handler); |
97 | // set raw keyboard mode |
98 | xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW)); |
99 | |
100 | // read and show scancodes |
101 | while (1) { |
102 | char buf[18]; |
103 | int i, n; |
104 | // setup 10s watchdog |
105 | alarm(10); |
106 | // read scancodes |
107 | n = read(STDIN_FILENO, buf, sizeof(buf)); |
108 | i = 0; |
109 | while (i < n) { |
110 | char c = buf[i]; |
111 | // show raw scancodes ordered? -> |
112 | if (option_mask32 & OPT_s) { |
113 | printf("0x%02x ", buf[i++]); |
114 | // show interpreted scancodes (default) ? -> |
115 | } else { |
116 | int kc; |
117 | if (i+2 < n && (c & 0x7f) == 0 |
118 | && (buf[i+1] & 0x80) != 0 |
119 | && (buf[i+2] & 0x80) != 0) { |
120 | kc = ((buf[i+1] & 0x7f) << 7) | (buf[i+2] & 0x7f); |
121 | i += 3; |
122 | } else { |
123 | kc = (c & 0x7f); |
124 | i++; |
125 | } |
126 | printf("keycode %3d %s", kc, (c & 0x80) ? "release" : "press"); |
127 | } |
128 | } |
129 | puts("\r"); |
130 | } |
131 | } |
132 | |
133 | // cleanup |
134 | signal_handler(SIGALRM); |
135 | |
136 | // should never be here! |
137 | return EXIT_SUCCESS; |
138 | } |