summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/bluetooth/btkbd.c428
-rw-r--r--sys/dev/bluetooth/btms.c190
-rw-r--r--sys/dev/bluetooth/files.bluetooth6
-rw-r--r--sys/dev/isa/pcppi.c16
-rw-r--r--sys/dev/usb/files.usb12
-rw-r--r--sys/dev/usb/hidkbd.c638
-rw-r--r--sys/dev/usb/hidkbdsc.h104
-rw-r--r--sys/dev/usb/hidkbdvar.h34
-rw-r--r--sys/dev/usb/hidms.c348
-rw-r--r--sys/dev/usb/hidmsvar.h67
-rw-r--r--sys/dev/usb/ukbd.c657
-rw-r--r--sys/dev/usb/ukbdvar.h5
-rw-r--r--sys/dev/usb/ums.c341
13 files changed, 1363 insertions, 1483 deletions
diff --git a/sys/dev/bluetooth/btkbd.c b/sys/dev/bluetooth/btkbd.c
index 863f6c551ad..ff34824c200 100644
--- a/sys/dev/bluetooth/btkbd.c
+++ b/sys/dev/bluetooth/btkbd.c
@@ -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 $ */
/*
@@ -62,10 +62,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * based on dev/usb/ukbd.c
- */
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/device.h>
@@ -87,54 +83,14 @@
#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
diff --git a/sys/dev/bluetooth/btms.c b/sys/dev/bluetooth/btms.c
index 7ef3d457809..8ae2d02cc6a 100644
--- a/sys/dev/bluetooth/btms.c
+++ b/sys/dev/bluetooth/btms.c
@@ -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 $ */
/*
@@ -62,10 +62,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * based on dev/usb/ums.c
- */
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/device.h>
@@ -84,33 +80,13 @@
#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);
}
diff --git a/sys/dev/bluetooth/files.bluetooth b/sys/dev/bluetooth/files.bluetooth
index e204487c77b..7f3678bf4a1 100644
--- a/sys/dev/bluetooth/files.bluetooth
+++ b/sys/dev/bluetooth/files.bluetooth
@@ -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
diff --git a/sys/dev/isa/pcppi.c b/sys/dev/isa/pcppi.c
index 57349b16018..74582d37c4f 100644
--- a/sys/dev/isa/pcppi.c
+++ b/sys/dev/isa/pcppi.c
@@ -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 $ */
/*
@@ -45,11 +45,11 @@
#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 */
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb
index 741ed827d35..a7e092a3eff 100644
--- a/sys/dev/usb/files.usb
+++ b/sys/dev/usb/files.usb
@@ -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
index 00000000000..687790dbd0a
--- /dev/null
+++ b/sys/dev/usb/hidkbd.c
@@ -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
index 00000000000..484bc25642b
--- /dev/null
+++ b/sys/dev/usb/hidkbdsc.h
@@ -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
index 00000000000..44b3d6408c2
--- /dev/null
+++ b/sys/dev/usb/hidkbdvar.h
@@ -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
index 00000000000..f076c503bd4
--- /dev/null
+++ b/sys/dev/usb/hidms.c
@@ -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
index 00000000000..bf032f25254
--- /dev/null
+++ b/sys/dev/usb/hidmsvar.h
@@ -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);
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 8fa1e46d89a..6f63447b085 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -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 $ */
/*
@@ -41,12 +41,6 @@
#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);
-}
diff --git a/sys/dev/usb/ukbdvar.h b/sys/dev/usb/ukbdvar.h
index e3613477644..7c2251f63e6 100644
--- a/sys/dev/usb/ukbdvar.h
+++ b/sys/dev/usb/ukbdvar.h
@@ -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_ */
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 00b3b5fd06c..2a72197acb1 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -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 $ */
/*
@@ -40,12 +40,6 @@
#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>
@@ -60,48 +54,14 @@
#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);
}