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	16 Jan 2017 16:46:03 -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,8 +214,16 @@ 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 cn_magic */
+	struct cnm_state ws_cnm_state;
 };
 
+#define MAGIC_CMD		0x2
+#define MAGIC_REG		0x1
+#define MAGIC_DEFAULT		"\x2\x20\xf4"
+
 #define MOD_SHIFT_L		(1 << 0)
 #define MOD_SHIFT_R		(1 << 1)
 #define MOD_SHIFTLOCK		(1 << 2)
@@ -456,6 +465,8 @@ wskbd_attach(device_t parent, device_t s
 
 	if (ap->console) {
 		sc->id = &wskbd_console_data;
+		cn_init_magic(&sc->ws_cnm_state);
+		cn_set_magic(MAGIC_DEFAULT);
 	} else {
 		sc->id = malloc(sizeof(struct wskbd_internal),
 				M_DEVBUF, M_WAITOK|M_ZERO);
@@ -641,6 +652,7 @@ wskbd_detach(device_t self, int flags)
 
 	if (sc->sc_isconsole) {
 		KASSERT(wskbd_console_device == sc);
+		cn_destroy_magic(&sc->ws_cnm_state);
 		wskbd_console_device = NULL;
 	}
 
@@ -1613,6 +1625,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 +1634,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);
@@ -1721,6 +1735,9 @@ wskbd_translate(struct wskbd_internal *i
 		return (0);
 	}
 	
+	if (sc != NULL && sc->sc_isconsole)
+		sc->cn_magicdev = cn_tab->cn_dev;
+
 	if (sc != NULL) {
 		if (sc->sc_hotkey != NULL)
 			ishotkey = sc->sc_hotkey(sc, sc->sc_hotkeycookie,
@@ -1742,9 +1759,24 @@ 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 (sc->ws_cnm_state.cnm_state == 0) {
+				cn_check_magic(sc->cn_magicdev, MAGIC_CMD,
+				    sc->ws_cnm_state);
+			}
+			if (kp->command & 0xff) {
+				cn_check_magic(sc->cn_magicdev, (kp->command & 0xff),
+				    sc->ws_cnm_state);
+			}
+			if ((kp->command >> 8) & 0xff) {
+				cn_check_magic(sc->cn_magicdev, ((kp->command >> 8) &
+				    0xff), sc->ws_cnm_state);
+			}
+		}
+	}
 
 	/* Now update modifiers */
 	switch (kp->group1[0]) {
@@ -1897,6 +1929,33 @@ 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 (sc->ws_cnm_state.cnm_state == 0) {
+						cn_check_magic(sc->cn_magicdev,
+						    MAGIC_REG, sc->ws_cnm_state);
+					}
+					if (res & 0xff) {
+						cn_check_magic(sc->cn_magicdev,
+						    (res & 0xff),
+						    sc->ws_cnm_state);
+					}
+					if ((res >> 8) & 0xff) {
+						cn_check_magic(sc->cn_magicdev,
+						    ((res >> 8) & 0xff),
+						    sc->ws_cnm_state);
+					}
+					if (KS_Escape & 0xff) {
+						cn_check_magic(sc->cn_magicdev,
+						    (KS_Escape & 0xff),
+						    sc->ws_cnm_state);
+					}
+					if ((KS_Escape >> 8) & 0xff) {
+						cn_check_magic(sc->cn_magicdev,
+						    ((KS_Escape >> 8) & 0xff),
+						    sc->ws_cnm_state);
+					}
+				}
+
 				return (2);
 			} else
 				res |= 0x80;
@@ -1904,6 +1963,22 @@ wskbd_translate(struct wskbd_internal *i
 	}
 
 	id->t_symbols[0] = res;
+
+	if (sc != NULL && sc->sc_isconsole) {
+		if (sc->ws_cnm_state.cnm_state == 0) {
+			cn_check_magic(sc->cn_magicdev, MAGIC_REG,
+			    sc->ws_cnm_state);
+		}
+		if (res & 0xff) {
+			cn_check_magic(sc->cn_magicdev, (res & 0xff),
+			    sc->ws_cnm_state);
+		}
+		if ((res >> 8) & 0xff) {
+			cn_check_magic(sc->cn_magicdev, ((res >> 8) & 0xff),
+			    sc->ws_cnm_state);
+		}
+	}
+
 	return (1);
 }
 
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	16 Jan 2017 16:46:03 -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,20 @@ 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
+E.g \\001+++++ five +'s to enter ddb.
+.Pp
+The default cnmagic is \\002\\040\\0364 which on most platforms is
+<Ctrl>-<Alt>-<Esc>
+the wskbd command for
+.Xr ddb 4 .
 .Sh FILES
 .Bl -item
 .It
@@ -163,9 +177,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	16 Jan 2017 16:46:03 -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-17 03:41:53.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
