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/fc2764f64b84
branches:  trunk
changeset: 826076:fc2764f64b84
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 d28a21aea964 -r fc2764f64b84 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