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);

Reply via email to