Factorization of the bluetooth and usb hid input driver logic, to reduce code
authormiod <miod@openbsd.org>
Sat, 31 Jul 2010 16:04:46 +0000 (16:04 +0000)
committermiod <miod@openbsd.org>
Sat, 31 Jul 2010 16:04:46 +0000 (16:04 +0000)
duplication and divergence.
Thanks to mlarkin@ for bluetooth devices tests.

15 files changed:
sys/arch/loongson/dev/kb3310.c
sys/arch/sparc64/dev/beep.c
sys/dev/bluetooth/btkbd.c
sys/dev/bluetooth/btms.c
sys/dev/bluetooth/files.bluetooth
sys/dev/isa/pcppi.c
sys/dev/usb/files.usb
sys/dev/usb/hidkbd.c [new file with mode: 0644]
sys/dev/usb/hidkbdsc.h [new file with mode: 0644]
sys/dev/usb/hidkbdvar.h [new file with mode: 0644]
sys/dev/usb/hidms.c [new file with mode: 0644]
sys/dev/usb/hidmsvar.h [new file with mode: 0644]
sys/dev/usb/ukbd.c
sys/dev/usb/ukbdvar.h
sys/dev/usb/ums.c

index ef3d4c1..ab9a463 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kb3310.c,v 1.10 2010/05/08 21:59:56 miod Exp $        */
+/*     $OpenBSD: kb3310.c,v 1.11 2010/07/31 16:04:46 miod Exp $        */
 /*
  * Copyright (c) 2010 Otto Moerbeek <otto@drijf.net>
  *
 
 #include "apm.h"
 #include "pckbd.h"
-#include "ukbd.h"
+#include "hidkbd.h"
 
-#if NPCKBD > 0 || NUKBD > 0
+#if NPCKBD > 0 || NHIDKBD > 0
 #include <dev/ic/pckbcvar.h>
 #include <dev/pckbc/pckbdvar.h>
-#include <dev/usb/ukbdvar.h>
+#include <dev/usb/hidkbdvar.h>
 #endif
 
 struct cfdriver ykbec_cd = {
@@ -76,7 +76,7 @@ struct ykbec_softc {
        bus_space_handle_t      sc_ioh;
        struct ksensor          sc_sensor[YKBEC_NSENSORS];
        struct ksensordev       sc_sensordev;
-#if NPCKBD > 0 || NUKBD > 0
+#if NPCKBD > 0 || NHIDKBD > 0
        struct timeout          sc_bell_tmo;
 #endif
 };
@@ -178,13 +178,13 @@ ykbec_attach(struct device *parent, struct device *self, void *aux)
        ykbec_refresh(sc);
        apm_setinfohook(ykbec_apminfo);
 #endif
-#if NPCKBD > 0 || NUKBD > 0
+#if NPCKBD > 0 || NHIDKBD > 0
        timeout_set(&sc->sc_bell_tmo, ykbec_bell_stop, sc);
 #if NPCKBD > 0
        pckbd_hookup_bell(ykbec_bell, sc);
 #endif
-#if NUKBD > 0
-       ukbd_hookup_bell(ykbec_bell, sc);
+#if NHIDKBD > 0
+       hidkbd_hookup_bell(ykbec_bell, sc);
 #endif
 #endif
 }
@@ -402,7 +402,7 @@ ykbec_apminfo(struct apm_power_info *info)
 }
 #endif
 
-#if NPCKBD > 0 || NUKBD > 0
+#if NPCKBD > 0 || NHIDKBD > 0
 void
 ykbec_bell(void *arg, u_int pitch, u_int period, u_int volume, int poll)
 {
index 74352c1..ca5680c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: beep.c,v 1.4 2008/01/24 14:54:49 robert Exp $ */
+/*     $OpenBSD: beep.c,v 1.5 2010/07/31 16:04:50 miod Exp $   */
 
 /*
  * Copyright (c) 2006 Jason L. Wright (jason@thought.net)
@@ -45,9 +45,9 @@
 #include <sparc64/dev/ebusreg.h>
 #include <sparc64/dev/ebusvar.h>
 
-#include "ukbd.h"
-#if NUKBD > 0
-#include <dev/usb/ukbdvar.h>
+#include "hidkbd.h"
+#if NHIDKBD > 0
+#include <dev/usb/hidkbdvar.h>
 #endif
 
 #define        BEEP_CTRL               0
@@ -87,7 +87,7 @@ struct cfdriver beep_cd = {
        NULL, "beep", DV_DULL
 };
 
-#if NUKBD > 0
+#if NHIDKBD > 0
 void beep_stop(void *);
 void beep_bell(void *, u_int, u_int, u_int, int);
 #endif
@@ -154,9 +154,9 @@ beep_attach(parent, self, aux)
 
        printf(": clock %sMHz\n", clockfreq(sc->sc_clk));
 
-#if NUKBD > 0
+#if NHIDKBD > 0
        timeout_set(&sc->sc_to, beep_stop, sc);
-       ukbd_hookup_bell(beep_bell, sc);
+       hidkbd_hookup_bell(beep_bell, sc);
 #endif
 }
 
@@ -200,7 +200,7 @@ beep_setfreq(struct beep_softc *sc, int freq)
            (sc->sc_freqs[i].reg >>  0) & 0xff);
 }
 
-#if NUKBD > 0
+#if NHIDKBD > 0
 void
 beep_stop(void *vsc)
 {
@@ -244,4 +244,4 @@ beep_bell(void *vsc, u_int pitch, u_int period, u_int volume, int poll)
        }
        splx(s);
 }
-#endif /* NUKBD > 0 */
+#endif /* NHIDKBD > 0 */
index 863f6c5..ff34824 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: btkbd.c,v 1.5 2009/01/21 21:53:59 grange Exp $        */
+/*     $OpenBSD: btkbd.c,v 1.6 2010/07/31 16:04:50 miod Exp $  */
 /*     $NetBSD: btkbd.c,v 1.10 2008/09/09 03:54:56 cube Exp $  */
 
 /*
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * based on dev/usb/ukbd.c
- */
-
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/device.h>
 #include <dev/wscons/wsksymdef.h>
 #include <dev/wscons/wsksymvar.h>
 
-#define        MAXKEYCODE              6
-#define MAXMOD                 8       /* max 32 */
-#define MAXKEYS                        (MAXMOD + (2 * MAXKEYCODE))
-
-struct btkbd_data {
-       uint32_t                modifiers;
-       uint8_t                 keycode[MAXKEYCODE];
-};
-
-struct btkbd_mod {
-       uint32_t                mask;
-       uint8_t                 key;
-};
+#include <dev/usb/hidkbdsc.h>
+#include <dev/usb/hidkbdvar.h>
 
 struct btkbd_softc {
-       struct bthidev           sc_hidev;      /* device+ */
-       struct device           *sc_wskbd;      /* child */
-       int                      sc_enabled;
-
+       struct bthidev           sc_hidev;      /* device */
+       struct hidkbd            sc_kbd;        /* keyboard state */
        int                     (*sc_output)    /* output method */
                                (struct bthidev *, uint8_t *, int);
-
-       /* stored data */
-       struct btkbd_data        sc_odata;
-       struct btkbd_data        sc_ndata;
-
-       /* input reports */
-       int                      sc_nmod;
-       struct hid_location      sc_modloc[MAXMOD];
-       struct btkbd_mod         sc_mods[MAXMOD];
-
-       int                      sc_nkeycode;
-       struct hid_location      sc_keycodeloc;
-
-       /* output reports */
-       struct hid_location      sc_numloc;
-       struct hid_location      sc_capsloc;
-       struct hid_location      sc_scroloc;
-       int                      sc_leds;
-
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       int                      sc_rawkbd;
-#ifdef BTKBD_REPEAT
-       struct timeout           sc_repeat;
-       int                      sc_nrep;
-       char                     sc_rep[MAXKEYS];
-#endif
-#endif
 };
 
 /* autoconf(9) methods */
@@ -151,6 +107,7 @@ const struct cfattach btkbd_ca = {
        btkbd_match,
        btkbd_attach,
        btkbd_detach,
+       /* XXX activate */
 };
 
 /* wskbd(4) accessops */
@@ -164,32 +121,8 @@ const struct wskbd_accessops btkbd_accessops = {
        btkbd_ioctl
 };
 
-/* wskbd(4) keymap data */
-extern const struct wscons_keydesc ukbd_keydesctab[];
-
-const struct wskbd_mapdata btkbd_keymapdata = {
-       ukbd_keydesctab,
-#if defined(BTKBD_LAYOUT)
-       BTKBD_LAYOUT,
-#elif defined(PCKBD_LAYOUT)
-       PCKBD_LAYOUT,
-#else
-       KB_US,
-#endif
-};
-
 /* bthid methods */
-void btkbd_input(struct bthidev *, uint8_t *, int);
-
-/* internal prototypes */
-const char *btkbd_parse_desc(struct btkbd_softc *, int, void *, int);
-
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-#ifdef BTKBD_REPEAT
-void btkbd_repeat(void *);
-#endif
-#endif
-
+void   btkbd_input(struct bthidev *, uint8_t *, int);
 
 int
 btkbd_match(struct device *self, void *match, void *aux)
@@ -207,379 +140,82 @@ void
 btkbd_attach(struct device *parent, struct device *self, void *aux)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
        struct bthidev_attach_args *ba = aux;
-       struct wskbddev_attach_args wska;
-       const char *parserr;
+       kbd_t layout;
 
        sc->sc_output = ba->ba_output;
-       ba->ba_input = btkbd_input;
+       ba->ba_input = btkbd_input;                     /* XXX ugly */
 
-       parserr = btkbd_parse_desc(sc, ba->ba_id, ba->ba_desc, ba->ba_dlen);
-       if (parserr != NULL) {
-               printf("%s\n", parserr);
+       if (hidkbd_attach(self, kbd, 0, 0,
+           ba->ba_id, ba->ba_desc, ba->ba_dlen) != 0)
                return;
-       }
 
        printf("\n");
 
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-#ifdef BTKBD_REPEAT
-       timeout_set(&sc->sc_repeat, btkbd_repeat, sc);
-#endif
+#if defined(BTKBD_LAYOUT)
+       layout = BTKBD_LAYOUT;
+#else
+       layout = KB_US;
 #endif
-
-       wska.console = 0;
-       wska.keymap = &btkbd_keymapdata;
-       wska.accessops = &btkbd_accessops;
-       wska.accesscookie = sc;
-
-       sc->sc_wskbd = config_found((struct device *)sc, &wska, wskbddevprint);
+       hidkbd_attach_wskbd(kbd, layout, &btkbd_accessops);
 }
 
 int
 btkbd_detach(struct device *self, int flags)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
-       int err = 0;
 
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-#ifdef BTKBD_REPEAT
-       timeout_del(&sc->sc_repeat);
-#endif
-#endif
-
-       if (sc->sc_wskbd != NULL) {
-               err = config_detach(sc->sc_wskbd, flags);
-               sc->sc_wskbd = NULL;
-       }
-
-       return err;
-}
-
-const char *
-btkbd_parse_desc(struct btkbd_softc *sc, int id, void *desc, int dlen)
-{
-       struct hid_data *d;
-       struct hid_item h;
-       int imod;
-
-       imod = 0;
-       sc->sc_nkeycode = 0;
-       d = hid_start_parse(desc, dlen, hid_input);
-       while (hid_get_item(d, &h)) {
-               if (h.kind != hid_input || (h.flags & HIO_CONST) ||
-                   HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
-                   h.report_ID != id)
-                       continue;
-
-               if (h.flags & HIO_VARIABLE) {
-                       if (h.loc.size != 1)
-                               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++;
-                       } else
-                               return ("too many modifier keys");
-               } else {
-                       /* Array */
-                       if (h.loc.size != 8)
-                               return ("key code size != 8");
-
-                       if (h.loc.count > MAXKEYCODE)
-                               return ("too many key codes");
-
-                       if (h.loc.pos % 8 != 0)
-                               return ("key codes not on byte boundary");
-
-                       if (sc->sc_nkeycode != 0)
-                               return ("multiple key code arrays\n");
-
-                       sc->sc_keycodeloc = h.loc;
-                       sc->sc_nkeycode = h.loc.count;
-               }
-       }
-       sc->sc_nmod = imod;
-       hid_end_parse(d);
-
-       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
-           id, hid_output, &sc->sc_numloc, NULL);
-
-       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
-           id, hid_output, &sc->sc_capsloc, NULL);
-
-       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
-           id, hid_output, &sc->sc_scroloc, NULL);
-
-       return (NULL);
+       return hidkbd_detach(&sc->sc_kbd, flags);
 }
 
 int
 btkbd_enable(void *self, int on)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
 
-       sc->sc_enabled = on;
-       return 0;
+       return hidkbd_enable(kbd, on);
 }
 
 void
 btkbd_set_leds(void *self, int leds)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
        uint8_t report;
 
-       if (sc->sc_leds == leds)
-               return;
-
-       sc->sc_leds = leds;
-
-       /*
-        * This is not totally correct, since we did not check the
-        * report size from the descriptor but for keyboards it should
-        * just be a single byte with the relevant bits set.
-        */
-       report = 0;
-       if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
-               report |= 1 << sc->sc_scroloc.pos;
-
-       if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
-               report |= 1 << sc->sc_numloc.pos;
-
-       if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
-               report |= 1 << sc->sc_capsloc.pos;
-
-       if (sc->sc_output)
-               (*sc->sc_output)(&sc->sc_hidev, &report, sizeof(report));
+       if (hidkbd_set_leds(kbd, leds, &report) != 0) {
+               if (sc->sc_output != NULL)
+                       (*sc->sc_output)(&sc->sc_hidev, &report,
+                           sizeof(report));
+       }
 }
 
 int
 btkbd_ioctl(void *self, u_long cmd, caddr_t data, int flag, struct proc *p)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
 
        switch (cmd) {
        case WSKBDIO_GTYPE:
                *(int *)data = WSKBD_TYPE_BLUETOOTH;
                return 0;
-
        case WSKBDIO_SETLEDS:
                btkbd_set_leds(sc, *(int *)data);
                return 0;
-
-       case WSKBDIO_GETLEDS:
-               *(int *)data = sc->sc_leds;
-               return 0;
-
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       case WSKBDIO_SETMODE:
-               sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
-#ifdef BTKBD_REPEAT
-               timeout_del(&sc->sc_repeat);
-#endif
-               return 0;
-#endif
+       default:
+               return hidkbd_ioctl(kbd, cmd, data, flag, p);
        }
-       return -1;
 }
 
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-#define NN 0                   /* no translation */
-/*
- * Translate USB keycodes to US keyboard XT scancodes.
- * Scancodes >= 0x80 represent EXTENDED keycodes.
- *
- * See http://www.microsoft.com/HWDEV/TECH/input/Scancode.asp
- */
-const u_int8_t btkbd_trtab[256] = {
-      NN,   NN,   NN,   NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
-    0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
-    0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
-    0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
-    0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
-    0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
-    0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
-    0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
-    0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
-    0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
-    0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
-    0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
-    0x48, 0x49, 0x52, 0x53, 0x56, 0xdd,   NN, 0x59, /* 60 - 67 */
-    0x5d, 0x5e, 0x5f,   NN,   NN,   NN,   NN,   NN, /* 68 - 6f */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 70 - 77 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 78 - 7f */
-      NN,   NN,   NN,   NN,   NN, 0x7e,   NN, 0x73, /* 80 - 87 */
-    0x70, 0x7d, 0x79, 0x7b, 0x5c,   NN,   NN,   NN, /* 88 - 8f */
-      NN,   NN, 0x78, 0x77, 0x76,   NN,   NN,   NN, /* 90 - 97 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 98 - 9f */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a0 - a7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a8 - af */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b0 - b7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b8 - bf */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c0 - c7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c8 - cf */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d0 - d7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d8 - df */
-    0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* e8 - ef */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f0 - f7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f8 - ff */
-};
-#endif
-
-#define KEY_ERROR      0x01
-#define PRESS          0x000
-#define RELEASE                0x100
-#define CODEMASK       0x0ff
-#define ADDKEY(c)      ibuf[nkeys++] = (c)
-#define REP_DELAY1     400
-#define REP_DELAYN     100
-
 void
 btkbd_input(struct bthidev *self, uint8_t *data, int len)
 {
        struct btkbd_softc *sc = (struct btkbd_softc *)self;
-       struct btkbd_data *ud = &sc->sc_ndata;
-       uint16_t ibuf[MAXKEYS];
-       uint32_t mod, omod;
-       int nkeys, i, j;
-       int key;
-       int s;
-
-       if (sc->sc_wskbd == NULL || sc->sc_enabled == 0)
-               return;
-
-       /* extract key modifiers */
-       ud->modifiers = 0;
-       for (i = 0 ; i < sc->sc_nmod ; i++)
-               if (hid_get_data(data, &sc->sc_modloc[i]))
-                       ud->modifiers |= sc->sc_mods[i].mask;
-
-       /* extract keycodes */
-       memcpy(ud->keycode, data + (sc->sc_keycodeloc.pos / 8),
-           sc->sc_nkeycode);
-
-       if (ud->keycode[0] == KEY_ERROR)
-               return;         /* ignore  */
-
-       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))
-                               ADDKEY(sc->sc_mods[i].key |
-                                   (mod & sc->sc_mods[i].mask
-                                   ? PRESS : RELEASE));
-
-       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;
-
-                       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;
-
-                       ADDKEY(key | PRESS);
-               pfound:
-                       ;
-               }
-       }
-       sc->sc_odata = *ud;
-
-       if (nkeys == 0)
-               return;
-
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       if (sc->sc_rawkbd) {
-               u_char cbuf[MAXKEYS * 2];
-               int c;
-               int npress;
-
-               for (npress = i = j = 0 ; i < nkeys ; i++) {
-                       key = ibuf[i];
-                       c = btkbd_trtab[key & CODEMASK];
-                       if (c == NN)
-                               continue;
-
-                       if (c & 0x80)
-                               cbuf[j++] = 0xe0;
-
-                       cbuf[j] = c & 0x7f;
-                       if (key & RELEASE)
-                               cbuf[j] |= 0x80;
-#ifdef BTKBD_REPEAT
-                       else {
-                               /* remember pressed keys for autorepeat */
-                               if (c & 0x80)
-                                       sc->sc_rep[npress++] = 0xe0;
-
-                               sc->sc_rep[npress++] = c & 0x7f;
-                       }
-#endif
-
-                       j++;
-               }
-
-               s = spltty();
-               wskbd_rawinput(sc->sc_wskbd, cbuf, j);
-               splx(s);
-#ifdef BTKBD_REPEAT
-               timeout_del(&sc->sc_repeat);
-               if (npress != 0) {
-                       sc->sc_nrep = npress;
-                       timeout_add_msec(&sc->sc_repeat, REP_DELAY1);
-               }
-#endif
-               return;
-       }
-#endif
-
-       s = spltty();
-       for (i = 0 ; i < nkeys ; i++) {
-               key = ibuf[i];
-               wskbd_input(sc->sc_wskbd,
-                   key & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
-                   key & CODEMASK);
-       }
-       splx(s);
-}
+       struct hidkbd *kbd = &sc->sc_kbd;
 
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-#ifdef BTKBD_REPEAT
-void
-btkbd_repeat(void *arg)
-{
-       struct btkbd_softc *sc = arg;
-       int s;
-
-       s = spltty();
-       wskbd_rawinput(sc->sc_wskbd, sc->sc_rep, sc->sc_nrep);
-       splx(s);
-       timeout_add_msec(&sc->sc_repeat, REP_DELAYN);
+       if (kbd->sc_enabled != 0)
+               hidkbd_input(kbd, data, len);
 }
-#endif
-#endif
index 7ef3d45..8ae2d02 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: btms.c,v 1.4 2008/11/22 04:42:58 uwe Exp $    */
+/*     $OpenBSD: btms.c,v 1.5 2010/07/31 16:04:50 miod Exp $   */
 /*     $NetBSD: btms.c,v 1.8 2008/09/09 03:54:56 cube Exp $    */
 
 /*
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * based on dev/usb/ums.c
- */
-
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/device.h>
 #include <dev/wscons/wsconsio.h>
 #include <dev/wscons/wsmousevar.h>
 
-#define MAX_BUTTONS    31
-#define BUTTON(n)      (1 << (((n) == 1 || (n) == 2) ? 3 - (n) : (n)))
-#define NOTMOUSE(f)    (((f) & (HIO_CONST | HIO_RELATIVE)) != HIO_RELATIVE)
+#include <dev/usb/hidmsvar.h>
 
 struct btms_softc {
-       struct bthidev           sc_hidev;      /* device+ */
-
-       struct device           *sc_wsmouse;    /* child */
-       int                      sc_enabled;
-       uint16_t                 sc_flags;
-
-       /* locators */
-       struct hid_location      sc_loc_x;
-       struct hid_location      sc_loc_y;
-       struct hid_location      sc_loc_z;
-       struct hid_location      sc_loc_w;
-       struct hid_location      sc_loc_button[MAX_BUTTONS];
-
-       int                      sc_num_buttons;
-       uint32_t                 sc_buttons;
+       struct bthidev          sc_hidev;
+       struct hidms            sc_ms;
 };
 
-/* sc_flags */
-#define BTMS_REVZ              (1 << 0)        /* reverse Z direction */
-#define BTMS_HASZ              (1 << 1)        /* has Z direction */
-#define BTMS_HASW              (1 << 2)        /* has W direction */
-
 /* autoconf(9) methods */
 int    btms_match(struct device *, void *, void *);
 void   btms_attach(struct device *, struct device *, void *);
@@ -125,6 +101,7 @@ const struct cfattach btms_ca = {
        btms_match,
        btms_attach,
        btms_detach,
+       /* XXX activate */
 };
 
 /* wsmouse(4) accessops */
@@ -158,189 +135,66 @@ void
 btms_attach(struct device *parent, struct device *self, void *aux)
 {
        struct btms_softc *sc = (struct btms_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
        struct bthidev_attach_args *ba = aux;
-       struct wsmousedev_attach_args wsma;
-       struct hid_location *zloc;
-       uint32_t flags;
-       int i, hl;
-
-       ba->ba_input = btms_input;
-
-       /* control the horizontal */
-       hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), ba->ba_id, hid_input,
-           &sc->sc_loc_x, &flags);
-
-       if (hl == 0 || NOTMOUSE(flags)) {
-               printf("\n%s: X report 0x%04x not supported\n",
-                   sc->sc_hidev.sc_dev.dv_xname, flags);
 
-               return;
-       }
-
-       /* control the vertical */
-       hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), ba->ba_id, hid_input,
-           &sc->sc_loc_y, &flags);
-
-       if (hl == 0 || NOTMOUSE(flags)) {
-               printf("\n%s: Y report 0x%04x not supported\n",
-                   sc->sc_hidev.sc_dev.dv_xname, flags);
+       ba->ba_input = btms_input;                      /* XXX ugly */
 
+       if (hidms_setup(self, ms, 0, ba->ba_id, ba->ba_desc, ba->ba_dlen) != 0)
                return;
-       }
 
-       /* Try the wheel first as the Z activator since it's tradition. */
-       hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), ba->ba_id, hid_input,
-           &sc->sc_loc_z, &flags);
-
-       zloc = &sc->sc_loc_z;
-       if (hl) {
-               if (NOTMOUSE(flags)) {
-                       printf("\n%s: Wheel report 0x%04x ignored\n",
-                           sc->sc_hidev.sc_dev.dv_xname, flags);
-
-                       /* ignore Bad Z coord */
-                       sc->sc_loc_z.size = 0;
-               } else {
-                       sc->sc_flags |= BTMS_HASZ;
-                       /* Wheels need the Z axis reversed. */
-                       sc->sc_flags ^= BTMS_REVZ;
-                       /* Put Z on the W coordinate */
-                       zloc = &sc->sc_loc_w;
-               }
-       }
-
-       hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), ba->ba_id, hid_input,
-           zloc, &flags);
-
-       /*
-        * The horizontal component of the scrollball can also be given by
-        * Application Control Pan in the Consumer page, so if we didnt see
-        * any Z then check that.
-        */
-       if (!hl) {
-               hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-                   HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN), ba->ba_id, hid_input,
-                   zloc, &flags);
-       }
-
-       if (hl) {
-               if (NOTMOUSE(flags))
-                       zloc->size = 0; /* ignore Z */
-               else {
-                       if (sc->sc_flags & BTMS_HASZ)
-                               sc->sc_flags |= BTMS_HASW;
-                       else
-                               sc->sc_flags |= BTMS_HASZ;
-               }
-       }
-
-       for (i = 1 ; i <= MAX_BUTTONS ; i++) {
-               hl = hid_locate(ba->ba_desc, ba->ba_dlen,
-                   HID_USAGE2(HUP_BUTTON, i), ba->ba_id, hid_input,
-                   &sc->sc_loc_button[i - 1], NULL);
-
-               if (hl == 0)
-                       break;
-       }
-       sc->sc_num_buttons = i - 1;
-
-       printf(": %d button%s%s%s%s.\n", sc->sc_num_buttons,
-           sc->sc_num_buttons == 1 ? "" : "s",
-           sc->sc_flags & BTMS_HASW ? ", W" : "",
-           sc->sc_flags & BTMS_HASZ ? " and Z dir" : "",
-           sc->sc_flags & BTMS_HASW ? "s" : "");
-
-       wsma.accessops = &btms_wsmouse_accessops;
-       wsma.accesscookie = sc;
-
-       sc->sc_wsmouse = config_found((struct device *)sc,
-           &wsma, wsmousedevprint);
+       hidms_attach(ms, &btms_wsmouse_accessops);
 }
 
 int
 btms_detach(struct device *self, int flags)
 {
        struct btms_softc *sc = (struct btms_softc *)self;
-       int err = 0;
-
-       if (sc->sc_wsmouse != NULL) {
-               err = config_detach(sc->sc_wsmouse, flags);
-               sc->sc_wsmouse = NULL;
-       }
+       struct hidms *ms = &sc->sc_ms;
 
-       return err;
+       return hidms_detach(ms, flags);
 }
 
 int
 btms_wsmouse_enable(void *self)
 {
        struct btms_softc *sc = (struct btms_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
 
-       if (sc->sc_enabled)
-               return EBUSY;
-
-       sc->sc_enabled = 1;
-       return 0;
+       return hidms_enable(ms);
 }
 
 int
 btms_wsmouse_ioctl(void *self, u_long cmd, caddr_t data, int flag,
     struct proc *p)
 {
-       /* struct btms_softc *sc = (struct btms_softc *)self; */
+       struct btms_softc *sc = (struct btms_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
 
        switch (cmd) {
        case WSMOUSEIO_GTYPE:
                *(u_int *)data = WSMOUSE_TYPE_BLUETOOTH;
                return 0;
+       default:
+               return hidms_ioctl(ms, cmd, data, flag, p);
        }
-
-       return -1;
 }
 
 void
 btms_wsmouse_disable(void *self)
 {
        struct btms_softc *sc = (struct btms_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
 
-       sc->sc_enabled = 0;
+       hidms_disable(ms);
 }
 
 void
 btms_input(struct bthidev *self, uint8_t *data, int len)
 {
        struct btms_softc *sc = (struct btms_softc *)self;
-       int dx, dy, dz, dw;
-       uint32_t buttons;
-       int i, s;
-
-       if (sc->sc_wsmouse == NULL || sc->sc_enabled == 0)
-               return;
-
-       dx =  hid_get_data(data, &sc->sc_loc_x);
-       dy = -hid_get_data(data, &sc->sc_loc_y);
-       dz =  hid_get_data(data, &sc->sc_loc_z);
-       dw =  hid_get_data(data, &sc->sc_loc_w);
+       struct hidms *ms = &sc->sc_ms;
 
-       if (sc->sc_flags & BTMS_REVZ)
-               dz = -dz;
-
-       buttons = 0;
-       for (i = 0 ; i < sc->sc_num_buttons ; i++)
-               if (hid_get_data(data, &sc->sc_loc_button[i]))
-                       buttons |= BUTTON(i);
-
-       if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
-           buttons != sc->sc_buttons) {
-               sc->sc_buttons = buttons;
-
-               s = spltty();
-               wsmouse_input(sc->sc_wsmouse, buttons, dx, dy, dz, dw,
-                   WSMOUSE_INPUT_DELTA);
-               splx(s);
-       }
+       if (ms->sc_enabled != 0)
+               hidms_input(ms, data, len);
 }
index e204487..7f3678b 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.bluetooth,v 1.6 2008/11/24 22:31:19 uwe Exp $
+#      $OpenBSD: files.bluetooth,v 1.7 2010/07/31 16:04:50 miod Exp $
 #
 # Config file and device description for machine-independent Bluetooth code.
 # Included by ports that support Bluetooth host controllers.
@@ -17,12 +17,12 @@ attach bthidev at bthub
 file dev/bluetooth/bthidev.c           bthidev
 
 # HID Mice
-device btms: hid, wsmousedev
+device btms: hid, hidms, wsmousedev
 attach btms at bthidbus
 file dev/bluetooth/btms.c              btms
 
 # HID Keyboard
-device btkbd: hid, wskbddev
+device btkbd: hid, hidkbd, wskbddev
 attach btkbd at bthidbus
 file dev/bluetooth/btkbd.c             btkbd
 
index 57349b1..74582d3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcppi.c,v 1.8 2009/10/13 20:55:41 miod Exp $ */
+/* $OpenBSD: pcppi.c,v 1.9 2010/07/31 16:04:50 miod Exp $ */
 /* $NetBSD: pcppi.c,v 1.1 1998/04/15 20:26:18 drochner Exp $ */
 
 /*
 #include <dev/ic/i8253reg.h>
 
 #include "pckbd.h"
-#include "ukbd.h"
-#if NPCKBD > 0 || NUKBD > 0
+#include "hidkbd.h"
+#if NPCKBD > 0 || NHIDKBD > 0
 #include <dev/ic/pckbcvar.h>
 #include <dev/pckbc/pckbdvar.h>
-#include <dev/usb/ukbdvar.h>
+#include <dev/usb/hidkbdvar.h>
 void   pcppi_kbd_bell(void *, u_int, u_int, u_int, int);
 #endif
 
@@ -174,8 +174,8 @@ pcppi_attach(parent, self, aux)
 #if NPCKBD > 0
        pckbd_hookup_bell(pcppi_kbd_bell, sc);
 #endif
-#if NUKBD > 0
-       ukbd_hookup_bell(pcppi_kbd_bell, sc);
+#if NHIDKBD > 0
+       hidkbd_hookup_bell(pcppi_kbd_bell, sc);
 #endif
 
        pa.pa_cookie = sc;
@@ -259,7 +259,7 @@ pcppi_bell_stop(arg)
        splx(s);
 }
 
-#if NPCKBD > 0 || NUKBD > 0
+#if NPCKBD > 0 || NHIDKBD > 0
 void
 pcppi_kbd_bell(arg, pitch, period, volume, poll)
        void *arg;
@@ -272,4 +272,4 @@ pcppi_kbd_bell(arg, pitch, period, volume, poll)
        pcppi_bell(arg, volume ? pitch : 0, (period * hz) / 1000,
            poll ? PCPPI_BELL_POLL : 0);
 }
-#endif /* NPCKBD > 0 || NUKBD > 0 */
+#endif /* NPCKBD > 0 || NHIDKBD > 0 */
index 741ed82..a7e092a 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.usb,v 1.91 2010/07/03 03:59:17 krw Exp $
+#      $OpenBSD: files.usb,v 1.92 2010/07/31 16:04:50 miod 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.
@@ -80,13 +80,17 @@ attach      uhid at uhidbus
 file   dev/usb/uhid.c                  uhid                    needs-flag
 
 # Keyboards
-device ukbd: hid, wskbddev
+define hidkbd
+file   dev/usb/hidkbd.c                hidkbd                  needs-flag
+file   dev/usb/ukbdmap.c               hidkbd
+device ukbd: hid, hidkbd, wskbddev
 attach ukbd at uhidbus
 file   dev/usb/ukbd.c                  ukbd                    needs-flag
-file   dev/usb/ukbdmap.c               ukbd | btkbd
 
 # Mice
-device ums: hid, wsmousedev
+define hidms
+file   dev/usb/hidms.c                 hidms
+device ums: hid, hidms, wsmousedev
 attach ums at uhidbus
 file   dev/usb/ums.c                   ums
 
diff --git a/sys/dev/usb/hidkbd.c b/sys/dev/usb/hidkbd.c
new file mode 100644 (file)
index 0000000..687790d
--- /dev/null
@@ -0,0 +1,638 @@
+/*     $OpenBSD: hidkbd.c,v 1.1 2010/07/31 16:04:50 miod Exp $ */
+/*      $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $        */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/timeout.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
+
+#include <dev/usb/usb_quirks.h>
+#include <dev/usb/hid.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymdef.h>
+#include <dev/wscons/wsksymvar.h>
+
+#include <dev/usb/hidkbdsc.h>
+#include <dev/usb/hidkbdvar.h>
+
+#ifdef HIDKBD_DEBUG
+#define DPRINTF(x)     do { if (hidkbddebug) printf x; } while (0)
+#define DPRINTFN(n,x)  do { if (hidkbddebug>(n)) printf x; } while (0)
+int    hidkbddebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+#define PRESS    0x000
+#define RELEASE  0x100
+#define CODEMASK 0x0ff
+
+#if defined(WSDISPLAY_COMPAT_RAWKBD)
+#define NN 0                   /* no translation */
+/*
+ * Translate USB keycodes to US keyboard XT scancodes.
+ * Scancodes >= 0x80 represent EXTENDED keycodes.
+ *
+ * See http://www.microsoft.com/whdc/device/input/Scancode.mspx
+ */
+const u_int8_t hidkbd_trtab[256] = {
+      NN,   NN,   NN,   NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
+    0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
+    0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
+    0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
+    0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
+    0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
+    0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
+    0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
+    0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
+    0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
+    0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
+    0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
+    0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, 0x84, 0x59, /* 60 - 67 */
+    0x5d, 0x5e, 0x5f,   NN,   NN,   NN,   NN,   NN, /* 68 - 6f */
+      NN,   NN,   NN,   NN, 0x97,   NN, 0x93, 0x95, /* 70 - 77 */
+    0x91, 0x92, 0x94, 0x9a, 0x96, 0x98, 0x99, 0xa0, /* 78 - 7f */
+    0xb0, 0xae,   NN,   NN,   NN, 0x7e,   NN, 0x73, /* 80 - 87 */
+    0x70, 0x7d, 0x79, 0x7b, 0x5c,   NN,   NN,   NN, /* 88 - 8f */
+      NN,   NN, 0x78, 0x77, 0x76,   NN,   NN,   NN, /* 90 - 97 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 98 - 9f */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a0 - a7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a8 - af */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b0 - b7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b8 - bf */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c0 - c7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c8 - cf */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d0 - d7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d8 - df */
+    0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* e8 - ef */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f0 - f7 */
+      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f8 - ff */
+};
+#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
+
+#define KEY_ERROR 0x01
+
+#ifdef HIDKBD_DEBUG
+#define HIDKBDTRACESIZE 64
+struct hidkbdtraceinfo {
+       int unit;
+       struct timeval tv;
+       struct hidkbd_data ud;
+};
+struct hidkbdtraceinfo hidkbdtracedata[HIDKBDTRACESIZE];
+int hidkbdtraceindex = 0;
+int hidkbdtrace = 0;
+void hidkbdtracedump(void);
+void
+hidkbdtracedump(void)
+{
+       int i;
+       for (i = 0; i < HIDKBDTRACESIZE; i++) {
+               struct hidkbdtraceinfo *p =
+                   &hidkbdtracedata[(i+hidkbdtraceindex)%HIDKBDTRACESIZE];
+               printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
+                      "key2=0x%02x key3=0x%02x\n",
+                      p->tv.tv_sec, p->tv.tv_usec,
+                      p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
+                      p->ud.keycode[2], p->ud.keycode[3]);
+       }
+}
+#endif
+
+int    hidkbd_is_console;
+
+const char *hidkbd_parse_desc(struct hidkbd *, int, void *, int);
+
+void   (*hidkbd_bell_fn)(void *, u_int, u_int, u_int, int);
+void   *hidkbd_bell_fn_arg;
+
+void   hidkbd_decode(struct hidkbd *, struct hidkbd_data *);
+void   hidkbd_delayed_decode(void *addr);
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+void   hidkbd_rawrepeat(void *);
+#endif
+
+extern const struct wscons_keydesc ukbd_keydesctab[];
+
+struct wskbd_mapdata ukbd_keymapdata = {
+       ukbd_keydesctab
+};
+
+int
+hidkbd_attach(struct device *self, struct hidkbd *kbd, int console,
+    uint32_t qflags, int id, void *desc, int dlen)
+{
+       const char *parserr;
+
+       parserr = hidkbd_parse_desc(kbd, id, desc, dlen);
+       if (parserr != NULL) {
+               printf(": %s\n", parserr);
+               return ENXIO;
+       }
+
+#ifdef DIAGNOSTIC
+       printf(": %d modifier keys, %d key codes",
+           kbd->sc_nmod, kbd->sc_nkeycode);
+#endif
+
+       kbd->sc_device = self;
+       kbd->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
+       /*
+        * Remember if we're the console keyboard.
+        *
+        * XXX This always picks the first (USB) keyboard to attach,
+        * but what else can we really do?
+        */
+       if (console) {
+               kbd->sc_console_keyboard = hidkbd_is_console;
+               /* Don't let any other keyboard have it. */
+               hidkbd_is_console = 0;
+       }
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+       timeout_set(&kbd->sc_rawrepeat_ch, hidkbd_rawrepeat, kbd);
+#endif
+       timeout_set(&kbd->sc_delay, hidkbd_delayed_decode, kbd);
+
+       return 0;
+}
+
+void
+hidkbd_attach_wskbd(struct hidkbd *kbd, kbd_t layout,
+    const struct wskbd_accessops *accessops)
+{
+       struct wskbddev_attach_args a;
+
+       ukbd_keymapdata.layout = layout;
+
+       a.console = kbd->sc_console_keyboard;
+       a.keymap = &ukbd_keymapdata;
+       a.accessops = accessops;
+       a.accesscookie = kbd->sc_device;
+       kbd->sc_wskbddev = config_found(kbd->sc_device, &a, wskbddevprint);
+}
+
+int
+hidkbd_detach(struct hidkbd *kbd, int flags)
+{
+       int rv = 0;
+
+       DPRINTF(("hidkbd_detach: sc=%p flags=%d\n", sc, flags));
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+       timeout_del(&kbd->sc_rawrepeat_ch);
+#endif
+
+       if (kbd->sc_console_keyboard) {
+#if 0
+               /*
+                * XXX Should probably disconnect our consops,
+                * XXX and either notify some other keyboard that
+                * XXX it can now be the console, or if there aren't
+                * XXX any more USB keyboards, set hidkbd_is_console
+                * XXX back to 1 so that the next USB keyboard attached
+                * XXX to the system will get it.
+                */
+               panic("hidkbd_detach: console keyboard");
+#else
+               /*
+                * Disconnect our consops and set hidkbd_is_console
+                * back to 1 so that the next USB keyboard attached
+                * to the system will get it.
+                * XXX Should notify some other keyboard that it can be
+                * XXX console, if there are any other keyboards.
+                */
+               printf("%s: was console keyboard\n",
+                      kbd->sc_device->dv_xname);
+               wskbd_cndetach();
+               hidkbd_is_console = 1;
+#endif
+       }
+       /* No need to do reference counting of hidkbd, wskbd has all the goo */
+       if (kbd->sc_wskbddev != NULL)
+               rv = config_detach(kbd->sc_wskbddev, flags);
+
+       return (rv);
+}
+
+void
+hidkbd_input(struct hidkbd *kbd, uint8_t *data, u_int len)
+{
+       struct hidkbd_data *ud = &kbd->sc_ndata;
+       int i;
+
+#ifdef HIDKBD_DEBUG
+       if (hidkbddebug > 5) {
+               printf("hidkbd_input: data");
+               for (i = 0; i < len; i++)
+                       printf(" 0x%02x", data[i]);
+               printf("\n");
+       }
+#endif
+
+       /* extract key modifiers */
+       ud->modifiers = 0;
+       for (i = 0; i < kbd->sc_nmod; i++)
+               if (hid_get_data(data, &kbd->sc_modloc[i]))
+                       ud->modifiers |= kbd->sc_mods[i].mask;
+
+       /* extract keycodes */
+       memcpy(ud->keycode, data + kbd->sc_keycodeloc.pos / 8,
+           kbd->sc_nkeycode);
+
+       if (kbd->sc_debounce && !kbd->sc_polling) {
+               /*
+                * Some keyboards have a peculiar quirk.  They sometimes
+                * generate a key up followed by a key down for the same
+                * key after about 10 ms.
+                * We avoid this bug by holding off decoding for 20 ms.
+                */
+               kbd->sc_data = *ud;
+               timeout_add_msec(&kbd->sc_delay, 20);
+#ifdef DDB
+       } else if (kbd->sc_console_keyboard && !kbd->sc_polling) {
+               /*
+                * For the console keyboard we can't deliver CTL-ALT-ESC
+                * from the interrupt routine.  Doing so would start
+                * polling from inside the interrupt routine and that
+                * loses bigtime.
+                */
+               /* if (!timeout_pending(&kbd->sc_delay)) */ {
+                       kbd->sc_data = *ud;
+                       timeout_add(&kbd->sc_delay, 1);
+               }
+#endif
+       } else {
+               hidkbd_decode(kbd, ud);
+       }
+}
+
+void
+hidkbd_delayed_decode(void *addr)
+{
+       struct hidkbd *kbd = addr;
+
+       hidkbd_decode(kbd, &kbd->sc_data);
+}
+
+void
+hidkbd_decode(struct hidkbd *kbd, struct hidkbd_data *ud)
+{
+       uint32_t mod, omod;
+       u_int16_t ibuf[MAXKEYS];        /* chars events */
+       int s;
+       int nkeys, i, j;
+       int key;
+#define ADDKEY(c) ibuf[nkeys++] = (c)
+
+#ifdef HIDKBD_DEBUG
+       /*
+        * Keep a trace of the last events.  Using printf changes the
+        * timing, so this can be useful sometimes.
+        */
+       if (hidkbdtrace) {
+               struct hidkbdtraceinfo *p = &hidkbdtracedata[hidkbdtraceindex];
+               p->unit = kbd->sc_hdev.sc_dev.dv_unit;
+               microtime(&p->tv);
+               p->ud = *ud;
+               if (++hidkbdtraceindex >= HIDKBDTRACESIZE)
+                       hidkbdtraceindex = 0;
+       }
+       if (hidkbddebug > 5) {
+               struct timeval tv;
+               microtime(&tv);
+               DPRINTF((" at %lu.%06lu  mod=0x%02x key0=0x%02x key1=0x%02x "
+                        "key2=0x%02x key3=0x%02x\n",
+                        tv.tv_sec, tv.tv_usec,
+                        ud->modifiers, ud->keycode[0], ud->keycode[1],
+                        ud->keycode[2], ud->keycode[3]));
+       }
+#endif
+
+       if (ud->keycode[0] == KEY_ERROR) {
+               DPRINTF(("hidkbd_input: KEY_ERROR\n"));
+               return;         /* ignore  */
+       }
+       nkeys = 0;
+       mod = ud->modifiers;
+       omod = kbd->sc_odata.modifiers;
+       if (mod != omod)
+               for (i = 0; i < kbd->sc_nmod; i++)
+                       if (( mod & kbd->sc_mods[i].mask) !=
+                           (omod & kbd->sc_mods[i].mask))
+                               ADDKEY(kbd->sc_mods[i].key |
+                                      (mod & kbd->sc_mods[i].mask
+                                         ? PRESS : RELEASE));
+       if (memcmp(ud->keycode, kbd->sc_odata.keycode, kbd->sc_nkeycode) != 0) {
+               /* Check for released keys. */
+               for (i = 0; i < kbd->sc_nkeycode; i++) {
+                       key = kbd->sc_odata.keycode[i];
+                       if (key == 0)
+                               continue;
+                       for (j = 0; j < kbd->sc_nkeycode; j++)
+                               if (key == ud->keycode[j])
+                                       goto rfound;
+                       DPRINTFN(3,("hidkbd_decode: relse key=0x%02x\n", key));
+                       ADDKEY(key | RELEASE);
+               rfound:
+                       ;
+               }
+
+               /* Check for pressed keys. */
+               for (i = 0; i < kbd->sc_nkeycode; i++) {
+                       key = ud->keycode[i];
+                       if (key == 0)
+                               continue;
+                       for (j = 0; j < kbd->sc_nkeycode; j++)
+                               if (key == kbd->sc_odata.keycode[j])
+                                       goto pfound;
+                       DPRINTFN(2,("hidkbd_decode: press key=0x%02x\n", key));
+                       ADDKEY(key | PRESS);
+               pfound:
+                       ;
+               }
+       }
+       kbd->sc_odata = *ud;
+
+       if (nkeys == 0)
+               return;
+
+       if (kbd->sc_polling) {
+               DPRINTFN(1,("hidkbd_decode: pollchar = 0x%03x\n", ibuf[0]));
+               memcpy(kbd->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
+               kbd->sc_npollchar = nkeys;
+               return;
+       }
+
+       if (kbd->sc_wskbddev == NULL)
+               return;
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+       if (kbd->sc_rawkbd) {
+               u_char cbuf[MAXKEYS * 2];
+               int c;
+               int npress;
+
+               for (npress = i = j = 0; i < nkeys; i++) {
+                       key = ibuf[i];
+                       c = hidkbd_trtab[key & CODEMASK];
+                       if (c == NN)
+                               continue;
+                       if (c & 0x80)
+                               cbuf[j++] = 0xe0;
+                       cbuf[j] = c & 0x7f;
+                       if (key & RELEASE)
+                               cbuf[j] |= 0x80;
+                       else {
+                               /* remember pressed keys for autorepeat */
+                               if (c & 0x80)
+                                       kbd->sc_rep[npress++] = 0xe0;
+                               kbd->sc_rep[npress++] = c & 0x7f;
+                       }
+                       DPRINTFN(1,("hidkbd_decode: raw = %s0x%02x\n",
+                                   c & 0x80 ? "0xe0 " : "",
+                                   cbuf[j]));
+                       j++;
+               }
+               s = spltty();
+               wskbd_rawinput(kbd->sc_wskbddev, cbuf, j);
+               if (npress != 0) {
+                       kbd->sc_nrep = npress;
+                       timeout_add_msec(&kbd->sc_rawrepeat_ch, REP_DELAY1);
+               } else
+                       timeout_del(&kbd->sc_rawrepeat_ch);
+
+               /*
+                * Pass audio keys to wskbd_input anyway.
+                */
+               for (i = 0; i < nkeys; i++) {
+                       key = ibuf[i];
+                       switch (key & CODEMASK) {
+                       case 127:
+                       case 128:
+                       case 129:
+                               wskbd_input(kbd->sc_wskbddev,
+                                   key & RELEASE ?  WSCONS_EVENT_KEY_UP :
+                                     WSCONS_EVENT_KEY_DOWN, key & CODEMASK);
+                               break;
+                       }
+               }
+               splx(s);
+
+               return;
+       }
+#endif
+
+       s = spltty();
+       for (i = 0; i < nkeys; i++) {
+               key = ibuf[i];
+               wskbd_input(kbd->sc_wskbddev,
+                   key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
+                   key&CODEMASK);
+       }
+       splx(s);
+#undef ADDKEY
+}
+
+int
+hidkbd_enable(struct hidkbd *kbd, int on)
+{
+       if (kbd->sc_enabled == on)
+               return EBUSY;
+
+       kbd->sc_enabled = on;
+       return 0;
+}
+
+int
+hidkbd_set_leds(struct hidkbd *kbd, int leds, uint8_t *report)
+{
+       if (kbd->sc_leds == leds)
+               return 0;
+
+       kbd->sc_leds = leds;
+
+       /*
+        * This is not totally correct, since we did not check the
+        * report size from the descriptor but for keyboards it should
+        * just be a single byte with the relevant bits set.
+        */
+       *report = 0;
+       if ((leds & WSKBD_LED_SCROLL) && kbd->sc_scroloc.size == 1)
+               *report |= 1 << kbd->sc_scroloc.pos;
+       if ((leds & WSKBD_LED_NUM) && kbd->sc_numloc.size == 1)
+               *report |= 1 << kbd->sc_numloc.pos;
+       if ((leds & WSKBD_LED_CAPS) && kbd->sc_capsloc.size == 1)
+               *report |= 1 << kbd->sc_capsloc.pos;
+
+       return 1;
+}
+
+int
+hidkbd_ioctl(struct hidkbd *kbd, u_long cmd, caddr_t data, int flag,
+   struct proc *p)
+{
+       switch (cmd) {
+       case WSKBDIO_GETLEDS:
+               *(int *)data = kbd->sc_leds;
+               return (0);
+       case WSKBDIO_COMPLEXBELL:
+#define d ((struct wskbd_bell_data *)data)
+               hidkbd_bell(d->pitch, d->period, d->volume, 0);
+#undef d
+               return (0);
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+       case WSKBDIO_SETMODE:
+               DPRINTF(("hidkbd_ioctl: set raw = %d\n", *(int *)data));
+               kbd->sc_rawkbd = *(int *)data == WSKBD_RAW;
+               timeout_del(&kbd->sc_rawrepeat_ch);
+               return (0);
+#endif
+       }
+       return (-1);
+}
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+void
+hidkbd_rawrepeat(void *v)
+{
+       struct hidkbd *kbd = v;
+       int s;
+
+       s = spltty();
+       wskbd_rawinput(kbd->sc_wskbddev, kbd->sc_rep, kbd->sc_nrep);
+       splx(s);
+       timeout_add_msec(&kbd->sc_rawrepeat_ch, REP_DELAYN);
+}
+#endif
+
+void
+hidkbd_cngetc(struct hidkbd *kbd, u_int *type, int *data)
+{
+       int c;
+
+       c = kbd->sc_pollchars[0];
+       kbd->sc_npollchar--;
+       memcpy(kbd->sc_pollchars, kbd->sc_pollchars+1,
+              kbd->sc_npollchar * sizeof(u_int16_t));
+       *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
+       *data = c & CODEMASK;
+}
+
+void
+hidkbd_bell(u_int pitch, u_int period, u_int volume, int poll)
+{
+       if (hidkbd_bell_fn != NULL)
+               (*hidkbd_bell_fn)(hidkbd_bell_fn_arg, pitch, period,
+                   volume, poll);
+}
+
+void
+hidkbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
+{
+       if (hidkbd_bell_fn == NULL) {
+               hidkbd_bell_fn = fn;
+               hidkbd_bell_fn_arg = arg;
+       }
+}
+
+const char *
+hidkbd_parse_desc(struct hidkbd *kbd, int id, void *desc, int dlen)
+{
+       struct hid_data *d;
+       struct hid_item h;
+       int imod;
+
+       imod = 0;
+       kbd->sc_nkeycode = 0;
+       d = hid_start_parse(desc, dlen, hid_input);
+       while (hid_get_item(d, &h)) {
+               if (h.kind != hid_input || (h.flags & HIO_CONST) ||
+                   HID_GET_USAGE_PAGE(h.usage) != HUP_KEYBOARD ||
+                   h.report_ID != id)
+                       continue;
+
+               DPRINTF(("hidkbd: imod=%d usage=0x%x flags=0x%x pos=%d size=%d "
+                        "cnt=%d\n", imod,
+                        h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
+               if (h.flags & HIO_VARIABLE) {
+                       if (h.loc.size != 1)
+                               return ("bad modifier size");
+                       /* Single item */
+                       if (imod < MAXMOD) {
+                               kbd->sc_modloc[imod] = h.loc;
+                               kbd->sc_mods[imod].mask = 1 << imod;
+                               kbd->sc_mods[imod].key = HID_GET_USAGE(h.usage);
+                               imod++;
+                       } else
+                               return ("too many modifier keys");
+               } else {
+                       /* Array */
+                       if (h.loc.size != 8)
+                               return ("key code size != 8");
+                       if (h.loc.count > MAXKEYCODE)
+                               return ("too many key codes");
+                       if (h.loc.pos % 8 != 0)
+                               return ("key codes not on byte boundary");
+                       if (kbd->sc_nkeycode != 0)
+                               return ("multiple key code arrays\n");
+                       kbd->sc_keycodeloc = h.loc;
+                       kbd->sc_nkeycode = h.loc.count;
+               }
+       }
+       kbd->sc_nmod = imod;
+       hid_end_parse(d);
+
+       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
+           id, hid_output, &kbd->sc_numloc, NULL);
+       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
+           id, hid_output, &kbd->sc_capsloc, NULL);
+       hid_locate(desc, dlen, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
+           id, hid_output, &kbd->sc_scroloc, NULL);
+
+       return (NULL);
+}
diff --git a/sys/dev/usb/hidkbdsc.h b/sys/dev/usb/hidkbdsc.h
new file mode 100644 (file)
index 0000000..484bc25
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $OpenBSD: hidkbdsc.h,v 1.1 2010/07/31 16:04:50 miod Exp $       */
+/*      $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $        */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define MAXKEYCODE 6
+#define MAXMOD 8               /* max 32 */
+
+#define MAXKEYS (MAXMOD+2*MAXKEYCODE)
+
+struct hidkbd_data {
+       u_int32_t       modifiers;
+       u_int8_t        keycode[MAXKEYCODE];
+};
+
+struct hidkbd {
+       /* stored data */
+       struct hidkbd_data sc_ndata;
+       struct hidkbd_data sc_odata;
+
+       /* input reports */
+       struct hid_location sc_modloc[MAXMOD];
+       u_int sc_nmod;
+       struct {
+               u_int32_t mask;
+               u_int8_t key;
+       } sc_mods[MAXMOD];
+
+       struct hid_location sc_keycodeloc;
+       u_int sc_nkeycode;
+
+       /* output reports */
+       struct hid_location sc_numloc;
+       struct hid_location sc_capsloc;
+       struct hid_location sc_scroloc;
+       int sc_leds;
+
+       /* state information */
+       struct device *sc_device;
+       struct device *sc_wskbddev;
+       char sc_enabled;
+
+       char sc_console_keyboard;       /* we are the console keyboard */
+
+       char sc_debounce;               /* for quirk handling */
+       struct timeout sc_delay;        /* for quirk handling */
+       struct hidkbd_data sc_data;     /* for quirk handling */
+
+       /* key repeat logic */
+       struct timeout sc_rawrepeat_ch;
+#if defined(WSDISPLAY_COMPAT_RAWKBD)
+#define REP_DELAY1 400
+#define REP_DELAYN 100
+       int sc_rawkbd;
+       int sc_nrep;
+       char sc_rep[MAXKEYS];
+#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
+
+       int sc_polling;
+       int sc_npollchar;
+       u_int16_t sc_pollchars[MAXKEYS];
+};
+
+int    hidkbd_attach(struct device *, struct hidkbd *, int, uint32_t,
+           int, void *, int);
+void   hidkbd_attach_wskbd(struct hidkbd *, kbd_t,
+           const struct wskbd_accessops *);
+void   hidkbd_bell(u_int, u_int, u_int, int);
+void   hidkbd_cngetc(struct hidkbd *, u_int *, int *);
+int    hidkbd_detach(struct hidkbd *, int);
+int    hidkbd_enable(struct hidkbd *, int);
+void   hidkbd_input(struct hidkbd *, uint8_t *, u_int);
+int    hidkbd_ioctl(struct hidkbd *, u_long, caddr_t, int, struct proc *);
+int    hidkbd_set_leds(struct hidkbd *, int, uint8_t *);
+
+extern int hidkbd_is_console;
diff --git a/sys/dev/usb/hidkbdvar.h b/sys/dev/usb/hidkbdvar.h
new file mode 100644 (file)
index 0000000..44b3d64
--- /dev/null
@@ -0,0 +1,34 @@
+/*     $OpenBSD: hidkbdvar.h,v 1.1 2010/07/31 16:04:50 miod Exp $      */
+/*      $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $        */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void   hidkbd_hookup_bell(void (*)(void *, u_int, u_int, u_int, int), void *);
diff --git a/sys/dev/usb/hidms.c b/sys/dev/usb/hidms.c
new file mode 100644 (file)
index 0000000..f076c50
--- /dev/null
@@ -0,0 +1,348 @@
+/*     $OpenBSD: hidms.c,v 1.1 2010/07/31 16:04:50 miod Exp $ */
+/*     $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $        */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
+
+#include <dev/usb/usb_quirks.h>
+#include <dev/usb/hid.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsmousevar.h>
+
+#include <dev/usb/hidmsvar.h>
+
+#ifdef HIDMS_DEBUG
+#define DPRINTF(x)     do { if (hidmsdebug) printf x; } while (0)
+#define DPRINTFN(n,x)  do { if (hidmsdebug>(n)) printf x; } while (0)
+int    hidmsdebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+#define HIDMS_BUT(i)   ((i) == 1 || (i) == 2 ? 3 - (i) : i)
+
+#define NOTMOUSE(f)    (((f) & (HIO_CONST | HIO_RELATIVE)) != HIO_RELATIVE)
+
+int
+hidms_setup(struct device *self, struct hidms *ms, uint32_t quirks,
+    int id, void *desc, int dlen)
+{
+       uint32_t flags;
+       int i, wheel, twheel;
+
+       ms->sc_device = self;
+
+       if (quirks & UQ_MS_REVZ)
+               ms->sc_flags |= HIDMS_REVZ;
+       if (quirks & UQ_SPUR_BUT_UP)
+               ms->sc_flags |= HIDMS_SPUR_BUT_UP;
+       if (quirks & UQ_MS_LEADING_BYTE)
+               ms->sc_flags |= HIDMS_LEADINGBYTE;
+
+       if (!hid_locate(desc, dlen, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), id,
+           hid_input, &ms->sc_loc_x, &flags)) {
+               printf("\n%s: mouse has no X report\n", self->dv_xname);
+               return ENXIO;
+       }
+       if (NOTMOUSE(flags)) {
+               printf("\n%s: X report 0x%04x not supported\n",
+                   self->dv_xname, flags);
+               return ENXIO;
+       }
+
+       if (!hid_locate(desc, dlen, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y), id,
+           hid_input, &ms->sc_loc_y, &flags)) {
+               printf("\n%s: mouse has no Y report\n", self->dv_xname);
+               return ENXIO;
+       }
+       if (NOTMOUSE(flags)) {
+               printf("\n%s: Y report 0x%04x not supported\n",
+                   self->dv_xname, flags);
+               return ENXIO;
+       }
+
+       /*
+        * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
+        * in that order.
+        */
+
+       wheel = hid_locate(desc, dlen,
+           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), id,
+           hid_input, &ms->sc_loc_z, &flags);
+       if (wheel == 0)
+               twheel = hid_locate(desc, dlen,
+                   HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), id,
+                   hid_input, &ms->sc_loc_z, &flags);
+       else
+               twheel = 0;
+
+       if (wheel || twheel) {
+               if (NOTMOUSE(flags)) {
+                       DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
+                           self->dv_xname, flags));
+                       ms->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
+               } else {
+                       ms->sc_flags |= HIDMS_Z;
+                       /* Wheels need the Z axis reversed. */
+                       ms->sc_flags ^= HIDMS_REVZ;
+               }
+               /*
+                * We might have both a wheel and Z direction; in this case,
+                * report the Z direction on the W axis.
+               */
+               if (hid_locate(desc, dlen,
+                   HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), id,
+                   hid_input, &ms->sc_loc_w, &flags)) {
+                       if (NOTMOUSE(flags)) {
+                               DPRINTF(("\n%s: Z report 0x%04x not supported\n",
+                                   self->dv_xname, flags));
+                               /* Bad Z coord, ignore it */
+                               ms->sc_loc_w.size = 0;
+                       }
+                       else
+                               ms->sc_flags |= HIDMS_W;
+               }
+       } else if (hid_locate(desc, dlen,
+           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), id,
+           hid_input, &ms->sc_loc_z, &flags)) {
+               if (NOTMOUSE(flags)) {
+                       DPRINTF(("\n%s: Z report 0x%04x not supported\n",
+                           self->dv_xname, flags));
+                       ms->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
+               } else {
+                       ms->sc_flags |= HIDMS_Z;
+               }
+       }
+
+       /*
+        * The Microsoft Wireless Intellimouse 2.0 reports its wheel
+        * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
+        * us to know that the byte after the wheel is the tilt axis.
+        * There are no other HID axis descriptors other than X, Y and
+        * TWHEEL, so we report TWHEEL on the W axis.
+        */
+       if (twheel) {
+               ms->sc_loc_w = ms->sc_loc_z;
+               ms->sc_loc_w.pos = ms->sc_loc_w.pos + 8;
+               ms->sc_flags |= HIDMS_W | HIDMS_LEADINGBYTE;
+               /* Wheels need their axis reversed. */
+               ms->sc_flags ^= HIDMS_REVW;
+       }
+
+       /* figure out the number of buttons */
+       for (i = 1; i <= MAX_BUTTONS; i++)
+               if (!hid_locate(desc, dlen, HID_USAGE2(HUP_BUTTON, i), id,
+                   hid_input, &ms->sc_loc_btn[i - 1], 0))
+                       break;
+       ms->sc_num_buttons = i - 1;
+
+       /*
+        * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
+        * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
+        * all of its other button positions are all off. It also reports that
+        * it has two addional buttons and a tilt wheel.
+        */
+       if (quirks & UQ_MS_BAD_CLASS) {
+               /* HIDMS_LEADINGBYTE cleared on purpose */
+               ms->sc_flags = HIDMS_Z | HIDMS_SPUR_BUT_UP;
+               ms->sc_num_buttons = 3;
+               /* XXX change sc_hdev isize to 5? */
+               /* 1st byte of descriptor report contains garbage */
+               ms->sc_loc_x.pos = 16;
+               ms->sc_loc_y.pos = 24;
+               ms->sc_loc_z.pos = 32;
+               ms->sc_loc_btn[0].pos = 8;
+               ms->sc_loc_btn[1].pos = 9;
+               ms->sc_loc_btn[2].pos = 10;
+       }
+
+       return 0;
+}
+
+void
+hidms_attach(struct hidms *ms, const struct wsmouse_accessops *ops)
+{
+       struct wsmousedev_attach_args a;
+#ifdef HIDMS_DEBUG
+       int i;
+#endif
+
+       printf(": %d button%s",
+           ms->sc_num_buttons, ms->sc_num_buttons <= 1 ? "" : "s");
+       switch (ms->sc_flags & (HIDMS_Z | HIDMS_W)) {
+       case HIDMS_Z:
+               printf(", Z dir");
+               break;
+       case HIDMS_W:
+               printf(", W dir");
+               break;
+       case HIDMS_Z | HIDMS_W:
+               printf(", Z and W dir");
+               break;
+       }
+       printf("\n");
+
+#ifdef HIDMS_DEBUG
+       DPRINTF(("hidms_attach: sc=%p\n", sc));
+       DPRINTF(("hidms_attach: X\t%d/%d\n",
+            ms->sc_loc_x.pos, ms->sc_loc_x.size));
+       DPRINTF(("hidms_attach: Y\t%d/%d\n",
+           ms->sc_loc_y.pos, ms->sc_loc_y.size));
+       if (ms->sc_flags & HIDMS_Z)
+               DPRINTF(("hidms_attach: Z\t%d/%d\n",
+                   ms->sc_loc_z.pos, ms->sc_loc_z.size));
+       if (ms->sc_flags & HIDMS_W)
+               DPRINTF(("hidms_attach: W\t%d/%d\n",
+                   ms->sc_loc_w.pos, ms->sc_loc_w.size));
+       for (i = 1; i <= ms->sc_num_buttons; i++) {
+               DPRINTF(("hidms_attach: B%d\t%d/%d\n",
+                   i, ms->sc_loc_btn[i - 1].pos, ms->sc_loc_btn[i - 1].size));
+       }
+#endif
+
+       a.accessops = ops;
+       a.accesscookie = ms->sc_device;
+       ms->sc_wsmousedev = config_found(ms->sc_device, &a, wsmousedevprint);
+}
+
+int
+hidms_detach(struct hidms *ms, int flags)
+{
+       int rv = 0;
+
+       DPRINTF(("hidms_detach: sc=%p flags=%d\n", sc, flags));
+
+       /* No need to do reference counting of hidms, wsmouse has all the goo */
+       if (ms->sc_wsmousedev != NULL)
+               rv = config_detach(ms->sc_wsmousedev, flags);
+
+       return (rv);
+}
+
+void
+hidms_input(struct hidms *ms, uint8_t *data, u_int len)
+{
+       int dx, dy, dz, dw;
+       u_int32_t buttons = 0;
+       int i, s;
+
+       DPRINTFN(5,("hidms_input: len=%d\n", len));
+
+       /*
+        * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
+        * byte of data compared to most USB mice.  This byte frequently
+        * switches from 0x01 (usual state) to 0x02.  It may be used to
+        * report non-standard events (such as battery life).  However,
+        * at the same time, it generates a left click event on the
+        * button byte, where there shouldn't be any.  We simply discard
+        * the packet in this case.
+        *
+        * This problem affects the MS Wireless Notebook Optical Mouse, too.
+        * However, the leading byte for this mouse is normally 0x11, and
+        * the phantom mouse click occurs when it's 0x14.
+        */
+       if (ms->sc_flags & HIDMS_LEADINGBYTE) {
+               if (*data++ == 0x02)
+                       return;
+               /* len--; */
+       } else if (ms->sc_flags & HIDMS_SPUR_BUT_UP) {
+               if (*data == 0x14 || *data == 0x15)
+                       return;
+       }
+
+       dx =  hid_get_data(data, &ms->sc_loc_x);
+       dy = -hid_get_data(data, &ms->sc_loc_y);
+       dz =  hid_get_data(data, &ms->sc_loc_z);
+       dw =  hid_get_data(data, &ms->sc_loc_w);
+
+       if (ms->sc_flags & HIDMS_REVZ)
+               dz = -dz;
+       if (ms->sc_flags & HIDMS_REVW)
+               dw = -dw;
+
+       for (i = 0; i < ms->sc_num_buttons; i++)
+               if (hid_get_data(data, &ms->sc_loc_btn[i]))
+                       buttons |= (1 << HIDMS_BUT(i));
+
+       if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
+           buttons != ms->sc_buttons) {
+               DPRINTFN(10, ("hidms_input: x:%d y:%d z:%d w:%d buttons:0x%x\n",
+                       dx, dy, dz, dw, buttons));
+               ms->sc_buttons = buttons;
+               if (ms->sc_wsmousedev != NULL) {
+                       s = spltty();
+                       wsmouse_input(ms->sc_wsmousedev, buttons,
+                           dx, dy, dz, dw, WSMOUSE_INPUT_DELTA);
+                       splx(s);
+               }
+       }
+}
+
+int
+hidms_enable(struct hidms *ms)
+{
+       if (ms->sc_enabled)
+               return EBUSY;
+
+       ms->sc_enabled = 1;
+       ms->sc_buttons = 0;
+       return 0;
+}
+
+int
+hidms_ioctl(struct hidms *ms, u_long cmd, caddr_t data, int flag,
+    struct proc *p)
+{
+       switch (cmd) {
+       default:
+               return -1;
+       }
+}
+
+void
+hidms_disable(struct hidms *ms)
+{
+       ms->sc_enabled = 0;
+}
diff --git a/sys/dev/usb/hidmsvar.h b/sys/dev/usb/hidmsvar.h
new file mode 100644 (file)
index 0000000..bf032f2
--- /dev/null
@@ -0,0 +1,67 @@
+/*     $OpenBSD: hidmsvar.h,v 1.1 2010/07/31 16:04:50 miod Exp $ */
+/*     $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $        */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define MAX_BUTTONS    31      /* must not exceed size of sc_buttons */
+
+struct hidms {
+       int             sc_enabled;
+       int             sc_flags;       /* device configuration */
+#define HIDMS_SPUR_BUT_UP      0x01    /* spurious button up events */
+#define HIDMS_Z                        0x02    /* Z direction available */
+#define HIDMS_REVZ             0x04    /* Z-axis is reversed */
+#define HIDMS_W                        0x08    /* W direction available */
+#define HIDMS_REVW             0x10    /* W-axis is reversed */
+#define HIDMS_LEADINGBYTE      0x20    /* Unknown leading byte */
+
+       int             sc_num_buttons;
+       u_int32_t       sc_buttons;     /* mouse button status */
+
+       struct device   *sc_device;
+       struct device   *sc_wsmousedev;
+
+       /* locators */
+       struct hid_location sc_loc_x;
+       struct hid_location sc_loc_y;
+       struct hid_location sc_loc_z;
+       struct hid_location sc_loc_w;
+       struct hid_location sc_loc_btn[MAX_BUTTONS];
+};
+
+void   hidms_attach(struct hidms *, const struct wsmouse_accessops *);
+int    hidms_detach(struct hidms *, int);
+void   hidms_disable(struct hidms *);
+int    hidms_enable(struct hidms *);
+void   hidms_input(struct hidms *, uint8_t *, u_int);
+int    hidms_ioctl(struct hidms *, u_long, caddr_t, int, struct proc *);
+int    hidms_setup(struct device *, struct hidms *, uint32_t, int, void *,
+           int);
index 8fa1e46..6f63447 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ukbd.c,v 1.51 2010/02/22 17:24:20 miod Exp $  */
+/*     $OpenBSD: ukbd.c,v 1.52 2010/07/31 16:04:50 miod Exp $  */
 /*      $NetBSD: ukbd.c,v 1.85 2003/03/11 16:44:00 augustss Exp $        */
 
 /*
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/file.h>
-#include <sys/selinfo.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/poll.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbhid.h>
@@ -64,6 +58,9 @@
 #include <dev/wscons/wsksymdef.h>
 #include <dev/wscons/wsksymvar.h>
 
+#include <dev/usb/hidkbdsc.h>
+#include <dev/usb/hidkbdvar.h>
+
 #ifdef UKBD_DEBUG
 #define DPRINTF(x)     do { if (ukbddebug) printf x; } while (0)
 #define DPRINTFN(n,x)  do { if (ukbddebug>(n)) printf x; } while (0)
@@ -73,62 +70,6 @@ int  ukbddebug = 0;
 #define DPRINTFN(n,x)
 #endif
 
-#define MAXKEYCODE 6
-#define MAXMOD 8               /* max 32 */
-
-struct ukbd_data {
-       u_int32_t       modifiers;
-       u_int8_t        keycode[MAXKEYCODE];
-};
-
-#define PRESS    0x000
-#define RELEASE  0x100
-#define CODEMASK 0x0ff
-
-#if defined(WSDISPLAY_COMPAT_RAWKBD)
-#define NN 0                   /* no translation */
-/*
- * Translate USB keycodes to US keyboard XT scancodes.
- * Scancodes >= 0x80 represent EXTENDED keycodes.
- *
- * See http://www.microsoft.com/whdc/device/input/Scancode.mspx
- */
-const u_int8_t ukbd_trtab[256] = {
-      NN,   NN,   NN,   NN, 0x1e, 0x30, 0x2e, 0x20, /* 00 - 07 */
-    0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, /* 08 - 0f */
-    0x32, 0x31, 0x18, 0x19, 0x10, 0x13, 0x1f, 0x14, /* 10 - 17 */
-    0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x02, 0x03, /* 18 - 1f */
-    0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, /* 20 - 27 */
-    0x1c, 0x01, 0x0e, 0x0f, 0x39, 0x0c, 0x0d, 0x1a, /* 28 - 2f */
-    0x1b, 0x2b, 0x2b, 0x27, 0x28, 0x29, 0x33, 0x34, /* 30 - 37 */
-    0x35, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, /* 38 - 3f */
-    0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0xaa, 0x46, /* 40 - 47 */
-    0x7f, 0xd2, 0xc7, 0xc9, 0xd3, 0xcf, 0xd1, 0xcd, /* 48 - 4f */
-    0xcb, 0xd0, 0xc8, 0x45, 0xb5, 0x37, 0x4a, 0x4e, /* 50 - 57 */
-    0x9c, 0x4f, 0x50, 0x51, 0x4b, 0x4c, 0x4d, 0x47, /* 58 - 5f */
-    0x48, 0x49, 0x52, 0x53, 0x56, 0xdd, 0x84, 0x59, /* 60 - 67 */
-    0x5d, 0x5e, 0x5f,   NN,   NN,   NN,   NN,   NN, /* 68 - 6f */
-      NN,   NN,   NN,   NN, 0x97,   NN, 0x93, 0x95, /* 70 - 77 */
-    0x91, 0x92, 0x94, 0x9a, 0x96, 0x98, 0x99, 0xa0, /* 78 - 7f */
-    0xb0, 0xae,   NN,   NN,   NN, 0x7e,   NN, 0x73, /* 80 - 87 */
-    0x70, 0x7d, 0x79, 0x7b, 0x5c,   NN,   NN,   NN, /* 88 - 8f */
-      NN,   NN, 0x78, 0x77, 0x76,   NN,   NN,   NN, /* 90 - 97 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* 98 - 9f */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a0 - a7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* a8 - af */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b0 - b7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* b8 - bf */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c0 - c7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* c8 - cf */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d0 - d7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* d8 - df */
-    0x1d, 0x2a, 0x38, 0xdb, 0x9d, 0x36, 0xb8, 0xdc, /* e0 - e7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* e8 - ef */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f0 - f7 */
-      NN,   NN,   NN,   NN,   NN,   NN,   NN,   NN, /* f8 - ff */
-};
-#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
-
 const kbd_t ukbd_countrylayout[1 + HCC_MAX] = {
        (kbd_t)-1,
        (kbd_t)-1,      /* arabic */
@@ -168,90 +109,13 @@ const kbd_t ukbd_countrylayout[1 + HCC_MAX] = {
        (kbd_t)-1       /* turkish F */
 };
 
-#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 {
-               u_int32_t mask;
-               u_int8_t key;
-       } sc_mods[MAXMOD];
-
-       struct hid_location sc_keycodeloc;
-       u_int sc_nkeycode;
-
-       char sc_enabled;
-
-       int sc_console_keyboard;        /* we are the console keyboard */
-
-       char sc_debounce;               /* for quirk handling */
-       struct timeout sc_delay;        /* for quirk handling */
-       struct ukbd_data sc_data;       /* for quirk handling */
-
-       struct hid_location sc_numloc;
-       struct hid_location sc_capsloc;
-       struct hid_location sc_scroloc;
-       int sc_leds;
-
-       struct timeout sc_rawrepeat_ch;
-
-       struct device *sc_wskbddev;
-#if defined(WSDISPLAY_COMPAT_RAWKBD)
-#define REP_DELAY1 400
-#define REP_DELAYN 100
-       int sc_rawkbd;
-       int sc_nrep;
-       char sc_rep[MAXKEYS];
-#endif /* defined(WSDISPLAY_COMPAT_RAWKBD) */
-
-       int sc_spl;
-       int sc_polling;
-       int sc_npollchar;
-       u_int16_t sc_pollchars[MAXKEYS];
-
-       u_char sc_dying;
+       struct uhidev   sc_hdev;
+       struct hidkbd   sc_kbd;
+       u_char          sc_dying;
+       int             sc_spl;
 };
 
-#ifdef UKBD_DEBUG
-#define UKBDTRACESIZE 64
-struct ukbdtraceinfo {
-       int unit;
-       struct timeval tv;
-       struct ukbd_data ud;
-};
-struct ukbdtraceinfo ukbdtracedata[UKBDTRACESIZE];
-int ukbdtraceindex = 0;
-int ukbdtrace = 0;
-void ukbdtracedump(void);
-void
-ukbdtracedump(void)
-{
-       int i;
-       for (i = 0; i < UKBDTRACESIZE; i++) {
-               struct ukbdtraceinfo *p =
-                   &ukbdtracedata[(i+ukbdtraceindex)%UKBDTRACESIZE];
-               printf("%lu.%06lu: mod=0x%02x key0=0x%02x key1=0x%02x "
-                      "key2=0x%02x key3=0x%02x\n",
-                      p->tv.tv_sec, p->tv.tv_usec,
-                      p->ud.modifiers, p->ud.keycode[0], p->ud.keycode[1],
-                      p->ud.keycode[2], p->ud.keycode[3]);
-       }
-}
-#endif
-
-#define        UKBDUNIT(dev)   (minor(dev))
-#define        UKBD_CHUNK      128     /* chunk size for read */
-#define        UKBD_BSIZE      1020    /* buffer size */
-
-int    ukbd_is_console;
-
 void   ukbd_cngetc(void *, u_int *, int *);
 void   ukbd_cnpollc(void *, int);
 void   ukbd_cnbell(void *, u_int, u_int, u_int);
@@ -262,24 +126,11 @@ const struct wskbd_consops ukbd_consops = {
        ukbd_cnbell,
 };
 
-const char *ukbd_parse_desc(struct ukbd_softc *sc);
-
-void   (*ukbd_bell_fn)(void *, u_int, u_int, u_int, int);
-void   *ukbd_bell_fn_arg;
-
-void   ukbd_bell(u_int, u_int, u_int, int);
-
 void   ukbd_intr(struct uhidev *addr, void *ibuf, u_int len);
-void   ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud);
-void   ukbd_delayed_decode(void *addr);
 
 int    ukbd_enable(void *, int);
 void   ukbd_set_leds(void *, int);
-
 int    ukbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-void   ukbd_rawrepeat(void *v);
-#endif
 
 const struct wskbd_accessops ukbd_accessops = {
        ukbd_enable,
@@ -287,12 +138,6 @@ const struct wskbd_accessops ukbd_accessops = {
        ukbd_ioctl,
 };
 
-extern const struct wscons_keydesc ukbd_keydesctab[];
-
-struct wskbd_mapdata ukbd_keymapdata = {
-       ukbd_keydesctab
-};
-
 int ukbd_match(struct device *, void *, void *); 
 void ukbd_attach(struct device *, struct device *, void *); 
 int ukbd_detach(struct device *, int); 
@@ -330,50 +175,30 @@ void
 ukbd_attach(struct device *parent, struct device *self, void *aux)
 {
        struct ukbd_softc *sc = (struct ukbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
        struct usb_attach_arg *uaa = aux;
        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
        usb_hid_descriptor_t *hid;
        u_int32_t qflags;
-       const char *parseerr;
+       int dlen;
+       void *desc;
        kbd_t layout = (kbd_t)-1;
-       struct wskbddev_attach_args a;
 
        sc->sc_hdev.sc_intr = ukbd_intr;
        sc->sc_hdev.sc_parent = uha->parent;
        sc->sc_hdev.sc_report_id = uha->reportid;
 
-       parseerr = ukbd_parse_desc(sc);
-       if (parseerr != NULL) {
-               printf("\n%s: attach failed, %s\n",
-                      sc->sc_hdev.sc_dev.dv_xname, parseerr);
-               return;
-       }
-
-       hid = usbd_get_hid_descriptor(uha->uaa->iface);
-
-#ifdef DIAGNOSTIC
-       printf(": %d modifier keys, %d key codes",
-           sc->sc_nmod, sc->sc_nkeycode);
-#endif
-
+       uhidev_get_report_desc(uha->parent, &desc, &dlen);
        qflags = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
-       sc->sc_debounce = (qflags & UQ_SPUR_BUT_UP) != 0;
-
-       /*
-        * Remember if we're the console keyboard.
-        *
-        * XXX This always picks the first keyboard on the
-        * first USB bus, but what else can we really do?
-        */
-       if ((sc->sc_console_keyboard = ukbd_is_console) != 0) {
-               /* Don't let any other keyboard have it. */
-               ukbd_is_console = 0;
-       }
+       if (hidkbd_attach(self, kbd, 1, qflags, uha->reportid, desc, dlen) != 0)
+               return;
 
        if (uha->uaa->vendor == USB_VENDOR_TOPRE &&
            uha->uaa->product == USB_PRODUCT_TOPRE_HHKB) {
                /* ignore country code on purpose */
        } else {
+               hid = usbd_get_hid_descriptor(uha->uaa->iface);
+
                if (hid->bCountryCode <= HCC_MAX)
                        layout = ukbd_countrylayout[hid->bCountryCode];
 #ifdef DIAGNOSTIC
@@ -388,65 +213,31 @@ ukbd_attach(struct device *parent, struct device *self, void *aux)
                layout = KB_US;
 #endif
        }
-       ukbd_keymapdata.layout = layout;
 
        printf("\n");
 
-       if (sc->sc_console_keyboard) {
+       if (kbd->sc_console_keyboard) {
+               extern struct wskbd_mapdata ukbd_keymapdata;
+
                DPRINTF(("ukbd_attach: console keyboard sc=%p\n", sc));
+               ukbd_keymapdata.layout = layout;
                wskbd_cnattach(&ukbd_consops, sc, &ukbd_keymapdata);
                ukbd_enable(sc, 1);
        }
 
-       a.console = sc->sc_console_keyboard;
-
-       a.keymap = &ukbd_keymapdata;
-
-       a.accessops = &ukbd_accessops;
-       a.accesscookie = sc;
-
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       timeout_set(&sc->sc_rawrepeat_ch, ukbd_rawrepeat, sc);
-#endif
-       timeout_set(&sc->sc_delay, ukbd_delayed_decode, sc);
-
        /* Flash the leds; no real purpose, just shows we're alive. */
        ukbd_set_leds(sc, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
        usbd_delay_ms(uha->parent->sc_udev, 400);
        ukbd_set_leds(sc, 0);
 
-       sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
-}
-
-int
-ukbd_enable(void *v, int on)
-{
-       struct ukbd_softc *sc = v;
-
-       if (on && sc->sc_dying)
-               return (EIO);
-
-       /* Should only be called to change state */
-       if (sc->sc_enabled == on) {
-               DPRINTF(("ukbd_enable: %s: bad call on=%d\n",
-                        sc->sc_hdev.sc_dev.dv_xname, on));
-               return (EBUSY);
-       }
-
-       DPRINTF(("ukbd_enable: sc=%p on=%d\n", sc, on));
-       sc->sc_enabled = on;
-       if (on) {
-               return (uhidev_open(&sc->sc_hdev));
-       } else {
-               uhidev_close(&sc->sc_hdev);
-               return (0);
-       }
+       hidkbd_attach_wskbd(kbd, layout, &ukbd_accessops);
 }
 
 int
 ukbd_activate(struct device *self, int act)
 {
        struct ukbd_softc *sc = (struct ukbd_softc *)self;
+       struct hidkbd *kbd = &sc->sc_kbd;
        int rv = 0;
 
        switch (act) {
@@ -454,8 +245,8 @@ ukbd_activate(struct device *self, int act)
                break;
 
        case DVACT_DEACTIVATE:
-               if (sc->sc_wskbddev != NULL)
-                       rv = config_deactivate(sc->sc_wskbddev);
+               if (kbd->sc_wskbddev != NULL)
+                       rv = config_deactivate(kbd->sc_wskbddev);
                sc->sc_dying = 1;
                break;
        }
@@ -466,38 +257,10 @@ int
 ukbd_detach(struct device *self, int flags)
 {
        struct ukbd_softc *sc = (struct ukbd_softc *)self;
-       int rv = 0;
+       struct hidkbd *kbd = &sc->sc_kbd;
+       int rv;
 
-       DPRINTF(("ukbd_detach: sc=%p flags=%d\n", sc, flags));
-
-       if (sc->sc_console_keyboard) {
-#if 0
-               /*
-                * XXX Should probably disconnect our consops,
-                * XXX and either notify some other keyboard that
-                * XXX it can now be the console, or if there aren't
-                * XXX any more USB keyboards, set ukbd_is_console
-                * XXX back to 1 so that the next USB keyboard attached
-                * XXX to the system will get it.
-                */
-               panic("ukbd_detach: console keyboard");
-#else
-               /*
-                * Disconnect our consops and set ukbd_is_console
-                * back to 1 so that the next USB keyboard attached
-                * to the system will get it.
-                * XXX Should notify some other keyboard that it can be
-                * XXX console, if there are any other keyboards.
-                */
-               printf("%s: was console keyboard\n",
-                      sc->sc_hdev.sc_dev.dv_xname);
-               wskbd_cndetach();
-               ukbd_is_console = 1;
-#endif
-       }
-       /* No need to do reference counting of ukbd, wskbd has all the goo. */
-       if (sc->sc_wskbddev != NULL)
-               rv = config_detach(sc->sc_wskbddev, flags);
+       rv = hidkbd_detach(kbd, flags);
 
        /* The console keyboard does not get a disable call, so check pipe. */
        if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
@@ -510,258 +273,53 @@ void
 ukbd_intr(struct uhidev *addr, void *ibuf, u_int len)
 {
        struct ukbd_softc *sc = (struct ukbd_softc *)addr;
-       struct ukbd_data *ud = &sc->sc_ndata;
-       int i;
-
-#ifdef UKBD_DEBUG
-       if (ukbddebug > 5) {
-               printf("ukbd_intr: data");
-               for (i = 0; i < len; i++)
-                       printf(" 0x%02x", ((u_char *)ibuf)[i]);
-               printf("\n");
-       }
-#endif
+       struct hidkbd *kbd = &sc->sc_kbd;
 
-       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);
-
-       if (sc->sc_debounce && !sc->sc_polling) {
-               /*
-                * Some keyboards have a peculiar quirk.  They sometimes
-                * generate a key up followed by a key down for the same
-                * key after about 10 ms.
-                * We avoid this bug by holding off decoding for 20 ms.
-                */
-               sc->sc_data = *ud;
-               timeout_add_msec(&sc->sc_delay, 20);
-#ifdef DDB
-       } else if (sc->sc_console_keyboard && !sc->sc_polling) {
-               /*
-                * For the console keyboard we can't deliver CTL-ALT-ESC
-                * from the interrupt routine.  Doing so would start
-                * polling from inside the interrupt routine and that
-                * loses bigtime.
-                */
-               /* if (!timeout_pending(&sc->sc_delay)) */ {
-                       sc->sc_data = *ud;
-                       timeout_add(&sc->sc_delay, 1);
-               }
-#endif
-       } else {
-               ukbd_decode(sc, ud);
-       }
+       if (kbd->sc_enabled != 0)
+               hidkbd_input(kbd, (uint8_t *)ibuf, len);
 }
 
-void
-ukbd_delayed_decode(void *addr)
-{
-       struct ukbd_softc *sc = addr;
-
-       ukbd_decode(sc, &sc->sc_data);
-}
-
-void
-ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
+int
+ukbd_enable(void *v, int on)
 {
-       int mod, omod;
-       u_int16_t ibuf[MAXKEYS];        /* chars events */
-       int s;
-       int nkeys, i, j;
-       int key;
-#define ADDKEY(c) ibuf[nkeys++] = (c)
-
-#ifdef UKBD_DEBUG
-       /*
-        * Keep a trace of the last events.  Using printf changes the
-        * timing, so this can be useful sometimes.
-        */
-       if (ukbdtrace) {
-               struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
-               p->unit = sc->sc_hdev.sc_dev.dv_unit;
-               microtime(&p->tv);
-               p->ud = *ud;
-               if (++ukbdtraceindex >= UKBDTRACESIZE)
-                       ukbdtraceindex = 0;
-       }
-       if (ukbddebug > 5) {
-               struct timeval tv;
-               microtime(&tv);
-               DPRINTF((" at %lu.%06lu  mod=0x%02x key0=0x%02x key1=0x%02x "
-                        "key2=0x%02x key3=0x%02x\n",
-                        tv.tv_sec, tv.tv_usec,
-                        ud->modifiers, ud->keycode[0], ud->keycode[1],
-                        ud->keycode[2], ud->keycode[3]));
-       }
-#endif
-
-       if (ud->keycode[0] == KEY_ERROR) {
-               DPRINTF(("ukbd_intr: KEY_ERROR\n"));
-               return;         /* ignore  */
-       }
-       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))
-                               ADDKEY(sc->sc_mods[i].key |
-                                      (mod & sc->sc_mods[i].mask
-                                         ? PRESS : RELEASE));
-       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));
-                       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));
-                       ADDKEY(key | PRESS);
-               pfound:
-                       ;
-               }
-       }
-       sc->sc_odata = *ud;
-
-       if (nkeys == 0)
-               return;
+       struct ukbd_softc *sc = v;
+       struct hidkbd *kbd = &sc->sc_kbd;
+       int rv;
 
-       if (sc->sc_polling) {
-               DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
-               memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
-               sc->sc_npollchar = nkeys;
-               return;
-       }
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       if (sc->sc_rawkbd) {
-               u_char cbuf[MAXKEYS * 2];
-               int c;
-               int npress;
-
-               for (npress = i = j = 0; i < nkeys; i++) {
-                       key = ibuf[i];
-                       c = ukbd_trtab[key & CODEMASK];
-                       if (c == NN)
-                               continue;
-                       if (c & 0x80)
-                               cbuf[j++] = 0xe0;
-                       cbuf[j] = c & 0x7f;
-                       if (key & RELEASE)
-                               cbuf[j] |= 0x80;
-                       else {
-                               /* remember pressed keys for autorepeat */
-                               if (c & 0x80)
-                                       sc->sc_rep[npress++] = 0xe0;
-                               sc->sc_rep[npress++] = c & 0x7f;
-                       }
-                       DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
-                                   c & 0x80 ? "0xe0 " : "",
-                                   cbuf[j]));
-                       j++;
-               }
-               s = spltty();
-               wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
-               if (npress != 0) {
-                       sc->sc_nrep = npress;
-                       timeout_add_msec(&sc->sc_rawrepeat_ch, REP_DELAY1);
-               } else
-                       timeout_del(&sc->sc_rawrepeat_ch);
-
-               /*
-                * Pass audio keys to wskbd_input anyway.
-                */
-               for (i = 0; i < nkeys; i++) {
-                       key = ibuf[i];
-                       switch (key & CODEMASK) {
-                       case 127:
-                       case 128:
-                       case 129:
-                               wskbd_input(sc->sc_wskbddev,
-                                   key & RELEASE ?  WSCONS_EVENT_KEY_UP :
-                                     WSCONS_EVENT_KEY_DOWN, key & CODEMASK);
-                               break;
-                       }
-               }
-               splx(s);
+       if (on && sc->sc_dying)
+               return EIO;
 
-               return;
-       }
-#endif
+       if ((rv = hidkbd_enable(kbd, on)) != 0)
+               return rv;
 
-       s = spltty();
-       for (i = 0; i < nkeys; i++) {
-               key = ibuf[i];
-               wskbd_input(sc->sc_wskbddev,
-                   key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
-                   key&CODEMASK);
+       if (on) {
+               return uhidev_open(&sc->sc_hdev);
+       } else {
+               uhidev_close(&sc->sc_hdev);
+               return 0;
        }
-       splx(s);
 }
 
 void
 ukbd_set_leds(void *v, int leds)
 {
        struct ukbd_softc *sc = v;
+       struct hidkbd *kbd = &sc->sc_kbd;
        u_int8_t res;
 
-       DPRINTF(("ukbd_set_leds: sc=%p leds=%d, sc_leds=%d\n",
-                sc, leds, sc->sc_leds));
-
        if (sc->sc_dying)
                return;
 
-       if (sc->sc_leds == leds)
-               return;
-       sc->sc_leds = leds;
-       res = 0;
-       /* XXX not really right */
-       if ((leds & WSKBD_LED_SCROLL) && sc->sc_scroloc.size == 1)
-               res |= 1 << sc->sc_scroloc.pos;
-       if ((leds & WSKBD_LED_NUM) && sc->sc_numloc.size == 1)
-               res |= 1 << sc->sc_numloc.pos;
-       if ((leds & WSKBD_LED_CAPS) && sc->sc_capsloc.size == 1)
-               res |= 1 << sc->sc_capsloc.pos;
-       uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT, &res, 1);
+       if (hidkbd_set_leds(kbd, leds, &res) != 0)
+               uhidev_set_report_async(&sc->sc_hdev, UHID_OUTPUT_REPORT,
+                   &res, 1);
 }
 
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-void
-ukbd_rawrepeat(void *v)
-{
-       struct ukbd_softc *sc = v;
-       int s;
-
-       s = spltty();
-       wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
-       splx(s);
-       timeout_add_msec(&sc->sc_rawrepeat_ch, REP_DELAYN);
-}
-#endif
-
 int
 ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
 {
        struct ukbd_softc *sc = v;
+       struct hidkbd *kbd = &sc->sc_kbd;
 
        switch (cmd) {
        case WSKBDIO_GTYPE:
@@ -770,39 +328,8 @@ ukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
        case WSKBDIO_SETLEDS:
                ukbd_set_leds(v, *(int *)data);
                return (0);
-       case WSKBDIO_GETLEDS:
-               *(int *)data = sc->sc_leds;
-               return (0);
-       case WSKBDIO_COMPLEXBELL:
-#define d ((struct wskbd_bell_data *)data)
-               ukbd_bell(d->pitch, d->period, d->volume, 0);
-#undef d
-               return (0);
-#ifdef WSDISPLAY_COMPAT_RAWKBD
-       case WSKBDIO_SETMODE:
-               DPRINTF(("ukbd_ioctl: set raw = %d\n", *(int *)data));
-               sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
-               timeout_del(&sc->sc_rawrepeat_ch);
-               return (0);
-#endif
-       }
-       return (-1);
-}
-
-void
-ukbd_bell(u_int pitch, u_int period, u_int volume, int poll)
-{
-       if (ukbd_bell_fn != NULL)
-               (*ukbd_bell_fn)(ukbd_bell_fn_arg, pitch, period,
-                   volume, poll);
-}
-
-void
-ukbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
-{
-       if (ukbd_bell_fn == NULL) {
-               ukbd_bell_fn = fn;
-               ukbd_bell_fn_arg = arg;
+       default:
+               return hidkbd_ioctl(kbd, cmd, data, flag, p);
        }
 }
 
@@ -811,20 +338,15 @@ void
 ukbd_cngetc(void *v, u_int *type, int *data)
 {
        struct ukbd_softc *sc = v;
-       int c;
+       struct hidkbd *kbd = &sc->sc_kbd;
 
        DPRINTFN(0,("ukbd_cngetc: enter\n"));
-       sc->sc_polling = 1;
-       while(sc->sc_npollchar <= 0)
+       kbd->sc_polling = 1;
+       while (kbd->sc_npollchar <= 0)
                usbd_dopoll(sc->sc_hdev.sc_parent->sc_iface);
-       sc->sc_polling = 0;
-       c = sc->sc_pollchars[0];
-       sc->sc_npollchar--;
-       memcpy(sc->sc_pollchars, sc->sc_pollchars+1,
-              sc->sc_npollchar * sizeof(u_int16_t));
-       *type = c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
-       *data = c & CODEMASK;
-       DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", c));
+       kbd->sc_polling = 0;
+       hidkbd_cngetc(kbd, type, data);
+       DPRINTFN(0,("ukbd_cngetc: return 0x%02x\n", *data));
 }
 
 void
@@ -846,7 +368,7 @@ ukbd_cnpollc(void *v, int on)
 void
 ukbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) 
 {
-       ukbd_bell(pitch, period, volume, 1);
+       hidkbd_bell(pitch, period, volume, 1);
 }      
 
 int
@@ -858,67 +380,6 @@ ukbd_cnattach(void)
         * XXX in order to work, so we can't do much for the console
         * XXX keyboard until autconfiguration has run its course.
         */
-       ukbd_is_console = 1;
+       hidkbd_is_console = 1;
        return (0);
 }
-
-const char *
-ukbd_parse_desc(struct ukbd_softc *sc)
-{
-       struct hid_data *d;
-       struct hid_item h;
-       int size;
-       void *desc;
-       int imod;
-
-       uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
-       imod = 0;
-       sc->sc_nkeycode = 0;
-       d = hid_start_parse(desc, size, hid_input);
-       while (hid_get_item(d, &h)) {
-               /*printf("ukbd: id=%d kind=%d usage=0x%x flags=0x%x pos=%d size=%d cnt=%d\n",
-                 h.report_ID, h.kind, h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count);*/
-               if (h.kind != hid_input || (h.flags & HIO_CONST) ||
-                   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,
-                        h.usage, h.flags, h.loc.pos, h.loc.size, h.loc.count));
-               if (h.flags & HIO_VARIABLE) {
-                       if (h.loc.size != 1)
-                               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++;
-                       } else
-                               return ("too many modifier keys");
-               } else {
-                       /* Array */
-                       if (h.loc.size != 8)
-                               return ("key code size != 8");
-                       if (h.loc.count > MAXKEYCODE)
-                               return ("too many key codes");
-                       if (h.loc.pos % 8 != 0)
-                               return ("key codes not on byte boundary");
-                       if (sc->sc_nkeycode != 0)
-                               return ("multiple key code arrays\n");
-                       sc->sc_keycodeloc = h.loc;
-                       sc->sc_nkeycode = h.loc.count;
-               }
-       }
-       sc->sc_nmod = imod;
-       hid_end_parse(d);
-
-       hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_NUM_LOCK),
-                  sc->sc_hdev.sc_report_id, hid_output, &sc->sc_numloc, NULL);
-       hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_CAPS_LOCK),
-                  sc->sc_hdev.sc_report_id, hid_output, &sc->sc_capsloc, NULL);
-       hid_locate(desc, size, HID_USAGE2(HUP_LEDS, HUD_LED_SCROLL_LOCK),
-                  sc->sc_hdev.sc_report_id, hid_output, &sc->sc_scroloc, NULL);
-
-       return (NULL);
-}
index e361347..7c2251f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ukbdvar.h,v 1.4 2008/06/26 05:42:18 ray Exp $ */
+/*     $OpenBSD: ukbdvar.h,v 1.5 2010/07/31 16:04:50 miod Exp $ */
 /*     $NetBSD: ukbdvar.h,v 1.2 2000/06/01 14:29:00 augustss Exp $     */
 
 /*-
@@ -36,7 +36,4 @@
 
 int    ukbd_cnattach(void);
 
-void   ukbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int),
-           void *);
-
 #endif /* _DEV_USB_UKBDVAR_H_ */
index 00b3b5f..2a72197 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ums.c,v 1.31 2009/10/13 19:33:19 pirofti Exp $ */
+/*     $OpenBSD: ums.c,v 1.32 2010/07/31 16:04:50 miod Exp $ */
 /*     $NetBSD: ums.c,v 1.60 2003/03/11 16:44:00 augustss Exp $        */
 
 /*
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/file.h>
-#include <sys/selinfo.h>
-#include <sys/proc.h>
-#include <sys/vnode.h>
-#include <sys/poll.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbhid.h>
 #include <dev/wscons/wsconsio.h>
 #include <dev/wscons/wsmousevar.h>
 
-#ifdef USB_DEBUG
-#define DPRINTF(x)     do { if (umsdebug) printf x; } while (0)
-#define DPRINTFN(n,x)  do { if (umsdebug>(n)) printf x; } while (0)
-int    umsdebug = 0;
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n,x)
-#endif
-
-#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
-
-#define UMSUNIT(s)     (minor(s))
-
-#define MAX_BUTTONS    16      /* must not exceed size of sc_buttons */
+#include <dev/usb/hidmsvar.h>
 
 struct ums_softc {
-       struct uhidev sc_hdev;
-
-       struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_w;
-       struct hid_location sc_loc_btn[MAX_BUTTONS];
-
-       int sc_enabled;
-
-       int flags;              /* device configuration */
-#define UMS_Z          0x01    /* Z direction available */
-#define UMS_SPUR_BUT_UP        0x02    /* spurious button up events */
-#define UMS_REVZ       0x04    /* Z-axis is reversed */
-#define UMS_W          0x08    /* W direction available */
-#define UMS_REVW       0x10    /* W-axis is reversed */
-#define UMS_LEADINGBYTE        0x20    /* Unknown leading byte */
-
-       int nbuttons;
-
-       u_int32_t sc_buttons;   /* mouse button status */
-       struct device *sc_wsmousedev;
-
-       char                    sc_dying;
+       struct uhidev   sc_hdev;
+       struct hidms    sc_ms;
+       char            sc_dying;
 };
 
-#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
-#define MOUSE_FLAGS (HIO_RELATIVE)
-
 void ums_intr(struct uhidev *addr, void *ibuf, u_int len);
 
 int    ums_enable(void *);
@@ -151,146 +111,22 @@ void
 ums_attach(struct device *parent, struct device *self, void *aux)
 {
        struct ums_softc *sc = (struct ums_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
        struct usb_attach_arg *uaa = aux;
        struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
-       struct wsmousedev_attach_args a;
        int size;
        void *desc;
-       u_int32_t flags, quirks;
-       int i, wheel, twheel;
+       u_int32_t quirks;
 
        sc->sc_hdev.sc_intr = ums_intr;
        sc->sc_hdev.sc_parent = uha->parent;
        sc->sc_hdev.sc_report_id = uha->reportid;
 
        quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
-       if (quirks & UQ_MS_REVZ)
-               sc->flags |= UMS_REVZ;
-       if (quirks & UQ_SPUR_BUT_UP)
-               sc->flags |= UMS_SPUR_BUT_UP;
-       if (quirks & UQ_MS_LEADING_BYTE)
-               sc->flags |= UMS_LEADINGBYTE;
-
        uhidev_get_report_desc(uha->parent, &desc, &size);
 
-       if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
-              uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
-               printf("\n%s: mouse has no X report\n",
-                      sc->sc_hdev.sc_dev.dv_xname);
-               return;
-       }
-       if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
-               printf("\n%s: X report 0x%04x not supported\n",
-                      sc->sc_hdev.sc_dev.dv_xname, flags);
-               return;
-       }
-
-       if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
-              uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
-               printf("\n%s: mouse has no Y report\n",
-                      sc->sc_hdev.sc_dev.dv_xname);
-               return;
-       }
-       if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
-               printf("\n%s: Y report 0x%04x not supported\n",
-                      sc->sc_hdev.sc_dev.dv_xname, flags);
+       if (hidms_setup(self, ms, quirks, uha->reportid, desc, size) != 0)
                return;
-       }
-
-       /*
-        * Try to guess the Z activator: check WHEEL, TWHEEL, and Z,
-        * in that order.
-        */
-
-       wheel = hid_locate(desc, size,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
-           uha->reportid, hid_input, &sc->sc_loc_z, &flags);
-       if (wheel == 0)
-               twheel = hid_locate(desc, size,
-                   HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
-                   uha->reportid, hid_input, &sc->sc_loc_z, &flags);
-       else
-               twheel = 0;
-
-       if (wheel || twheel) {
-               if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
-                       DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
-                               sc->sc_hdev.sc_dev.dv_xname, flags));
-                       sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
-               } else {
-                       sc->flags |= UMS_Z;
-                       /* Wheels need the Z axis reversed. */
-                       sc->flags ^= UMS_REVZ;
-               }
-               /*
-                * We might have both a wheel and Z direction; in this case,
-                * report the Z direction on the W axis.
-               */
-               if (hid_locate(desc, size,
-                   HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
-                   uha->reportid, hid_input, &sc->sc_loc_w, &flags)) {
-                       if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
-                               DPRINTF(("\n%s: Z report 0x%04x not supported\n",
-                                       sc->sc_hdev.sc_dev.dv_xname, flags));
-                               /* Bad Z coord, ignore it */
-                               sc->sc_loc_w.size = 0;
-                       }
-                       else
-                               sc->flags |= UMS_W;
-               }
-       } else if (hid_locate(desc, size,
-           HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
-           uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
-               if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
-                       DPRINTF(("\n%s: Z report 0x%04x not supported\n",
-                               sc->sc_hdev.sc_dev.dv_xname, flags));
-                       sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
-               } else {
-                       sc->flags |= UMS_Z;
-               }
-       }
-
-       /*
-        * The Microsoft Wireless Intellimouse 2.0 reports its wheel
-        * using 0x0048 (I've called it HUG_TWHEEL) and seems to expect
-        * us to know that the byte after the wheel is the tilt axis.
-        * There are no other HID axis descriptors other than X, Y and
-        * TWHEEL, so we report TWHEEL on the W axis.
-        */
-       if (twheel) {
-               sc->sc_loc_w = sc->sc_loc_z;
-               sc->sc_loc_w.pos = sc->sc_loc_w.pos + 8;
-               sc->flags |= UMS_W | UMS_LEADINGBYTE;
-               /* Wheels need their axis reversed. */
-               sc->flags ^= UMS_REVW;
-       }
-
-       /* figure out the number of buttons */
-       for (i = 1; i <= MAX_BUTTONS; i++)
-               if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
-                   uha->reportid, hid_input, &sc->sc_loc_btn[i - 1], 0))
-                       break;
-       sc->nbuttons = i - 1;
-
-       /*
-        * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
-        * shape than the Wireless Intellimouse 2.0, as its X, Y, wheel, and
-        * all of its other button positions are all off. It also reports that
-        * it has two addional buttons and a tilt wheel.
-        */
-       if (quirks & UQ_MS_BAD_CLASS) {
-               /* UMS_LEADINGBYTE cleared on purpose */
-               sc->flags = UMS_Z | UMS_SPUR_BUT_UP;
-               sc->nbuttons = 3;
-               /* XXX change sc_hdev isize to 5? */
-               /* 1st byte of descriptor report contains garbage */
-               sc->sc_loc_x.pos = 16;
-               sc->sc_loc_y.pos = 24;
-               sc->sc_loc_z.pos = 32;
-               sc->sc_loc_btn[0].pos = 8;
-               sc->sc_loc_btn[1].pos = 9;
-               sc->sc_loc_btn[2].pos = 10;
-       }
 
        /*
         * The Microsoft Wireless Notebook Optical Mouse 3000 Model 1049 has
@@ -301,60 +137,25 @@ ums_attach(struct device *parent, struct device *self, void *aux)
         */
        if (uaa->vendor == USB_VENDOR_MICROSOFT &&
            uaa->product == USB_PRODUCT_MICROSOFT_WLNOTEBOOK3) {
-               sc->flags = UMS_Z;
-               sc->nbuttons = 3;
+               ms->sc_flags = HIDMS_Z;
+               ms->sc_num_buttons = 3;
                /* XXX change sc_hdev isize to 5? */
-               sc->sc_loc_x.pos = 8;
-               sc->sc_loc_y.pos = 16;
-               sc->sc_loc_z.pos = 24;
-               sc->sc_loc_btn[0].pos = 0;
-               sc->sc_loc_btn[1].pos = 1;
-               sc->sc_loc_btn[2].pos = 2;
+               ms->sc_loc_x.pos = 8;
+               ms->sc_loc_y.pos = 16;
+               ms->sc_loc_z.pos = 24;
+               ms->sc_loc_btn[0].pos = 0;
+               ms->sc_loc_btn[1].pos = 1;
+               ms->sc_loc_btn[2].pos = 2;
        }
 
-       printf(": %d button%s",
-           sc->nbuttons, sc->nbuttons <= 1 ? "" : "s");
-       switch (sc->flags & (UMS_Z | UMS_W)) {
-       case UMS_Z:
-               printf(", Z dir");
-               break;
-       case UMS_W:
-               printf(", W dir");
-               break;
-       case UMS_Z | UMS_W:
-               printf(", Z and W dir");
-               break;
-       }
-       printf("\n");
-
-#ifdef USB_DEBUG
-       DPRINTF(("ums_attach: sc=%p\n", sc));
-       DPRINTF(("ums_attach: X\t%d/%d\n",
-            sc->sc_loc_x.pos, sc->sc_loc_x.size));
-       DPRINTF(("ums_attach: Y\t%d/%d\n",
-           sc->sc_loc_y.pos, sc->sc_loc_y.size));
-       if (sc->flags & UMS_Z)
-               DPRINTF(("ums_attach: Z\t%d/%d\n",
-                   sc->sc_loc_z.pos, sc->sc_loc_z.size));
-       if (sc->flags & UMS_W)
-               DPRINTF(("ums_attach: W\t%d/%d\n",
-                   sc->sc_loc_w.pos, sc->sc_loc_w.size));
-       for (i = 1; i <= sc->nbuttons; i++) {
-               DPRINTF(("ums_attach: B%d\t%d/%d\n",
-                   i, sc->sc_loc_btn[i - 1].pos, sc->sc_loc_btn[i - 1].size));
-       }
-#endif
-
-       a.accessops = &ums_accessops;
-       a.accesscookie = sc;
-
-       sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+       hidms_attach(ms, &ums_accessops);
 }
 
 int
 ums_activate(struct device *self, int act)
 {
        struct ums_softc *sc = (struct ums_softc *)self;
+       struct hidms *ms = &sc->sc_ms;
        int rv = 0;
 
        switch (act) {
@@ -362,8 +163,8 @@ ums_activate(struct device *self, int act)
                break;
 
        case DVACT_DEACTIVATE:
-               if (sc->sc_wsmousedev != NULL)
-                       rv = config_deactivate(sc->sc_wsmousedev);
+               if (ms->sc_wsmousedev != NULL)
+                       rv = config_deactivate(ms->sc_wsmousedev);
                sc->sc_dying = 1;
                break;
        }
@@ -374,122 +175,58 @@ int
 ums_detach(struct device *self, int flags)
 {
        struct ums_softc *sc = (struct ums_softc *)self;
-       int rv = 0;
+       struct hidms *ms = &sc->sc_ms;
 
-       DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
-
-       /* No need to do reference counting of ums, wsmouse has all the goo. */
-       if (sc->sc_wsmousedev != NULL)
-               rv = config_detach(sc->sc_wsmousedev, flags);
-
-       return (rv);
+       return hidms_detach(ms, flags);
 }
 
 void
 ums_intr(struct uhidev *addr, void *buf, u_int len)
 {
        struct ums_softc *sc = (struct ums_softc *)addr;
-       u_char *ibuf = (u_char *)buf;
-       int dx, dy, dz, dw;
-       u_int32_t buttons = 0;
-       int i;
-       int s;
+       struct hidms *ms = &sc->sc_ms;
 
-       DPRINTFN(5,("ums_intr: len=%d\n", len));
-
-       /*
-        * The Microsoft Wireless Intellimouse 2.0 sends one extra leading
-        * byte of data compared to most USB mice.  This byte frequently
-        * switches from 0x01 (usual state) to 0x02.  It may be used to
-        * report non-standard events (such as battery life).  However,
-        * at the same time, it generates a left click event on the
-        * button byte, where there shouldn't be any.  We simply discard
-        * the packet in this case.
-        *
-        * This problem affects the MS Wireless Notebook Optical Mouse, too.
-        * However, the leading byte for this mouse is normally 0x11, and
-        * the phantom mouse click occurs when it's 0x14.
-        */
-       if (sc->flags & UMS_LEADINGBYTE) {
-               if (*ibuf++ == 0x02)
-                       return;
-               /* len--; */
-       } else if (sc->flags & UMS_SPUR_BUT_UP) {
-               if (*ibuf == 0x14 || *ibuf == 0x15)
-                       return;
-       }
-
-       dx =  hid_get_data(ibuf, &sc->sc_loc_x);
-       dy = -hid_get_data(ibuf, &sc->sc_loc_y);
-       dz =  hid_get_data(ibuf, &sc->sc_loc_z);
-       dw =  hid_get_data(ibuf, &sc->sc_loc_w);
-       if (sc->flags & UMS_REVZ)
-               dz = -dz;
-       if (sc->flags & UMS_REVW)
-               dw = -dw;
-       for (i = 0; i < sc->nbuttons; i++)
-               if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
-                       buttons |= (1 << UMS_BUT(i));
-
-       if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
-           buttons != sc->sc_buttons) {
-               DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d w:%d buttons:0x%x\n",
-                       dx, dy, dz, dw, buttons));
-               sc->sc_buttons = buttons;
-               if (sc->sc_wsmousedev != NULL) {
-                       s = spltty();
-                       wsmouse_input(sc->sc_wsmousedev, buttons,
-                           dx, dy, dz, dw, WSMOUSE_INPUT_DELTA);
-                       splx(s);
-               }
-       }
+       if (ms->sc_enabled != 0)
+               hidms_input(ms, (uint8_t *)buf, len);
 }
 
 int
 ums_enable(void *v)
 {
        struct ums_softc *sc = v;
-
-       DPRINTFN(1,("ums_enable: sc=%p\n", sc));
+       struct hidms *ms = &sc->sc_ms;
+       int rv;
 
        if (sc->sc_dying)
-               return (EIO);
-
-       if (sc->sc_enabled)
-               return (EBUSY);
+               return EIO;
 
-       sc->sc_enabled = 1;
-       sc->sc_buttons = 0;
+       if ((rv = hidms_enable(ms)) != 0)
+               return rv;
 
-       return (uhidev_open(&sc->sc_hdev));
+       return uhidev_open(&sc->sc_hdev);
 }
 
 void
 ums_disable(void *v)
 {
        struct ums_softc *sc = v;
+       struct hidms *ms = &sc->sc_ms;
 
-       DPRINTFN(1,("ums_disable: sc=%p\n", sc));
-#ifdef DIAGNOSTIC
-       if (!sc->sc_enabled) {
-               printf("ums_disable: not enabled\n");
-               return;
-       }
-#endif
-
-       sc->sc_enabled = 0;
+       hidms_disable(ms);
        uhidev_close(&sc->sc_hdev);
 }
 
 int
 ums_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
-
 {
+       struct ums_softc *sc = v;
+       struct hidms *ms = &sc->sc_ms;
+
        switch (cmd) {
        case WSMOUSEIO_GTYPE:
                *(u_int *)data = WSMOUSE_TYPE_USB;
-               return (0);
+               return 0;
+       default:
+               return hidms_ioctl(ms, cmd, data, flag, p);
        }
-
-       return (-1);
 }