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