Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Support more varieties of USB keyboard reports.
details: https://anonhg.NetBSD.org/src/rev/187a812476d3
branches: trunk
changeset: 355775:187a812476d3
user: jakllsch <jakllsch%NetBSD.org@localhost>
date: Sun Aug 13 22:19:56 2017 +0000
description:
Support more varieties of USB keyboard reports.
The previous code asssumed reports would closely match the Bootstrap
Keyboard Protocol. This is no longer always the case, particularly
with higher-end keyboards.
diffstat:
sys/dev/usb/ukbd.c | 176 +++++++++++++++++++++-------------------------------
1 files changed, 70 insertions(+), 106 deletions(-)
diffs (truncated from 310 to 300 lines):
diff -r 882711eb1532 -r 187a812476d3 sys/dev/usb/ukbd.c
--- a/sys/dev/usb/ukbd.c Sun Aug 13 21:11:45 2017 +0000
+++ b/sys/dev/usb/ukbd.c Sun Aug 13 22:19:56 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ukbd.c,v 1.137 2017/08/13 21:11:45 jakllsch Exp $ */
+/* $NetBSD: ukbd.c,v 1.138 2017/08/13 22:19:56 jakllsch Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.137 2017/08/13 21:11:45 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ukbd.c,v 1.138 2017/08/13 22:19:56 jakllsch Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -83,12 +83,11 @@
#define DPRINTFN(n,x)
#endif
-#define MAXKEYCODE 6
-#define MAXMOD 8 /* max 32 */
+#define MAXKEYCODE 32
+#define MAXKEYS 256
struct ukbd_data {
- uint32_t modifiers;
- uint8_t keycode[MAXKEYCODE];
+ uint8_t keys[MAXKEYS/NBBY];
};
#define PRESS 0x000
@@ -234,19 +233,14 @@
#define KEY_ERROR 0x01
-#define MAXKEYS (MAXMOD+2*MAXKEYCODE)
-
struct ukbd_softc {
struct uhidev sc_hdev;
struct ukbd_data sc_ndata;
struct ukbd_data sc_odata;
- struct hid_location sc_modloc[MAXMOD];
- u_int sc_nmod;
- struct {
- uint32_t mask;
- uint8_t key;
- } sc_mods[MAXMOD];
+ struct hid_location sc_keyloc[MAXKEYS];
+ uint8_t sc_keyuse[MAXKEYS];
+ u_int sc_nkeyloc;
struct hid_location sc_keycodeloc;
u_int sc_nkeycode;
@@ -307,15 +301,17 @@
void
ukbdtracedump(void)
{
- int i;
+ size_t i, j;
for (i = 0; i < UKBDTRACESIZE; i++) {
struct ukbdtraceinfo *p =
&ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
- printf("%"PRIu64".%06"PRIu64": mod=0x%02x key0=0x%02x key1=0x%02x "
- "key2=0x%02x key3=0x%02x\n",
- p->tv.tv_sec, (uint64_t)p->tv.tv_usec,
- p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
- p->ud.keycode[2], p->ud.keycode[3]);
+ printf("%"PRIu64".%06"PRIu64":", p->tv.tv_sec,
+ (uint64_t)p->tv.tv_usec);
+ for (j = 0; j < MAXKEYS; j++) {
+ if (isset(p->ud.keys, j))
+ printf(" %zu", j);
+ }
+ printf(".\n");
}
}
#endif
@@ -438,7 +434,7 @@
#endif
#ifdef DIAGNOSTIC
- aprint_normal(": %d modifier keys, %d key codes", sc->sc_nmod,
+ aprint_normal(": %d Variable keys, %d Array codes", sc->sc_nkeyloc,
sc->sc_nkeycode);
if (sc->sc_flags & FLAG_APPLE_FN)
aprint_normal(", apple fn key");
@@ -595,21 +591,22 @@
const struct ukbd_keycodetrans *tab)
{
const struct ukbd_keycodetrans *tp;
+ struct ukbd_data oud;
int i;
- uint8_t key;
+
+ oud = *ud;
- for (i = 0; i < sc->sc_nkeycode; i++) {
- key = ud->keycode[i];
- if (key)
+ for (i = 4; i < MAXKEYS; i++) {
+ if (isset(oud.keys, i))
for (tp = tab; tp->from; tp++)
- if (tp->from == key) {
+ if (tp->from == i) {
if (tp->to & IS_PMF) {
pmf_event_inject(
sc->sc_hdev.sc_dev,
tp->to & 0xff);
- ud->keycode[i] = 0;
} else
- ud->keycode[i] = tp->to;
+ setbit(ud->keys, tp->to);
+ clrbit(ud->keys, i);
break;
}
}
@@ -652,12 +649,18 @@
}
#endif
- ud->modifiers = 0;
- for (i = 0; i < sc->sc_nmod; i++)
- if (hid_get_data(ibuf, &sc->sc_modloc[i]))
- ud->modifiers |= sc->sc_mods[i].mask;
- memcpy(ud->keycode, (char *)ibuf + sc->sc_keycodeloc.pos / 8,
- sc->sc_nkeycode);
+ memset(ud->keys, 0, sizeof(ud->keys));
+
+ for (i = 0; i < sc->sc_nkeyloc; i++)
+ if (hid_get_data(ibuf, &sc->sc_keyloc[i]))
+ setbit(ud->keys, sc->sc_keyuse[i]);
+
+ const uint8_t * const scancode = (char *)ibuf + sc->sc_keycodeloc.pos / 8;
+ const uint16_t Keyboard_NoEvent = 0x0000;
+ for (i = 0; i < sc->sc_nkeycode; i++) {
+ if (scancode[i] != Keyboard_NoEvent)
+ setbit(ud->keys, scancode[i]);
+ }
if (sc->sc_flags & FLAG_APPLE_FN) {
if (hid_get_data(ibuf, &sc->sc_apple_fn)) {
@@ -714,10 +717,12 @@
void
ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
{
- int mod, omod;
uint16_t ibuf[MAXKEYS]; /* chars events */
int s;
- int nkeys, i, j;
+ int nkeys, i;
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+ int j;
+#endif
int key;
#define ADDKEY(c) do { \
KASSERT(nkeys < MAXKEYS); \
@@ -740,15 +745,17 @@
if (ukbddebug > 5) {
struct timeval tv;
microtime(&tv);
- DPRINTF((" at %"PRIu64".%06"PRIu64" mod=0x%02x key0=0x%02x key1=0x%02x "
- "key2=0x%02x key3=0x%02x\n",
- tv.tv_sec, (uint64_t)tv.tv_usec,
- ud->modifiers, ud->keycode[0], ud->keycode[1],
- ud->keycode[2], ud->keycode[3]));
+ DPRINTF((" at %"PRIu64".%06"PRIu64":", tv.tv_sec,
+ (uint64_t)tv.tv_usec));
+ for (size_t k = 0; k < MAXKEYS; k++) {
+ if (isset(ud->keys, k))
+ DPRINTF((" %zu", k));
+ }
+ DPRINTF((".\n"));
}
#endif
- if (ud->keycode[0] == KEY_ERROR) {
+ if (isset(ud->keys, KEY_ERROR)) {
DPRINTF(("ukbd_intr: KEY_ERROR\n"));
return; /* ignore */
}
@@ -757,61 +764,19 @@
ukbd_translate_keycodes(sc, ud, trtab_apple_iso);
nkeys = 0;
- mod = ud->modifiers;
- omod = sc->sc_odata.modifiers;
- if (mod != omod)
- for (i = 0; i < sc->sc_nmod; i++)
- if (( mod & sc->sc_mods[i].mask) !=
- (omod & sc->sc_mods[i].mask)) {
- key = sc->sc_mods[i].key |
- ((mod & sc->sc_mods[i].mask) ?
- PRESS : RELEASE);
+ for (i = 0; i < MAXKEYS; i++) {
+#ifdef GDIUM_KEYBOARD_HACK
+ if (sc->sc_flags & FLAG_GDIUM_FN && i == 0x82) {
+ if (isset(ud->keys, i))
+ sc->sc_flags |= FLAG_FN_PRESSED;
+ else
+ sc->sc_flags &= ~FLAG_FN_PRESSED;
+ }
+#endif
+ if (isset(ud->keys, i) != isset(sc->sc_odata.keys, i)) {
+ key = i | ((isset(ud->keys, i) ? PRESS : RELEASE));
ADDKEY(ukbd_translate_modifier(sc, key));
}
- if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
- /* Check for released keys. */
- for (i = 0; i < sc->sc_nkeycode; i++) {
- key = sc->sc_odata.keycode[i];
- if (key == 0)
- continue;
- for (j = 0; j < sc->sc_nkeycode; j++)
- if (key == ud->keycode[j])
- goto rfound;
- DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
-#ifdef GDIUM_KEYBOARD_HACK
- if (sc->sc_flags & FLAG_GDIUM_FN) {
- if (key == 0x82) {
- sc->sc_flags &= ~FLAG_FN_PRESSED;
- goto rfound;
- }
- }
-#endif
- ADDKEY(key | RELEASE);
- rfound:
- ;
- }
-
- /* Check for pressed keys. */
- for (i = 0; i < sc->sc_nkeycode; i++) {
- key = ud->keycode[i];
- if (key == 0)
- continue;
- for (j = 0; j < sc->sc_nkeycode; j++)
- if (key == sc->sc_odata.keycode[j])
- goto pfound;
- DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
-#ifdef GDIUM_KEYBOARD_HACK
- if (sc->sc_flags & FLAG_GDIUM_FN) {
- if (key == 0x82) {
- sc->sc_flags |= FLAG_FN_PRESSED;
- goto pfound;
- }
- }
-#endif
- ADDKEY(key | PRESS);
- pfound:
- ;
- }
}
sc->sc_odata = *ud;
@@ -1052,10 +1017,10 @@
struct hid_item h;
int size;
void *desc;
- int imod;
+ int ikey;
uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
- imod = 0;
+ ikey = 0;
sc->sc_nkeycode = 0;
d = hid_start_parse(desc, size, hid_input);
while (hid_get_item(d, &h)) {
@@ -1074,8 +1039,8 @@
HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
h.report_ID != sc->sc_hdev.sc_report_id)
continue;
- DPRINTF(("ukbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
- "cnt=%d\n", imod,
+ DPRINTF(("ukbd: ikey=%d usage=0x%x flags=0x%x pos=%d size=%d "
+ "cnt=%d\n", ikey,
h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
if (h.flags & HIO_VARIABLE) {
if (h.loc.size != 1) {
@@ -1083,14 +1048,13 @@
return "bad modifier size";
}
/* Single item */
- if (imod < MAXMOD) {
- sc->sc_modloc[imod] = h.loc;
- sc->sc_mods[imod].mask = 1 << imod;
- sc->sc_mods[imod].key = HID_GET_USAGE(h.usage);
- imod++;
+ if (ikey < MAXKEYS) {
+ sc->sc_keyloc[ikey] = h.loc;
+ sc->sc_keyuse[ikey] = HID_GET_USAGE(h.usage);
+ ikey++;
} else {
hid_end_parse(d);
- return "too many modifier keys";
+ return "too many Variable keys";
}
} else {
Home |
Main Index |
Thread Index |
Old Index