Index: src/sys/dev/wscons/wskbd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wskbd.c,v
retrieving revision 1.138
diff -u -p -r1.138 wskbd.c
--- src/sys/dev/wscons/wskbd.c  10 Dec 2016 22:36:28 -0000      1.138
+++ src/sys/dev/wscons/wskbd.c  14 Jan 2017 21:47:55 -0000
@@ -135,6 +135,7 @@ __KERNEL_RCSID(0, "$NetBSD: wskbd.c,v 1.
#include <sys/vnode.h>
#include <sys/kauth.h>

+#include <dev/cons.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsksymdef.h>
@@ -213,6 +214,10 @@ struct wskbd_softc {
       /* optional table to translate scancodes in event mode */
       int             sc_evtrans_len;
       keysym_t        *sc_evtrans;
+
+       /* cn_magic support */
+       dev_t           cn_magicdev;    /* device for cnmagic */
+       struct cnm_state ws_cnm_state;
};

#define MOD_SHIFT_L            (1 << 0)
@@ -285,6 +290,7 @@ static int wskbd_mux_close(struct wsevsr

static int wskbd_do_open(struct wskbd_softc *, struct wseventvar *);
static int wskbd_do_ioctl(device_t, u_long, void *, int, struct lwp *);
+static void ws_check_magic(int, int, struct cnm_state *);

CFATTACH_DECL_NEW(wskbd, sizeof (struct wskbd_softc),
    wskbd_match, wskbd_attach, wskbd_detach, wskbd_activate);
@@ -456,6 +462,9 @@ wskbd_attach(device_t parent, device_t s

       if (ap->console) {
               sc->id = &wskbd_console_data;
+               sc->cn_magicdev = cn_tab->cn_dev;
+               cn_init_magic(&sc->ws_cnm_state);
+               cn_set_magic("\x2\x20\xf4"); /* default magic */
       } else {
               sc->id = malloc(sizeof(struct wskbd_internal),
                               M_DEVBUF, M_WAITOK|M_ZERO);
@@ -1613,6 +1622,7 @@ internal_command(struct wskbd_softc *sc,

#if defined(DDB) || defined(KGDB)
       if (ksym == KS_Cmd_Debugger) {
+#if 0
               if (sc->sc_isconsole) {
#ifdef DDB
                       console_debugger();
@@ -1621,6 +1631,7 @@ internal_command(struct wskbd_softc *sc,
                       kgdb_connect(1);
#endif
               }
+#endif
               /* discard this key (ddb discarded command modifiers) */
               *type = WSCONS_EVENT_KEY_UP;
               return (1);
@@ -1742,9 +1753,19 @@ wskbd_translate(struct wskbd_internal *i
       }

       /* if this key has a command, process it first */
-       if (sc != NULL && kp->command != KS_voidSymbol)
+       if (sc != NULL && kp->command != KS_voidSymbol) {
               iscommand = internal_command(sc, &type, kp->command,
                                            kp->group1[0]);
+               if (sc->sc_isconsole && iscommand) {
+                       if (kp->command & 0xff) {
+                               ws_check_magic(2, (kp->command & 0xff),
+                                   &sc->ws_cnm_state);
+                       }
+                       if ((kp->command >> 8) & 0xff)
+                               ws_check_magic(2, ((kp->command >> 8) & 0xff),
+                                    &sc->ws_cnm_state);
+               }
+       }

       /* Now update modifiers */
       switch (kp->group1[0]) {
@@ -1897,6 +1918,26 @@ wskbd_translate(struct wskbd_internal *i
                       if (id->t_flags & WSKFL_METAESC) {
                               id->t_symbols[0] = KS_Escape;
                               id->t_symbols[1] = res;
+                               if (sc != NULL && sc->sc_isconsole) {
+                                       if (res & 0xff) {
+                                               ws_check_magic(1, (res & 0xff),
+                                                   &sc->ws_cnm_state);
+                                       }
+                                       if ((res >> 8) & 0xff) {
+                                               ws_check_magic(1, ((res >> 8) &
+                                                   0xff), &sc->ws_cnm_state);
+                                       }
+                                       if (KS_Escape & 0xff) {
+                                               ws_check_magic(1, (KS_Escape &
+                                                   0xff), &sc->ws_cnm_state);
+                                       }
+                                       if ((KS_Escape >> 8) & 0xff) {
+                                               ws_check_magic(1, ((KS_Escape
+                                                   >> 8) & 0xff),
+                                                   &sc->ws_cnm_state);
+                                       }
+                               }
+
                               return (2);
                       } else
                               res |= 0x80;
@@ -1904,6 +1945,16 @@ wskbd_translate(struct wskbd_internal *i
       }

       id->t_symbols[0] = res;
+
+       if (sc != NULL && sc->sc_isconsole) {
+               if (res & 0xff)
+                       ws_check_magic(1, (res & 0xff), &sc->ws_cnm_state);
+               if ((res >> 8) & 0xff) {
+                       ws_check_magic(1, ((res >> 8) & 0xff),
+                           &sc->ws_cnm_state);
+               }
+       }
+
       return (1);
}

@@ -1916,3 +1967,24 @@ wskbd_set_evtrans(device_t dev, keysym_t
       sc->sc_evtrans = tab;
}

+static void
+ws_check_magic(int mode, int command, struct cnm_state *state)
+{
+       int _v = state->cnm_magic[state->cnm_state];
+       int _u = state->cnm_magic[0];
+       if (mode == CNS_MAGIC_VAL(_u)) {
+               if (state->cnm_state == 0) {
+                       state->cnm_state = CNS_MAGIC_NEXT(_v);
+                       _v = state->cnm_magic[state->cnm_state];
+               }
+               if (command == CNS_MAGIC_VAL(_v)) {
+                       state->cnm_state = CNS_MAGIC_NEXT(_v);
+                       if (state->cnm_state == CNS_TERM) {
+                               cn_trap();
+                               state->cnm_state = 0;
+                       }
+               } else
+                       state->cnm_state = 0;
+       }
+}
+
Index: src/share/man/man4/wskbd.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/wskbd.4,v
retrieving revision 1.16
diff -u -p -r1.16 wskbd.4
--- src/share/man/man4/wskbd.4  27 May 2012 12:05:40 -0000      1.16
+++ src/share/man/man4/wskbd.4  14 Jan 2017 21:47:55 -0000
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 27, 2012
+.Dd January 9, 2016
.Dt WSKBD 4
.Os
.Sh NAME
@@ -152,6 +152,16 @@ if (ioctl(fd, WSKBDIO_SETVERSION, &ver)
    err(EXIT_FAILURE, "cannot set version");
.Ed
.El
+.Sh CAVEATS
+The
+.Xr cnmagic 9
+sysctl variable must be prefixed by \\001 for normal characters and/or control
+codes.
+Alternatively it can be prefixed by \\002 for wskbd commands.
+You cannot mix both types in cnmagic.
+.Pp
+The default cnmagic is \\002\\040\\0364 which is the wskbd command for
+.Xr ddb 4 .
.Sh FILES
.Bl -item
.It
@@ -163,9 +173,15 @@ if (ioctl(fd, WSKBDIO_SETVERSION, &ver)
.El
.Sh SEE ALSO
.Xr btkbd 4 ,
+.Xr ddb 4 ,
.Xr pckbd 4 ,
.Xr ukbd 4 ,
.Xr wscons 4 ,
.Xr wsmux 4 ,
+.Xr sysctl 8 ,
.Xr wsconsctl 8 ,
+.Xr cnmagic 9 ,
.Xr wskbd 9
+.Sh HISTORY
+Support for cnmagic first appeared in
+.Nx 8.0 .
Index: src/sys/rump/dev/lib/libwscons/Makefile
===================================================================
RCS file: /cvsroot/src/sys/rump/dev/lib/libwscons/Makefile,v
retrieving revision 1.7
diff -u -p -r1.7 Makefile
--- src/sys/rump/dev/lib/libwscons/Makefile     26 Jan 2016 23:12:17 -0000      1.7
+++ src/sys/rump/dev/lib/libwscons/Makefile     14 Jan 2017 21:47:55 -0000
@@ -1,6 +1,8 @@
#      $NetBSD: Makefile,v 1.7 2016/01/26 23:12:17 pooka Exp $
#

+.PATH: ${.CURDIR}/../../../../dev
+.PATH: ${.CURDIR}/../../../../kern
.PATH: ${.CURDIR}/../../../../dev/wscons

LIB=   rumpdev_wscons
@@ -10,7 +12,7 @@ IOCONF=       WSCONS.ioconf

SRCS=   wsevent.c wskbd.c wskbdutil.c wsmouse.c

-SRCS+= wscons_component.c
+SRCS+= wscons_component.c cons.c cnmagic.c

.include <bsd.lib.mk>
.include <bsd.klinks.mk>
--- /dev/null   2017-01-15 08:49:56.000000000 +1100
+++ src/sys/rump/dev/lib/libwscons/nullcons.h   2017-01-14 09:43:05.000000000 +1100
@@ -0,0 +1,3 @@
+/* $NetBSD$ */
+
+#define        NNULLCONS       0