]> Zhao Yanbai Git Server - minix.git/commitdiff
Add scancode reading capability to TTY
authorErik van der Kouwe <erik@minix3.org>
Thu, 15 Apr 2010 06:55:32 +0000 (06:55 +0000)
committerErik van der Kouwe <erik@minix3.org>
Thu, 15 Apr 2010 06:55:32 +0000 (06:55 +0000)
test/scancodes/Makefile [new file with mode: 0644]
test/scancodes/test-scancodes.c [new file with mode: 0644]

diff --git a/test/scancodes/Makefile b/test/scancodes/Makefile
new file mode 100644 (file)
index 0000000..4d0f0d5
--- /dev/null
@@ -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 (file)
index 0000000..e03cd05
--- /dev/null
@@ -0,0 +1,408 @@
+#define _MINIX
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+/* 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;
+}