--- /usr/src/sys/dev/usb/usbhid.h.org 2009-01-16 02:45:38.000000000 +0900 +++ /usr/src/sys/dev/usb/usbhid.h 2009-08-03 18:49:14.000000000 +0900 @@ -165,6 +165,9 @@ typedef struct usb_hid_descriptor { #define HUD_ERASER 0x0045 #define HUD_TABLET_PICK 0x0046 +/* Usages, Consumer */ +#define HUC_AC_PAN 0x0238 /* Logitec(Creative Labs) WheelMouse */ + #define HID_USAGE2(p,u) (((p) << 16) | u) #define UHID_INPUT_REPORT 0x01 --- /usr/src/sys/dev/usb/ums.c.org 2008-10-02 11:57:24.000000000 +0900 +++ /usr/src/sys/dev/usb/ums.c 2009-12-17 00:00:00.000000000 +0900 @@ -109,6 +109,7 @@ struct ums_softc { #define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */ #define UMS_T 0x04 /* aa direction available (tilt) */ #define UMS_REVZ 0x08 /* Z-axis is reversed */ +#define UMS_W 0x10 /* W direction available (additional wheel) */ int nbuttons; #define MAX_BUTTONS 31 /* chosen because sc_buttons is int */ @@ -286,6 +287,8 @@ USB_ATTACH(ums) printf("\n%s: Z report 0x%04x not supported\n", device_get_nameunit(sc->sc_dev), flags); sc->sc_loc_w.size = 0; /* Bad Z, ignore */ + } else { + sc->flags |= UMS_W; } } } else if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, @@ -311,6 +314,20 @@ USB_ATTACH(ums) sc->flags |= UMS_T; } + /* The Logitec(Creative Labs) WheelMouse reports it's wheel-tilt + * using "Consumer: AC Pan". + */ + if (hid_locate(desc, size, HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN), + hid_input, &sc->sc_loc_t, &flags)) { + if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { + printf("\n%s: HUC_AC_PAN report 0x%04x not supported\n", + device_get_nameunit(sc->sc_dev), flags); + sc->sc_loc_t.size = 0; + } else { + sc->flags |= UMS_T; + } + } + /* figure out the number of buttons */ for (i = 1; i <= MAX_BUTTONS; i++) if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), @@ -353,6 +370,9 @@ USB_ATTACH(ums) 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_T) + DPRINTF(("ums_attach: T\t%d/%d\n", + sc->sc_loc_t.pos, sc->sc_loc_t.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)); @@ -446,7 +466,9 @@ ums_intr(xfer, addr, status) u_char *ibuf; int dx, dy, dz, dw, dt; int buttons = 0; + static int buttons_last = 0; int i; + int buttons_repeat = 0; #define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) @@ -494,18 +516,49 @@ ums_intr(xfer, addr, status) 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_T) + if (sc->flags & UMS_W) { + dw = hid_get_data(ibuf, &sc->sc_loc_w); + i = sc->nbuttons; + if (0 < dw) { + buttons |= (1 << UMS_BUT(i + 0)); + if ((1 << UMS_BUT(i + 0)) & sc->status.button) { + buttons_repeat = (1 << UMS_BUT(i + 0)); + } + } else if (dw < 0) { + buttons |= (1 << UMS_BUT(i + 1)); + if ((1 << UMS_BUT(i + 1)) & sc->status.button) { + buttons_repeat = (1 << UMS_BUT(i + 1)); + } + } + } else { + dw = 0; + } + if (sc->flags & UMS_T) { dt = -hid_get_data(ibuf, &sc->sc_loc_t); - else + i = sc->nbuttons + ((sc->flags & UMS_W) ? 2 : 0); + if (0 < dt) { + buttons |= (1 << UMS_BUT(i + 0)); + if ((1 << UMS_BUT(i + 0)) & sc->status.button) { + buttons_repeat = (1 << UMS_BUT(i + 0)); + } + } else if (dt < 0) { + buttons |= (1 << UMS_BUT(i + 1)); + if ((1 << UMS_BUT(i + 1)) & sc->status.button) { + buttons_repeat = (1 << UMS_BUT(i + 1)); + } + } + } else { dt = 0; + } for (i = 0; i < sc->nbuttons; i++) if (hid_get_data(ibuf, &sc->sc_loc_btn[i])) buttons |= (1 << UMS_BUT(i)); - if (dx || dy || dz || dt || dw || (sc->flags & UMS_Z) + if (dx || dy || dz || dt || dw + || (sc->flags & UMS_Z) || (sc->flags & UMS_W) || (sc->flags & UMS_T) + || buttons_repeat || buttons != sc->status.button) { DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d w:%d t:%d buttons:0x%x\n", dx, dy, dz, dw, dt, buttons)); @@ -538,7 +591,16 @@ ums_intr(xfer, addr, status) } else { usb_uncallout(sc->callout_handle, ums_add_to_queue_timeout, (void *) sc); + if ( ((( 0x07) & buttons) != (( 0x07) & buttons_last)) + && (((~0x07) & buttons) != ((~0x07) & buttons_last)) + ) { + ums_add_to_queue(sc, dx, dy, dz, dt, (((~0x07) & buttons) | (( 0x07) & buttons_last))); + } + if (buttons_repeat) { + ums_add_to_queue(sc, 0, 0, 0, 0, buttons & ~buttons_repeat); + } ums_add_to_queue(sc, dx, dy, dz, dt, buttons); + buttons_last = buttons; } } } @@ -570,7 +632,7 @@ ums_add_to_queue(struct ums_softc *sc, i if (dz > 126) dz = 126; if (dz < -128) dz = -128; if (dt > 126) dt = 126; - if (dt < -128) dt = -128; + if (dt < -128) dt = -128; sc->qbuf[sc->qhead] = sc->mode.syncmask[1]; sc->qbuf[sc->qhead] |= ~buttons & MOUSE_MSC_BUTTONS;