Module Name:    src
Committed By:   jmcneill
Date:           Sat Sep 23 23:54:30 UTC 2017

Modified Files:
        src/sys/dev/fdt: files.fdt gpiokeys.c

Log Message:
For known Linux keycodes, report key press events through a wskbd device
instead of using sysmon pswitch hotkey events.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/dev/fdt/files.fdt
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/fdt/gpiokeys.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/fdt/files.fdt
diff -u src/sys/dev/fdt/files.fdt:1.20 src/sys/dev/fdt/files.fdt:1.21
--- src/sys/dev/fdt/files.fdt:1.20	Sun Aug 13 18:27:31 2017
+++ src/sys/dev/fdt/files.fdt	Sat Sep 23 23:54:30 2017
@@ -1,4 +1,4 @@
-# $NetBSD: files.fdt,v 1.20 2017/08/13 18:27:31 jmcneill Exp $
+# $NetBSD: files.fdt,v 1.21 2017/09/23 23:54:30 jmcneill Exp $
 
 include	"external/bsd/libfdt/conf/files.libfdt"
 
@@ -26,7 +26,7 @@ device	ffclock: clk
 attach	ffclock at fdt
 file	dev/fdt/fixedfactorclock.c		ffclock
 
-device	gpiokeys: sysmon_envsys, sysmon_power
+device	gpiokeys: sysmon_envsys, sysmon_power, wskbddev, linux_keymap
 attach	gpiokeys at fdt
 file	dev/fdt/gpiokeys.c			gpiokeys
 

Index: src/sys/dev/fdt/gpiokeys.c
diff -u src/sys/dev/fdt/gpiokeys.c:1.4 src/sys/dev/fdt/gpiokeys.c:1.5
--- src/sys/dev/fdt/gpiokeys.c:1.4	Thu Jul  6 14:26:00 2017
+++ src/sys/dev/fdt/gpiokeys.c	Sat Sep 23 23:54:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: gpiokeys.c,v 1.4 2017/07/06 14:26:00 jmcneill Exp $ */
+/* $NetBSD: gpiokeys.c,v 1.5 2017/09/23 23:54:30 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gpiokeys.c,v 1.4 2017/07/06 14:26:00 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gpiokeys.c,v 1.5 2017/09/23 23:54:30 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -40,6 +40,12 @@ __KERNEL_RCSID(0, "$NetBSD: gpiokeys.c,v
 #include <dev/sysmon/sysmonvar.h>
 #include <dev/sysmon/sysmon_taskq.h>
 
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+#include <dev/wscons/linux_keymap.h>
+
 #include <dev/fdt/fdtvar.h>
 
 #define GPIOKEYS_POLL_INTERVAL	mstohz(200)
@@ -53,15 +59,23 @@ static void	gpiokeys_attach(device_t, de
 static void	gpiokeys_tick(void *);
 static void	gpiokeys_task(void *);
 
+extern const struct wscons_keydesc ukbd_keydesctab[];
+static const struct wskbd_mapdata gpiokeys_keymapdata = {
+	ukbd_keydesctab,
+	KB_US,
+};
+
 struct gpiokeys_softc;
 
 struct gpiokeys_key {
+	struct gpiokeys_softc	*key_sc;
 	int			key_phandle;
 	char	 		*key_label;
 	struct fdtbus_gpio_pin	*key_pin;
 	u_int			key_debounce;
 	u_int			key_code;
 	struct sysmon_pswitch	key_pswitch;
+	uint8_t			key_usbcode;
 	u_int			key_state;
 
 	struct gpiokeys_key	*key_next;
@@ -77,12 +91,48 @@ struct gpiokeys_softc {
 
 	struct gpiokeys_key *sc_keys;
 	callout_t	sc_tick;
+
+	device_t	sc_wskbddev;
+	int		sc_enabled;
 };
 
 CFATTACH_DECL_NEW(gpiokeys, sizeof(struct gpiokeys_softc),
     gpiokeys_match, gpiokeys_attach, NULL, NULL);
 
 static int
+gpiokeys_enable(void *v, int on)
+{
+	struct gpiokeys_softc * const sc = v;
+
+	sc->sc_enabled = on;
+
+	return 0;
+}
+
+static void
+gpiokeys_set_leds(void *v, int leds)
+{
+}
+
+static int
+gpiokeys_ioctl(void *v, u_long cmd, void *data, int flag, lwp_t *l)
+{
+	switch (cmd) {
+	case WSKBDIO_GTYPE:
+		*(int *)data = WSKBD_TYPE_USB;
+		return 0;
+	}
+
+	return EPASSTHROUGH;
+}
+
+static const struct wskbd_accessops gpiokeys_accessops = {
+	.enable = gpiokeys_enable,
+	.set_leds = gpiokeys_set_leds,
+	.ioctl = gpiokeys_ioctl
+};
+
+static int
 gpiokeys_match(device_t parent, cfdata_t cf, void *aux)
 {
 	const char * const compatible[] = { "gpio-keys", NULL };
@@ -98,8 +148,9 @@ gpiokeys_attach(device_t parent, device_
 	const struct fdt_attach_args *faa = aux;
 	const int phandle = faa->faa_phandle;
 	struct gpiokeys_key *key;
-	int child, len;
 	u_int debounce, code;
+	int use_wskbddev = 0;
+	int child, len;
 
 	sc->sc_dev = self;
 	sc->sc_phandle = phandle;
@@ -117,6 +168,7 @@ gpiokeys_attach(device_t parent, device_
 			continue;
 		}
 		key = kmem_zalloc(sizeof(*key), KM_SLEEP);
+		key->key_sc = sc;
 		key->key_phandle = child;
 		key->key_code = code;
 		key->key_label = kmem_zalloc(len, KM_SLEEP);
@@ -131,20 +183,28 @@ gpiokeys_attach(device_t parent, device_
 		if (key->key_pin)
 			key->key_state = fdtbus_gpio_read(key->key_pin);
 
-		key->key_pswitch.smpsw_name = key->key_label;
 		switch (code) {
 		case KEY_POWER:
+			key->key_pswitch.smpsw_name = key->key_label;
 			key->key_pswitch.smpsw_type = PSWITCH_TYPE_POWER;
 			break;
 		case KEY_SLEEP:
+			key->key_pswitch.smpsw_name = key->key_label;
 			key->key_pswitch.smpsw_type = PSWITCH_TYPE_SLEEP;
 			break;
 		default:
-			key->key_pswitch.smpsw_type = PSWITCH_TYPE_HOTKEY;
+			key->key_usbcode = linux_key_to_usb(code);
+			if (key->key_usbcode != 0) {
+				use_wskbddev++;
+			} else {
+				key->key_pswitch.smpsw_name = key->key_label;
+				key->key_pswitch.smpsw_type = PSWITCH_TYPE_HOTKEY;
+			}
 			break;
 		}
 
-		if (sysmon_pswitch_register(&key->key_pswitch) != 0) {
+		if (key->key_pswitch.smpsw_name != NULL &&
+		    sysmon_pswitch_register(&key->key_pswitch) != 0) {
 			aprint_error(" %s:ERROR", key->key_label);
 			kmem_free(key->key_label, len);
 			kmem_free(key, sizeof(*key));
@@ -168,6 +228,17 @@ gpiokeys_attach(device_t parent, device_
 
 	aprint_normal("\n");
 
+	if (use_wskbddev > 0) {
+		struct wskbddev_attach_args a;
+		memset(&a, 0, sizeof(a));
+		a.console = false;
+		a.keymap = &gpiokeys_keymapdata;
+		a.accessops = &gpiokeys_accessops;
+		a.accesscookie = sc;
+		sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a,
+		    wskbddevprint);
+	}
+
 	callout_init(&sc->sc_tick, CALLOUT_MPSAFE);
 	callout_setfunc(&sc->sc_tick, gpiokeys_tick, sc);
 
@@ -197,7 +268,14 @@ static void
 gpiokeys_task(void *priv)
 {
 	struct gpiokeys_key *key = priv;
+	struct gpiokeys_softc *sc = key->key_sc;
 
-	sysmon_pswitch_event(&key->key_pswitch,
-	    key->key_state ? PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
+	if (key->key_pswitch.smpsw_name) {
+		sysmon_pswitch_event(&key->key_pswitch,
+		    key->key_state ? PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
+	} else if (sc->sc_enabled && sc->sc_wskbddev != NULL && key->key_usbcode != 0) {
+		wskbd_input(sc->sc_wskbddev,
+		    key->key_state ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP,
+		    key->key_usbcode);
+	}
 }

Reply via email to