summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/alpha/conf/GENERIC4
-rw-r--r--sys/arch/amd64/conf/GENERIC4
-rw-r--r--sys/arch/arm64/conf/GENERIC4
-rw-r--r--sys/arch/armv7/conf/GENERIC4
-rw-r--r--sys/arch/hppa/conf/GENERIC4
-rw-r--r--sys/arch/i386/conf/GENERIC4
-rw-r--r--sys/arch/landisk/conf/GENERIC4
-rw-r--r--sys/arch/loongson/conf/GENERIC4
-rw-r--r--sys/arch/macppc/conf/GENERIC4
-rw-r--r--sys/arch/octeon/conf/GENERIC4
-rw-r--r--sys/arch/powerpc64/conf/GENERIC4
-rw-r--r--sys/arch/sparc64/conf/GENERIC4
-rw-r--r--sys/dev/usb/files.usb7
-rw-r--r--sys/dev/usb/ucc.c489
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