diff options
author | Anton Lindqvist <anton@cvs.openbsd.org> | 2021-08-25 05:45:34 +0000 |
---|---|---|
committer | Anton Lindqvist <anton@cvs.openbsd.org> | 2021-08-25 05:45:34 +0000 |
commit | 58ed82de6472515cd4420a639041dd3fa3e62973 (patch) | |
tree | 5290aed81a11423035c6fe7eef47c6b5e5c74cd5 /sys/dev | |
parent | 63266e8d80ad20ae82c1f52d519c8b603ae2e482 (diff) |
Determine if a hid item is an array by solely inspecting presence of
associated min/max boundaries. Assuming that every usage array starts
with the Control usage is incorrect.
Fixes claudio@'s GMMK keyboard and partial fix for florian@'s Microsoft
Sculpt keyboard.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/ucc.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/sys/dev/usb/ucc.c b/sys/dev/usb/ucc.c index 332a31e708d..6043d707e14 100644 --- a/sys/dev/usb/ucc.c +++ b/sys/dev/usb/ucc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ucc.c,v 1.6 2021/08/24 10:53:43 anton Exp $ */ +/* $OpenBSD: ucc.c,v 1.7 2021/08/25 05:45:33 anton Exp $ */ /* * Copyright (c) 2021 Anton Lindqvist <anton@openbsd.org> @@ -87,6 +87,7 @@ int ucc_ioctl(void *, u_long, caddr_t, int, struct proc *); int ucc_hid_parse(struct ucc_softc *, void *, int); int ucc_hid_parse_array(struct ucc_softc *, const struct hid_item *); +int ucc_hid_is_array(const struct hid_item *); int ucc_add_key(struct ucc_softc *, int32_t, u_int); int ucc_bit_to_raw(struct ucc_softc *, u_int, u_char *); int ucc_usage_to_sym(int32_t, const struct ucc_keysym **); @@ -337,6 +338,7 @@ ucc_hid_parse(struct ucc_softc *sc, void *desc, int descsiz) struct hid_item hi; struct hid_data *hd; int nsyms = nitems(ucc_keysyms); + int error = 0; int isize; /* @@ -369,30 +371,28 @@ ucc_hid_parse(struct ucc_softc *sc, void *desc, int descsiz) hd = hid_start_parse(desc, descsiz, hid_input); while (hid_get_item(hd, &hi)) { u_int bit; - int error; - if (HID_GET_USAGE_PAGE(hi.usage) != HUP_CONSUMER) + if (hi.kind != hid_input || + HID_GET_USAGE_PAGE(hi.usage) != HUP_CONSUMER) continue; /* * The usages could be expressed as an array instead of * enumerating all supported ones. */ - if (HID_GET_USAGE(hi.usage) == HUC_CONTROL) { + if (ucc_hid_is_array(&hi)) { error = ucc_hid_parse_array(sc, &hi); - if (error) - return error; - continue; + break; } bit = sc->sc_nusages++; error = ucc_add_key(sc, HID_GET_USAGE(hi.usage), bit); if (error) - return error; + break; } hid_end_parse(hd); - return 0; + return error; } int @@ -402,15 +402,13 @@ ucc_hid_parse_array(struct ucc_softc *sc, const struct hid_item *hi) min = HID_GET_USAGE(hi->usage_minimum); max = HID_GET_USAGE(hi->usage_maximum); - if (min < 0 || max < 0 || min >= max) - return 0; + sc->sc_nusages = (max - min) + 1; sc->sc_isarray = 1; for (usage = min; usage <= max; usage++) { int error; - sc->sc_nusages++; error = ucc_add_key(sc, usage, 0); if (error) return error; @@ -420,6 +418,16 @@ ucc_hid_parse_array(struct ucc_softc *sc, const struct hid_item *hi) } int +ucc_hid_is_array(const struct hid_item *hi) +{ + int32_t max, min; + + min = HID_GET_USAGE(hi->usage_minimum); + max = HID_GET_USAGE(hi->usage_maximum); + return min >= 0 && max > 0 && min < max; +} + +int ucc_add_key(struct ucc_softc *sc, int32_t usage, u_int bit) { const struct ucc_keysym *us; |