Tobias Stoeckmann suggested off-list to keep explicit state of wether rawmode is enabled or not, so that the signal handler doesn't perform useless (and wrong, strictly speaking) work. He also suggested to integrate keycode.c into wsconsctl.c (if i understood correctly ;), but i was unsure about that.
And the usage string for -r erroneously and unfortunately contained '-f [xy]', which this diff also fixes. I'll watch out and see if i find my heart drops somewhere. Thanks again. --steffen Index: Makefile =================================================================== RCS file: /Users/steffen/arena/code.openbsd/src/sbin/wsconsctl/Makefile,v retrieving revision 1.34 diff -a -p -u -r1.34 Makefile --- Makefile 30 Jan 2010 20:48:50 -0000 1.34 +++ Makefile 30 Jan 2012 15:17:46 -0000 @@ -12,7 +12,7 @@ ${MACHINE} == "zaurus" PROG= wsconsctl -SRCS= display.c keyboard.c keysym.c map_parse.y map_scan.l \ +SRCS= display.c keyboard.c keycode.c keysym.c map_parse.y map_scan.l \ mouse.c util.c wsconsctl.c CPPFLAGS+= -I${.CURDIR} -I. Index: keycode.c =================================================================== RCS file: keycode.c diff -N keycode.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ keycode.c 31 Jan 2012 13:46:22 -0000 @@ -0,0 +1,139 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2012 Steffen Daode Nurpmeso. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsksymdef.h> +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <termios.h> +#include <unistd.h> +#include "wsconsctl.h" + +static int is_rawmode; +static struct termios tios_orig, tios_raw; + +static void onsig(int sig); +static void raw_on(void), raw_off(void); + +static void +onsig(int sig) +{ + if (is_rawmode) + raw_off(); + exit(sig != SIGALRM); +} + +static void +raw_on(void) +{ + int arg = WSKBD_RAW; + + if (tcsetattr(STDIN_FILENO, TCSANOW, &tios_raw) < 0) + err(1, "Can't set terminal attributes"); + if (ioctl(STDIN_FILENO, WSKBDIO_SETMODE, &arg) < 0) { + arg = errno; + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tios_orig); + errno = arg; + err(1, ((arg == ENOTTY) + ? "This mode won't work on pseudo terminals" + : "Can't put keyboard in raw mode (the " + "WSDISPLAY_COMPAT_RAWKBD kernel option is required)")); + } + + is_rawmode = 1; + return; +} + +static void +raw_off(void) +{ + int arg = WSKBD_TRANSLATED; + + (void)ioctl(STDIN_FILENO, WSKBDIO_SETMODE, &arg); + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tios_orig); + + is_rawmode = 0; + return; +} + +void +keycode_mode(void) +{ + ssize_t i, skip; + struct sigaction sa; + struct itimerval it; + unsigned char *cursor, buffer[64]; + + if (tcgetattr(STDIN_FILENO, &tios_orig) < 0) + err(1, "Can't query terminal attributes"); + tios_raw = tios_orig; + (void)cfmakeraw(&tios_raw); + + sa.sa_handler = &onsig; + sa.sa_flags = 0; + (void)sigfillset(&sa.sa_mask); + for (i = 0; i < NSIG; ++i) + if (sigaction((int)i + 1, &sa, NULL) < 0 && i == SIGALRM) + err(1, "Can't install SIGALRM signal handler"); + + printf("You may now use the keyboard.\n" + "After five seconds of inactivity the program terminates\n"); + for (i = skip = 0;;) { + it.it_value.tv_sec = 5; + it.it_value.tv_usec = 0; + it.it_interval.tv_sec = it.it_interval.tv_usec = 0; + if (setitimer(ITIMER_REAL, &it, NULL) < 0) + err(3, "Can't install wakeup timer"); + + raw_on(); + i = read(STDIN_FILENO, buffer + skip, sizeof(buffer) - skip); + raw_off(); + + it.it_value.tv_sec = it.it_value.tv_usec = 0; + (void)setitimer(ITIMER_REAL, &it, NULL); + + if (i <= 0) + exit(1); + i += skip; + + for (cursor = buffer; --i >= 0;) { + unsigned int k = *cursor++; + if ((k & 0xF0) == 0xE0 || (k & 0xF8) == 0xF0) { + if (--i < 0) { + buffer[0] = (unsigned char)k; + skip = 1; + break; + } + k <<= 8; + k |= *cursor++; + k &= ((k & 0xF000) == 0xE000) ? 0x0FFF : 0x00FF; + } + printf("keycode %3u %-7s\n", + (k & ~0x0080), (k & 0x0080) ? "release" : "press"); + skip = 0; + } + } + /* NOTREACHED */ + return; +} Index: wsconsctl.8 =================================================================== RCS file: /Users/steffen/arena/code.openbsd/src/sbin/wsconsctl/wsconsctl.8,v retrieving revision 1.23 diff -a -p -u -r1.23 wsconsctl.8 --- wsconsctl.8 4 Aug 2008 07:32:51 -0000 1.23 +++ wsconsctl.8 30 Jan 2012 15:18:12 -0000 @@ -49,6 +49,8 @@ .Op Fl n .Op Fl f Ar file .Ar name Ns += Ns Ar value ... +.Nm wsconsctl +.Fl r .Sh DESCRIPTION The .Nm @@ -81,6 +83,12 @@ symbol. See the .Sx EXAMPLES section for more details. +.It Fl r +Enters a raw interactive mode in which keypresses are displayed +as their keycodes. +This mode always operates on standard input +and does not work on pseudo terminals. +After five seconds of inactivity the program terminates. .El .Pp The Index: wsconsctl.c =================================================================== RCS file: /Users/steffen/arena/code.openbsd/src/sbin/wsconsctl/wsconsctl.c,v retrieving revision 1.26 diff -a -p -u -r1.26 wsconsctl.c --- wsconsctl.c 20 Aug 2010 00:20:55 -0000 1.26 +++ wsconsctl.c 31 Jan 2012 13:47:03 -0000 @@ -72,15 +72,17 @@ usage() "usage: %s [-an]\n" " %s [-n] [-f file] name ...\n" " %s [-n] [-f file] name=value ...\n" - " %s [-n] [-f file] name+=value ...\n", - __progname, __progname, __progname, __progname); + " %s [-n] [-f file] name+=value ...\n" + " %s -r\n", + __progname, __progname, __progname, __progname, __progname); exit(1); } int main(int argc, char *argv[]) { - int i, ch, error = 0, aflag = 0, do_merge, putval, devidx, devfd; + int i, ch, error = 0, aflag = 0, rflag = 0, + do_merge, putval, devidx, devfd; struct vartypesw *sw = NULL; char *getsep = "=", *setsep = " -> ", *p; char *wdev = NULL; @@ -88,7 +90,7 @@ main(int argc, char *argv[]) struct field *f; char devname[20]; - while ((ch = getopt(argc, argv, "af:nw")) != -1) { + while ((ch = getopt(argc, argv, "af:nrw")) != -1) { switch(ch) { case 'a': aflag = 1; @@ -99,6 +101,9 @@ main(int argc, char *argv[]) case 'n': getsep = setsep = NULL; break; + case 'r': + rflag = 1; + break; case 'w': /* compat */ break; @@ -110,12 +115,17 @@ main(int argc, char *argv[]) argc -= optind; argv += optind; - if (argc > 0 && aflag != 0) - errx(1, "excess arguments after -a"); - if (argc == 0) - aflag = 1; + if (argc > 0 && (aflag != 0 || rflag != 0)) + errx(1, "excess arguments after -%c", (aflag ? 'a' : 'r')); + if (rflag == 0) { + if (argc == 0) + aflag = 1; + } else if (aflag != 0 || wdev != NULL || getsep == NULL) + errx(1, "-r is mutual exclusive with other options"); - if (aflag != 0) { + if (rflag != 0) + keycode_mode(); + else if (aflag != 0) { for (sw = typesw; sw->name; sw++) { for (devidx = 0;; devidx++) { device = (*sw->nextdev)(devidx); Index: wsconsctl.h =================================================================== RCS file: /Users/steffen/arena/code.openbsd/src/sbin/wsconsctl/wsconsctl.h,v retrieving revision 1.13 diff -a -p -u -r1.13 wsconsctl.h --- wsconsctl.h 20 Aug 2010 00:20:55 -0000 1.13 +++ wsconsctl.h 30 Jan 2012 15:18:12 -0000 @@ -76,6 +76,7 @@ keysym_t ksym_upcase(keysym_t); void keyboard_get_values(int); int keyboard_put_values(int); char * keyboard_next_device(int); +void keycode_mode(void); void mouse_get_values(int); int mouse_put_values(int); char * mouse_next_device(int);