From: Erik van der Kouwe Date: Thu, 15 Apr 2010 06:55:32 +0000 (+0000) Subject: Add scancode reading capability to TTY X-Git-Tag: v3.1.7~141 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch08.html?a=commitdiff_plain;h=32f43d7571978be29ceb2d6abc46f766fef98874;p=minix.git Add scancode reading capability to TTY --- diff --git a/test/scancodes/Makefile b/test/scancodes/Makefile new file mode 100644 index 000000000..4d0f0d51c --- /dev/null +++ b/test/scancodes/Makefile @@ -0,0 +1,10 @@ +all: test-scancodes + +clean: + rm -f *.o test-scancodes + +test-scancodes: test-scancodes.o + +test-scancodes.o: test-scancodes.c + + diff --git a/test/scancodes/test-scancodes.c b/test/scancodes/test-scancodes.c new file mode 100644 index 000000000..e03cd05b0 --- /dev/null +++ b/test/scancodes/test-scancodes.c @@ -0,0 +1,408 @@ +#define _MINIX + +#include +#include +#include +#include +#include +#include +#include + +/* list of scancodes to demonstrate whether the keycodes are correct; + * source: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html + */ +static char *keydescr[] = { + NULL, /* 0x00 */ + "Esc", /* 0x01 */ + "1!", /* 0x02 */ + "2@", /* 0x03 */ + "3#", /* 0x04 */ + "4$", /* 0x05 */ + "5%", /* 0x06 */ + "6^", /* 0x07 */ + "7&", /* 0x08 */ + "8*", /* 0x09 */ + "9(", /* 0x0a */ + "0)", /* 0x0b */ + "-_", /* 0x0c */ + "=+", /* 0x0d */ + "Backspace", /* 0x0e */ + "Tab", /* 0x0f */ + "Q", /* 0x10 */ + "W", /* 0x11 */ + "E", /* 0x12 */ + "R", /* 0x13 */ + "T", /* 0x14 */ + "Y", /* 0x15 */ + "U", /* 0x16 */ + "I", /* 0x17 */ + "O", /* 0x18 */ + "P", /* 0x19 */ + "[{", /* 0x1a */ + "]}", /* 0x1b */ + "Enter", /* 0x1c */ + "LCtrl", /* 0x1d */ + "A", /* 0x1e */ + "S", /* 0x1f */ + "D", /* 0x20 */ + "F", /* 0x21 */ + "G", /* 0x22 */ + "H", /* 0x23 */ + "J", /* 0x24 */ + "K", /* 0x25 */ + "L", /* 0x26 */ + ";:", /* 0x27 */ + "'\"", /* 0x28 */ + "`~", /* 0x29 */ + "LShift", /* 0x2a */ + "\\|", /* 0x2b */ + "Z", /* 0x2c */ + "X", /* 0x2d */ + "C", /* 0x2e */ + "V", /* 0x2f */ + "B", /* 0x30 */ + "N", /* 0x31 */ + "M", /* 0x32 */ + ",<", /* 0x33 */ + ".>", /* 0x34 */ + "/?", /* 0x35 */ + "RShift", /* 0x36 */ + "Keypad-*", /* 0x37 */ + "LAlt", /* 0x38 */ + "Space bar", /* 0x39 */ + "CapsLock", /* 0x3a */ + "F1", /* 0x3b */ + "F2", /* 0x3c */ + "F3", /* 0x3d */ + "F4", /* 0x3e */ + "F5", /* 0x3f */ + "F6", /* 0x40 */ + "F7", /* 0x41 */ + "F8", /* 0x42 */ + "F9", /* 0x43 */ + "F10", /* 0x44 */ + "NumLock", /* 0x45 */ + "ScrollLock", /* 0x46 */ + "Keypad-7/Home",/* 0x47 */ + "Keypad-8/Up", /* 0x48 */ + "Keypad-9/PgUp",/* 0x49 */ + "Keypad--", /* 0x4a */ + "Keypad-4/Left",/* 0x4b */ + "Keypad-5", /* 0x4c */ + "Keypad-6/Right",/* 0x4d */ + "Keypad-+", /* 0x4e */ + "Keypad-1/End", /* 0x4f */ + "Keypad-2/Down",/* 0x50 */ + "Keypad-3/PgDn",/* 0x51 */ + "Keypad-0/Ins", /* 0x52 */ + "Keypad-./Del", /* 0x53 */ + "Alt-SysRq", /* 0x54 */ + NULL, /* 0x55 */ + NULL, /* 0x56 */ + "F11", /* 0x57 */ + "F12", /* 0x58 */ + NULL, /* 0x59 */ + NULL, /* 0x5a */ + NULL, /* 0x5b */ + NULL, /* 0x5c */ + NULL, /* 0x5d */ + NULL, /* 0x5e */ + NULL, /* 0x5f */ + NULL, /* 0x60 */ + NULL, /* 0x61 */ + NULL, /* 0x62 */ + NULL, /* 0x63 */ + NULL, /* 0x64 */ + NULL, /* 0x65 */ + NULL, /* 0x66 */ + NULL, /* 0x67 */ + NULL, /* 0x68 */ + NULL, /* 0x69 */ + NULL, /* 0x6a */ + NULL, /* 0x6b */ + NULL, /* 0x6c */ + NULL, /* 0x6d */ + NULL, /* 0x6e */ + NULL, /* 0x6f */ + NULL, /* 0x70 */ + NULL, /* 0x71 */ + NULL, /* 0x72 */ + NULL, /* 0x73 */ + NULL, /* 0x74 */ + NULL, /* 0x75 */ + NULL, /* 0x76 */ + NULL, /* 0x77 */ + NULL, /* 0x78 */ + NULL, /* 0x79 */ + NULL, /* 0x7a */ + NULL, /* 0x7b */ + NULL, /* 0x7c */ + NULL, /* 0x7d */ + NULL, /* 0x7e */ + NULL, /* 0x7f */ +}; + +static char *keydescresc[] = { + NULL, /* 0xe0 0x00 */ + NULL, /* 0xe0 0x01 */ + NULL, /* 0xe0 0x02 */ + NULL, /* 0xe0 0x03 */ + NULL, /* 0xe0 0x04 */ + NULL, /* 0xe0 0x05 */ + NULL, /* 0xe0 0x06 */ + NULL, /* 0xe0 0x07 */ + NULL, /* 0xe0 0x08 */ + NULL, /* 0xe0 0x09 */ + NULL, /* 0xe0 0x0a */ + NULL, /* 0xe0 0x0b */ + NULL, /* 0xe0 0x0c */ + NULL, /* 0xe0 0x0d */ + NULL, /* 0xe0 0x0e */ + NULL, /* 0xe0 0x0f */ + NULL, /* 0xe0 0x10 */ + NULL, /* 0xe0 0x11 */ + NULL, /* 0xe0 0x12 */ + NULL, /* 0xe0 0x13 */ + NULL, /* 0xe0 0x14 */ + NULL, /* 0xe0 0x15 */ + NULL, /* 0xe0 0x16 */ + NULL, /* 0xe0 0x17 */ + NULL, /* 0xe0 0x18 */ + NULL, /* 0xe0 0x19 */ + NULL, /* 0xe0 0x1a */ + NULL, /* 0xe0 0x1b */ + "Keypad Enter", /* 0xe0 0x1c */ + "RCtrl", /* 0xe0 0x1d */ + NULL, /* 0xe0 0x1e */ + NULL, /* 0xe0 0x1f */ + NULL, /* 0xe0 0x20 */ + NULL, /* 0xe0 0x21 */ + NULL, /* 0xe0 0x22 */ + NULL, /* 0xe0 0x23 */ + NULL, /* 0xe0 0x24 */ + NULL, /* 0xe0 0x25 */ + NULL, /* 0xe0 0x26 */ + NULL, /* 0xe0 0x27 */ + NULL, /* 0xe0 0x28 */ + NULL, /* 0xe0 0x29 */ + "fake LShift", /* 0xe0 0x2a */ + NULL, /* 0xe0 0x2b */ + NULL, /* 0xe0 0x2c */ + NULL, /* 0xe0 0x2d */ + NULL, /* 0xe0 0x2e */ + NULL, /* 0xe0 0x2f */ + NULL, /* 0xe0 0x30 */ + NULL, /* 0xe0 0x31 */ + NULL, /* 0xe0 0x32 */ + NULL, /* 0xe0 0x33 */ + NULL, /* 0xe0 0x34 */ + "Keypad-/", /* 0xe0 0x35 */ + "fake RShift", /* 0xe0 0x36 */ + "Ctrl-PrtScn", /* 0xe0 0x37 */ + "RAlt", /* 0xe0 0x38 */ + NULL, /* 0xe0 0x39 */ + NULL, /* 0xe0 0x3a */ + NULL, /* 0xe0 0x3b */ + NULL, /* 0xe0 0x3c */ + NULL, /* 0xe0 0x3d */ + NULL, /* 0xe0 0x3e */ + NULL, /* 0xe0 0x3f */ + NULL, /* 0xe0 0x40 */ + NULL, /* 0xe0 0x41 */ + NULL, /* 0xe0 0x42 */ + NULL, /* 0xe0 0x43 */ + NULL, /* 0xe0 0x44 */ + NULL, /* 0xe0 0x45 */ + "Ctrl-Break", /* 0xe0 0x46 */ + "Grey Home", /* 0xe0 0x47 */ + "Grey Up", /* 0xe0 0x48 */ + "Grey PgUp", /* 0xe0 0x49 */ + NULL, /* 0xe0 0x4a */ + "Grey Left", /* 0xe0 0x4b */ + NULL, /* 0xe0 0x4c */ + "Grey Right", /* 0xe0 0x4d */ + NULL, /* 0xe0 0x4e */ + "Grey End", /* 0xe0 0x4f */ + "Grey Down", /* 0xe0 0x50 */ + "Grey PgDn", /* 0xe0 0x51 */ + "Grey Insert", /* 0xe0 0x52 */ + "Grey Delete", /* 0xe0 0x53 */ + NULL, /* 0xe0 0x54 */ + NULL, /* 0xe0 0x55 */ + NULL, /* 0xe0 0x56 */ + NULL, /* 0xe0 0x57 */ + NULL, /* 0xe0 0x58 */ + NULL, /* 0xe0 0x59 */ + NULL, /* 0xe0 0x5a */ + "LeftWindow", /* 0xe0 0x5b */ + "RightWindow", /* 0xe0 0x5c */ + "Menu", /* 0xe0 0x5d */ + "Power", /* 0xe0 0x5e */ + "Sleep", /* 0xe0 0x5f */ + NULL, /* 0xe0 0x60 */ + NULL, /* 0xe0 0x61 */ + NULL, /* 0xe0 0x62 */ + "Wake", /* 0xe0 0x63 */ + NULL, /* 0xe0 0x64 */ + NULL, /* 0xe0 0x65 */ + NULL, /* 0xe0 0x66 */ + NULL, /* 0xe0 0x67 */ + NULL, /* 0xe0 0x68 */ + NULL, /* 0xe0 0x69 */ + NULL, /* 0xe0 0x6a */ + NULL, /* 0xe0 0x6b */ + NULL, /* 0xe0 0x6c */ + NULL, /* 0xe0 0x6d */ + NULL, /* 0xe0 0x6e */ + NULL, /* 0xe0 0x6f */ + NULL, /* 0xe0 0x70 */ + NULL, /* 0xe0 0x71 */ + NULL, /* 0xe0 0x72 */ + NULL, /* 0xe0 0x73 */ + NULL, /* 0xe0 0x74 */ + NULL, /* 0xe0 0x75 */ + NULL, /* 0xe0 0x76 */ + NULL, /* 0xe0 0x77 */ + NULL, /* 0xe0 0x78 */ + NULL, /* 0xe0 0x79 */ + NULL, /* 0xe0 0x7a */ + NULL, /* 0xe0 0x7b */ + NULL, /* 0xe0 0x7c */ + NULL, /* 0xe0 0x7d */ + NULL, /* 0xe0 0x7e */ + NULL, /* 0xe0 0x7f */ +}; + +#define CHECK(r) check((r), #r, __FILE__, __LINE__) + +int check(long r, const char *expr, const char *file, int line) +{ + char buffer[256]; + if (r < 0) { + snprintf(buffer, sizeof(buffer), "%s:%d: %s: result %ld, %s", + file, line, expr, r, strerror(errno)); + exit(-1); + } + return r; +} + +#define SCODE_ESC 0xe0 +#define SCODE_BREAK 0x80 + +static int testscancode(int fd) +{ + static int escape, lctrl, rctrl; + ssize_t count; + unsigned char scode; + char *scodedescr; + + /* read a scancode and test for EOF */ + CHECK(count = read(fd, &scode, sizeof(scode))); + if (count < sizeof(scode)) { + return 0; + } + + /* print scancode */ + printf("0x%.2x ", scode); + fflush(stdout); + + /* test for escape */ + if (!escape && scode == SCODE_ESC) { + escape = 1; + return 1; + } + + /* describe scancode */ + scodedescr = (escape ? keydescresc : keydescr)[scode & ~SCODE_BREAK]; + if (scodedescr) + printf("[%s] ", scodedescr); + + if (scode & SCODE_BREAK) + printf("up\n"); + else + printf("down\n"); + + fflush(stdout); + + /* exit on ctrl-C */ + if ((scode & ~SCODE_BREAK) == 0x1d) { + if (escape) + rctrl = !(scode & SCODE_BREAK); + else + lctrl = !(scode & SCODE_BREAK); + } + if ((lctrl || rctrl) && !escape && scode == 0x2e) { + return 0; + } + + /* next key is not escaped */ + escape = 0; + + return 1; +} + +static volatile int terminate; + +static void set_terminate(int signum) +{ + terminate = signum; +} + +static int testscancodes(int fd) +{ + struct termios termios_old, termios_scan; + + /* this test only works with a TTY as stdin */ + if (!CHECK(isatty(fd))) { + printf("warning: this test can only be run from a console\n"); + return 0; + } + + /* catch fatal signals to restore the console */ + CHECK((signal(SIGHUP, set_terminate) == SIG_ERR) ? -1 : 0); + CHECK((signal(SIGINT, set_terminate) == SIG_ERR) ? -1 : 0); + CHECK((signal(SIGQUIT, set_terminate) == SIG_ERR) ? -1 : 0); + CHECK((signal(SIGABRT, set_terminate) == SIG_ERR) ? -1 : 0); + CHECK((signal(SIGPIPE, set_terminate) == SIG_ERR) ? -1 : 0); + CHECK((signal(SIGTERM, set_terminate) == SIG_ERR) ? -1 : 0); + + /* configure tty in raw input mode with scancodes and no echo */ + CHECK(tcgetattr(fd, &termios_old)); + termios_scan = termios_old; + termios_scan.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR); + termios_scan.c_iflag &= ~(INLCR | INPCK | ISTRIP); + termios_scan.c_iflag &= ~(IXOFF | IXON | PARMRK); + termios_scan.c_iflag |= SCANCODES; + termios_scan.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + termios_scan.c_lflag &= ~(ICANON | IEXTEN | ISIG | NOFLSH); + CHECK(tcsetattr(fd, TCSANOW, &termios_scan)); + + /* test: is scancode input supported? */ + CHECK(tcgetattr(fd, &termios_scan)); + if (termios_scan.c_iflag & SCANCODES) { + while (!terminate && CHECK(testscancode(fd))) ; + } else { + printf("warning: cannot enable SCANCODES " + "(are you running from a console?)\n"); + } + + /* report if closed by a signal */ + if (terminate) { + printf("received signal %d, shutting down\n", terminate); + } + + /* restore original input mode */ + CHECK(tcsetattr(fd, TCSANOW, &termios_old)); + + /* clear buffered input */ + CHECK(tcflush(fd, TCIFLUSH)); +} + +int main(void) +{ + /* perform test using stdin */ + if (testscancodes(STDIN_FILENO) < 0) + return -1; + else + return 0; +}