~ubuntu-branches/ubuntu/karmic/busybox/karmic

« back to all changes in this revision

Viewing changes to console-tools/showkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2009-06-19 11:41:15 UTC
  • mfrom: (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090619114115-asrhxtx2khmkjnhd
Tags: 1:1.13.3-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - [udeb] Enable chvt, dd conv=notrunc, getopt (and -l), killall,
    losetup, mktemp, NFS mount, od, ping, stat, and remote syslog.
  - [deb] Enable mdev.
  - Enable 'mount -f' and mount helpers for all targets.
  - Add busybox-initramfs.
  - mkswap-uuid.patch: Set UUIDs on swap areas.
  - test-bin.patch: Move test and friends to /bin.
  - mount-helper-fixes.patch: Add proper support for mount -i (don't use
    external mount helper), and trivial support for umount -i although
    busybox umount doesn't support external helpers yet. Fix handling of
    mount -f and -n.
  - getopt-long-only.patch: Allow 'getopt -l' to be enabled independently
    of the whole of CONFIG_GETOPT_LONG, so that it can be enabled more
    cheaply.
  - printf-errors.patch: Exit non-zero on conversion errors.
* procps-kernel-threads.patch: Drop. We haven't needed this since we
  rewrote casper as an initramfs-tools module anyway, and the bit of this
  patch that actually does anything was dropped in 1:1.01-4ubuntu1 so we
  clearly don't need the rest of it!
* [initramfs] Include wc for the benefit of live-initramfs (LP: #387944).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}