diff options
-rw-r--r-- | sys/arch/alpha/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/amd64/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/arm64/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/armv7/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/hppa/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/i386/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/landisk/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/loongson/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/macppc/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/octeon/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/powerpc64/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/arch/sparc64/conf/GENERIC | 4 | ||||
-rw-r--r-- | sys/dev/usb/files.usb | 7 | ||||
-rw-r--r-- | sys/dev/usb/ucc.c | 489 |
14 files changed, 531 insertions, 13 deletions
diff --git a/sys/arch/alpha/conf/GENERIC b/sys/arch/alpha/conf/GENERIC index 8af652ce301..b917872b1f4 100644 --- a/sys/arch/alpha/conf/GENERIC +++ b/sys/arch/alpha/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.268 2021/02/04 16:25:38 anton Exp $ +# $OpenBSD: GENERIC,v 1.269 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -107,6 +107,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index c0c16f7c986..89316c69694 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.498 2021/04/28 11:32:59 bluhm Exp $ +# $OpenBSD: GENERIC,v 1.499 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -286,6 +286,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC index ff54bee0a9a..5ee5cfb482f 100644 --- a/sys/arch/arm64/conf/GENERIC +++ b/sys/arch/arm64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.203 2021/06/29 12:43:33 patrick Exp $ +# $OpenBSD: GENERIC,v 1.204 2021/08/20 05:23:18 anton Exp $ # # GENERIC machine description file # @@ -392,6 +392,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/armv7/conf/GENERIC b/sys/arch/armv7/conf/GENERIC index 1af5eb8dd85..d8cf637e1c6 100644 --- a/sys/arch/armv7/conf/GENERIC +++ b/sys/arch/armv7/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.138 2021/05/28 15:52:11 visa Exp $ +# $OpenBSD: GENERIC,v 1.139 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -327,6 +327,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/hppa/conf/GENERIC b/sys/arch/hppa/conf/GENERIC index 1a27dbb18c0..f533dd3eb2e 100644 --- a/sys/arch/hppa/conf/GENERIC +++ b/sys/arch/hppa/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.182 2021/02/04 16:25:39 anton Exp $ +# $OpenBSD: GENERIC,v 1.183 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -111,6 +111,8 @@ ukbd* at uhidev? # USB keyboard wskbd* at ukbd? mux 1 uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index b49353a92d0..d82693d7f36 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.856 2021/04/28 11:32:59 bluhm Exp $ +# $OpenBSD: GENERIC,v 1.857 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -284,6 +284,8 @@ uticom* at uhub? # TI serial ucom* at uticom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/landisk/conf/GENERIC b/sys/arch/landisk/conf/GENERIC index a2091413514..01a5ef1d209 100644 --- a/sys/arch/landisk/conf/GENERIC +++ b/sys/arch/landisk/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.57 2021/02/04 16:25:39 anton Exp $ +# $OpenBSD: GENERIC,v 1.58 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -137,6 +137,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/loongson/conf/GENERIC b/sys/arch/loongson/conf/GENERIC index d213bd976f9..6204519a5a4 100644 --- a/sys/arch/loongson/conf/GENERIC +++ b/sys/arch/loongson/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.64 2021/02/04 16:25:39 anton Exp $ +# $OpenBSD: GENERIC,v 1.65 2021/08/20 05:23:18 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -164,6 +164,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/macppc/conf/GENERIC b/sys/arch/macppc/conf/GENERIC index 34014204a23..7c364fe9454 100644 --- a/sys/arch/macppc/conf/GENERIC +++ b/sys/arch/macppc/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.273 2021/02/04 16:25:39 anton Exp $g +# $OpenBSD: GENERIC,v 1.274 2021/08/20 05:23:18 anton Exp $g # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -260,6 +260,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/octeon/conf/GENERIC b/sys/arch/octeon/conf/GENERIC index ec5424938cb..e66788dcdc7 100644 --- a/sys/arch/octeon/conf/GENERIC +++ b/sys/arch/octeon/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.58 2021/02/04 16:25:39 anton Exp $ +# $OpenBSD: GENERIC,v 1.59 2021/08/20 05:23:19 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -156,6 +156,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/powerpc64/conf/GENERIC b/sys/arch/powerpc64/conf/GENERIC index 5a41fb2ae72..614425506e0 100644 --- a/sys/arch/powerpc64/conf/GENERIC +++ b/sys/arch/powerpc64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.26 2021/04/28 11:32:59 bluhm Exp $ +# $OpenBSD: GENERIC,v 1.27 2021/08/20 05:23:19 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -127,6 +127,8 @@ uslhcom* at uhidev? # Silicon Labs CP2110 USB HID UART ucom* at uslhcom? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/arch/sparc64/conf/GENERIC b/sys/arch/sparc64/conf/GENERIC index 71e92dc9016..d3ec9a066ed 100644 --- a/sys/arch/sparc64/conf/GENERIC +++ b/sys/arch/sparc64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.318 2021/07/10 07:04:59 mpi Exp $ +# $OpenBSD: GENERIC,v 1.319 2021/08/20 05:23:19 anton Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -224,6 +224,8 @@ umsm* at uhub? # Qualcomm MSM EVDO ucom* at umsm? uhid* at uhidev? # USB generic HID support fido* at uhidev? # FIDO/U2F security key support +ucc* at uhidev? # Consumer Control keyboards +wskbd* at ucc? mux 1 ujoy* at uhidev? # USB joystick/gamecontroller support uhidpp* at uhidev? # Logitech HID++ Devices upd* at uhidev? # USB Power Devices sensors diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 4d79c5ea21a..02bf653d206 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.145 2021/02/04 16:25:39 anton Exp $ +# $OpenBSD: files.usb,v 1.146 2021/08/20 05:23:19 anton Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -488,3 +488,8 @@ file dev/usb/umstc.c umstc device uhidpp: hid attach uhidpp at uhidbus file dev/usb/uhidpp.c uhidpp + +# Consumer Control Keyboards +device ucc: hid, wskbddev +attach ucc at uhidbus +file dev/usb/ucc.c ucc diff --git a/sys/dev/usb/ucc.c b/sys/dev/usb/ucc.c new file mode 100644 index 00000000000..9b747bf9238 --- /dev/null +++ b/sys/dev/usb/ucc.c @@ -0,0 +1,489 @@ +/* $OpenBSD: ucc.c,v 1.1 2021/08/20 05:23:19 anton Exp $ */ + +/* + * Copyright (c) 2021 Anton Lindqvist <anton@openbsd.org> + * + * 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 <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbhid.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/uhidev.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wskbdvar.h> +#include <dev/wscons/wsksymdef.h> +#include <dev/wscons/wsksymvar.h> + +/* #define UCC_DEBUG */ +#ifdef UCC_DEBUG +#define DPRINTF(x...) do { if (ucc_debug) printf(x); } while (0) +void ucc_dump(const char *, u_char *, u_int); +int ucc_debug = 1; +#else +#define DPRINTF(x...) +#define ucc_dump(prefix, data, len) +#endif + +struct ucc_softc { + struct uhidev sc_hdev; + struct device *sc_wskbddev; + + /* Key mappings used in translating mode. */ + keysym_t *sc_map; + u_int sc_maplen; + u_int sc_mapsiz; + u_int sc_nkeys; + + /* Key mappings used in raw mode. */ + struct ucc_keyraw *sc_raw; + u_int sc_rawlen; + u_int sc_rawsiz; + + int sc_mode; + + /* Last pressed key. */ + union { + int sc_last_translate; + u_char sc_last_raw; + }; + + struct wscons_keydesc sc_keydesc[2]; + struct wskbd_mapdata sc_keymap; +}; + +struct ucc_keysym { + const char *us_name; + int32_t us_usage; + keysym_t us_key; + u_char us_raw; +}; + +struct ucc_keyraw { + u_int ur_bit; + u_char ur_raw; +}; + +int ucc_match(struct device *, void *, void *); +void ucc_attach(struct device *, struct device *, void *); +int ucc_detach(struct device *, int); +void ucc_intr(struct uhidev *, void *, u_int); + +void ucc_attach_wskbd(struct ucc_softc *); +int ucc_enable(void *, int); +void ucc_set_leds(void *, int); +int ucc_ioctl(void *, u_long, caddr_t, int, struct proc *); + +int ucc_parse_hid(struct ucc_softc *, void *, int); +int ucc_bit_to_raw(struct ucc_softc *, u_int, u_char *); +int ucc_usage_to_sym(int32_t, const struct ucc_keysym **); +void ucc_raw_to_scancode(u_char *, int *, u_char, int); +void ucc_input(struct ucc_softc *, u_int, int); +void ucc_rawinput(struct ucc_softc *, u_char, int); +int ucc_setbits(u_char *, int, u_int *); + +struct cfdriver ucc_cd = { + NULL, "ucc", DV_DULL +}; + +const struct cfattach ucc_ca = { + sizeof(struct ucc_softc), + ucc_match, + ucc_attach, + ucc_detach, +}; + +/* + * Mapping of HID consumer control usages to key symbols. + * The raw scan codes are taken from X11, see the media_common symbols in + * dist/xkeyboard-config/symbols/inet. + * Then use dist/xkeyboard-config/keycodes/xfree86 to resolve keys to the + * corresponding raw scan code. + */ +static const struct ucc_keysym ucc_keysyms[] = { +#ifdef UCC_DEBUG +#define U(x) #x, x +#else +#define U(x) NULL, x +#endif + { U(HUC_MUTE), KS_AudioMute, 0 }, + { U(HUC_VOL_INC), KS_AudioRaise, 0 }, + { U(HUC_VOL_DEC), KS_AudioLower, 0 }, + { U(HUC_TRACK_NEXT), 0, 153 /* I19 = XF86AudioNext */ }, + { U(HUC_TRACK_PREV), 0, 144 /* I10 = XF86AudioPrev */ }, + { U(HUC_STOP), 0, 164 /* I24 = XF86AudioStop */ }, + { U(HUC_PLAY_PAUSE), 0, 162 /* I22 = XF86AudioPlay, XF86AudioPause */ }, +#undef U +}; + +int +ucc_match(struct device *parent, void *match, void *aux) +{ + struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; + void *desc; + int size; + + uhidev_get_report_desc(uha->parent, &desc, &size); + if (!hid_is_collection(desc, size, uha->reportid, + HID_USAGE2(HUP_CONSUMER, HUC_CONTROL))) + return UMATCH_NONE; + + return UMATCH_IFACECLASS; +} + +void +ucc_attach(struct device *parent, struct device *self, void *aux) +{ + struct ucc_softc *sc = (struct ucc_softc *)self; + struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; + void *desc; + int error, repid, size; + + sc->sc_mode = WSKBD_TRANSLATED; + sc->sc_last_translate = -1; + + sc->sc_hdev.sc_intr = ucc_intr; + sc->sc_hdev.sc_parent = uha->parent; + sc->sc_hdev.sc_udev = uha->uaa->device; + sc->sc_hdev.sc_report_id = uha->reportid; + + uhidev_get_report_desc(uha->parent, &desc, &size); + repid = uha->reportid; + sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); + sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); + sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); + + error = ucc_parse_hid(sc, desc, size); + if (error) { + printf(" hid error %d\n", error); + return; + } + + printf(" %d key%s, %d mapping%s\n", + sc->sc_nkeys, sc->sc_nkeys == 1 ? "" : "s", + sc->sc_rawlen, sc->sc_rawlen == 1 ? "" : "s"); + + /* Cannot load an empty map. */ + if (sc->sc_maplen > 0) + ucc_attach_wskbd(sc); +} + +int +ucc_detach(struct device *self, int flags) +{ + struct ucc_softc *sc = (struct ucc_softc *)self; + int error = 0; + + if (sc->sc_wskbddev != NULL) + error = config_detach(sc->sc_wskbddev, flags); + uhidev_close(&sc->sc_hdev); + free(sc->sc_map, M_USBDEV, sc->sc_mapsiz); + free(sc->sc_raw, M_USBDEV, sc->sc_rawsiz); + return error; +} + +void +ucc_intr(struct uhidev *addr, void *data, u_int len) +{ + struct ucc_softc *sc = (struct ucc_softc *)addr; + int raw = sc->sc_mode == WSKBD_RAW; + u_int bit = 0; + + ucc_dump(__func__, data, len); + + if (ucc_setbits(data, len, &bit)) { + /* All zeroes, assume key up event. */ + if (raw) { + if (sc->sc_last_raw != 0) { + ucc_rawinput(sc, sc->sc_last_raw, 1); + sc->sc_last_raw = 0; + } + } else { + if (sc->sc_last_translate != -1) { + ucc_input(sc, sc->sc_last_translate, 1); + sc->sc_last_translate = -1; + } + } + return; + } + if (bit >= sc->sc_nkeys) + goto unknown; + + if (raw) { + u_char c; + + if (ucc_bit_to_raw(sc, bit, &c)) + goto unknown; + if (c != 0) { + ucc_rawinput(sc, c, 0); + sc->sc_last_raw = c; + return; + } + + /* + * The pressed key does not have a corresponding raw scan code + * which implies that wsbkd must handle the pressed key as if + * being in translating mode, hence the fall through. This is + * only the case for volume related keys. + */ + } + + ucc_input(sc, bit, 0); + if (!raw) + sc->sc_last_translate = bit; + return; + +unknown: + DPRINTF("%s: unknown key: bit %d\n", __func__, bit); +} + +void +ucc_attach_wskbd(struct ucc_softc *sc) +{ + static const struct wskbd_accessops accessops = { + .enable = ucc_enable, + .set_leds = ucc_set_leds, + .ioctl = ucc_ioctl, + }; + struct wskbddev_attach_args a = { + .console = 0, + .keymap = &sc->sc_keymap, + .accessops = &accessops, + .accesscookie = sc, + }; + + sc->sc_keydesc[0].name = KB_US; + sc->sc_keydesc[0].base = 0; + sc->sc_keydesc[0].map_size = sc->sc_maplen; + sc->sc_keydesc[0].map = sc->sc_map; + sc->sc_keymap.keydesc = sc->sc_keydesc; + sc->sc_keymap.layout = KB_US | KB_DEFAULT; + sc->sc_wskbddev = config_found(&sc->sc_hdev.sc_dev, &a, wskbddevprint); +} + +int +ucc_enable(void *v, int on) +{ + struct ucc_softc *sc = (struct ucc_softc *)v; + int error = 0; + + if (on) + error = uhidev_open(&sc->sc_hdev); + else + uhidev_close(&sc->sc_hdev); + return error; +} + +void +ucc_set_leds(void *v, int leds) +{ +} + +int +ucc_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct ucc_softc *sc = (struct ucc_softc *)v; + + switch (cmd) { + /* wsconsctl(8) stub */ + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_USB; + return 0; + + /* wsconsctl(8) stub */ + case WSKBDIO_GETLEDS: + *(int *)data = 0; + return 0; + +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + sc->sc_mode = *(int *)data; + return 0; +#endif + } + + return -1; +} + +/* + * Parse the HID report and construct a mapping between the bits in the input + * report and the corresponding pressed key. + */ +int +ucc_parse_hid(struct ucc_softc *sc, void *desc, int descsiz) +{ + struct hid_item hi; + struct hid_data *hd; + int isize; + + /* + * The size of the input report is expressed in bytes where each bit in + * turn represents a pressed key. It's likely that the number of keys is + * less than this generous estimate. + */ + isize = sc->sc_hdev.sc_isize * 8; + if (isize == 0) + return ENXIO; + + /* + * Create mapping between each input bit and the corresponding key used + * in translating mode. Two entries are needed per bit in order + * construct a mapping. + */ + sc->sc_mapsiz = isize * 2 * sizeof(*sc->sc_map); + sc->sc_map = mallocarray(isize, 2 * sizeof(*sc->sc_map), M_USBDEV, + M_WAITOK | M_ZERO); + + /* + * Create mapping between each input bit and the corresponding scan + * code used in raw mode. + */ + sc->sc_rawsiz = isize * sizeof(*sc->sc_raw); + sc->sc_raw = mallocarray(isize, sizeof(*sc->sc_raw), M_USBDEV, + M_WAITOK | M_ZERO); + + hd = hid_start_parse(desc, descsiz, hid_input); + while (hid_get_item(hd, &hi)) { + const struct ucc_keysym *us; + int bit; + + if (HID_GET_USAGE_PAGE(hi.usage) != HUP_CONSUMER || + HID_GET_USAGE(hi.usage) == HUC_CONTROL) + continue; + + bit = sc->sc_nkeys++; + if (ucc_usage_to_sym(HID_GET_USAGE(hi.usage), &us)) + continue; + + if (sc->sc_maplen + 2 >= sc->sc_mapsiz) + return ENOMEM; + sc->sc_map[sc->sc_maplen++] = KS_KEYCODE(bit); + sc->sc_map[sc->sc_maplen++] = us->us_key; + + if (sc->sc_rawlen + 1 >= sc->sc_rawsiz) + return ENOMEM; + sc->sc_raw[sc->sc_rawlen].ur_bit = bit; + sc->sc_raw[sc->sc_rawlen].ur_raw = us->us_raw; + sc->sc_rawlen++; + + DPRINTF("%s: bit %d, usage %s\n", __func__, + bit, us->us_name); + } + hid_end_parse(hd); + + return 0; +} + +int +ucc_bit_to_raw(struct ucc_softc *sc, u_int bit, u_char *raw) +{ + u_int i; + + for (i = 0; i < sc->sc_rawlen; i++) { + const struct ucc_keyraw *ur = &sc->sc_raw[i]; + + if (ur->ur_bit == bit) { + *raw = ur->ur_raw; + return 0; + } + } + return 1; +} + +int +ucc_usage_to_sym(int32_t usage, const struct ucc_keysym **us) +{ + int len = nitems(ucc_keysyms); + int i; + + for (i = 0; i < len; i++) { + if (ucc_keysyms[i].us_usage == usage) { + *us = &ucc_keysyms[i]; + return 0; + } + } + return 1; +} + +void +ucc_input(struct ucc_softc *sc, u_int bit, int release) +{ + int s; + + s = spltty(); + wskbd_input(sc->sc_wskbddev, + release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN, bit); + splx(s); +} + +void +ucc_rawinput(struct ucc_softc *sc, u_char c, int release) +{ + u_char buf[2]; + int len = 0; + int s; + + if (c & 0x80) + buf[len++] = 0xe0; + buf[len++] = c & 0x7f; + if (release) + buf[len - 1] |= 0x80; + + s = spltty(); + wskbd_rawinput(sc->sc_wskbddev, buf, len); + splx(s); +} + +int +ucc_setbits(u_char *data, int len, u_int *bit) +{ + int i, j; + + for (i = 0; i < len; i++) { + if (data[i] == 0) + continue; + + for (j = 0; j < 8; j++) { + if (data[i] & (1 << j)) { + *bit = (i * 8) + j; + return 0; + } + } + } + + return 1; +} + +#ifdef UCC_DEBUG + +void +ucc_dump(const char *prefix, u_char *data, u_int len) +{ + u_int i; + + if (ucc_debug == 0) + return; + + printf("%s:", prefix); + for (i = 0; i < len; i++) + printf(" %02x", data[i]); + printf("\n"); +} + +#endif |