From owner-freebsd-usb@FreeBSD.ORG Mon Nov 8 10:50:32 2004 Return-Path: Delivered-To: freebsd-usb@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C526A16A4D2 for ; Mon, 8 Nov 2004 10:50:29 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7B83E43D49 for ; Mon, 8 Nov 2004 10:50:29 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.11/8.12.11) with ESMTP id iA8AoTJl008817 for ; Mon, 8 Nov 2004 10:50:29 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id iA8AoS4s008816; Mon, 8 Nov 2004 10:50:28 GMT (envelope-from gnats) Date: Mon, 8 Nov 2004 10:50:28 GMT Message-Id: <200411081050.iA8AoS4s008816@freefall.freebsd.org> To: freebsd-usb@FreeBSD.org From: Matt Wright Subject: Re: kern/70607: [patch] Add Support for USB Microsoft Intellimouse (possibly others) X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Matt Wright List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Nov 2004 10:50:33 -0000 The following reply was made to PR kern/70607; it has been noted by GNATS. From: Matt Wright To: freebsd-gnats-submit@FreeBSD.org, amistry@am-productions.biz Cc: Subject: Re: kern/70607: [patch] Add Support for USB Microsoft Intellimouse (possibly others) Date: Mon, 08 Nov 2004 10:41:18 +0000 Further to the patch that Anish posted here is a patch that removes bugs 2 and 3 which Mark noticed. If you need any explanation there is a fairly detailed explanation of the patch, well at least the method I used to debug it, at: http://www.consultmatt.co.uk/freebsd/intellimouse.php Regards, Matt --- sys/dev/usb/usbhid.h.orig Mon Sep 20 00:59:48 2004 +++ sys/dev/usb/usbhid.h Mon Sep 20 02:14:40 2004 @@ -123,6 +123,7 @@ #define HUG_VBRY 0x0044 #define HUG_VBRZ 0x0045 #define HUG_VNO 0x0046 +#define HUG_TWHEEL 0x0048 // M$ Wireless Intellimouse Wheel #define HUG_SYSTEM_CONTROL 0x0080 #define HUG_SYSTEM_POWER_DOWN 0x0081 #define HUG_SYSTEM_SLEEP 0x0082 --- sys/sys/mouse.h.orig Fri Jul 30 01:59:40 2004 +++ sys/sys/mouse.h Tue Sep 21 00:42:37 2004 @@ -58,6 +58,7 @@ int dx; /* x movement */ int dy; /* y movement */ int dz; /* z movement */ + int dt; /* left right tilt axis */ } mousestatus_t; /* button */ --- sys/dev/usb/ums.c.orig Mon Aug 16 00:39:18 2004 +++ sys/dev/usb/ums.c Tue Sep 21 00:47:52 2004 @@ -104,7 +104,7 @@ u_char *sc_ibuf; u_int8_t sc_iid; int sc_isize; - struct hid_location sc_loc_x, sc_loc_y, sc_loc_z; + struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_t; struct hid_location *sc_loc_btn; usb_callout_t callout_handle; /* for spurious button ups */ @@ -114,6 +114,7 @@ int flags; /* device configuration */ #define UMS_Z 0x01 /* z direction available */ +#define UMS_T 0x02 /* aa direction available (tilt) */ #define UMS_SPUR_BUT_UP 0x02 /* spurious button up events */ int nbuttons; #define MAX_BUTTONS 7 /* chosen because sc_buttons is u_char */ @@ -140,7 +141,7 @@ usbd_private_handle priv, usbd_status status); Static void ums_add_to_queue(struct ums_softc *sc, - int dx, int dy, int dz, int buttons); + int dx, int dy, int dz, int dt, int buttons); Static void ums_add_to_queue_timeout(void *priv); Static int ums_enable(void *); @@ -269,6 +270,8 @@ if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z), hid_input, &sc->sc_loc_z, &flags) || hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), + hid_input, &sc->sc_loc_z, &flags) || + hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags)) { if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) { sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */ @@ -277,6 +280,17 @@ } } + /* The Microsoft Wireless Intellimouse 2.0 reports it's wheel + * using 0x0048 (i've called it HUG_TWHEEL) and seems to expect + * you 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 */ + if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL), + hid_input, &sc->sc_loc_t, &flags)) { + sc->sc_loc_t.pos = sc->sc_loc_t.pos + 8; + 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), @@ -290,8 +304,9 @@ USB_ATTACH_ERROR_RETURN; } - printf("%s: %d buttons%s\n", USBDEVNAME(sc->sc_dev), - sc->nbuttons, sc->flags & UMS_Z? " and Z dir." : ""); + printf("%s: %d buttons%s%s.\n", USBDEVNAME(sc->sc_dev), + sc->nbuttons, sc->flags & UMS_Z? " and Z dir" : "", + sc->flags & UMS_T?" and a TILT dir": ""); for (i = 1; i <= sc->nbuttons; i++) hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i), @@ -408,15 +423,15 @@ { struct ums_softc *sc = addr; u_char *ibuf; - int dx, dy, dz; + int dx, dy, dz, dt; u_char buttons = 0; int i; #define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i)) DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status)); - DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n", - sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2])); + DPRINTFN(5, ("ums_intr: data = %02x %02x %02x %02x %02x %02x\n", + sc->sc_ibuf[0], sc->sc_ibuf[1], sc->sc_ibuf[2], sc->sc_ibuf[3], sc->sc_ibuf[4], sc->sc_ibuf[5])); if (status == USBD_CANCELLED) return; @@ -425,32 +440,44 @@ DPRINTF(("ums_intr: status=%d\n", status)); if (status == USBD_STALLED) usbd_clear_endpoint_stall_async(sc->sc_intrpipe); - return; + if(status != USBD_IOERROR) + return; } ibuf = sc->sc_ibuf; if (sc->sc_iid) { - if (*ibuf++ != sc->sc_iid) - return; + ibuf++; } + /* The M$ Wireless Intellimouse 2.0 sends 1 extra leading byte of + * data compared to most USB mice. This byte frequently switches + * from 0x01 (usual state) to 0x02. I assume it is to allow + * extra, non-standard, reporting (say battery-life). However + * at the same time it generates a left-click message on the button + * byte which causes spurious left-click's where there shouldn't be. + * This should sort that. */ + if ((sc->sc_ibuf != ibuf) && (sc->sc_ibuf[0] == 0x02)) + 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); + dt = -hid_get_data(ibuf, &sc->sc_loc_t); 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 || (sc->flags & UMS_Z) + if (dx || dy || dz || dt || (sc->flags & UMS_Z) || buttons != sc->status.button) { - DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n", - dx, dy, dz, buttons)); + DPRINTFN(5, ("ums_intr: x:%d y:%d z:%d aa:%d buttons:0x%x\n", + dx, dy, dz, dt, buttons)); sc->status.button = buttons; sc->status.dx += dx; sc->status.dy += dy; sc->status.dz += dz; - + sc->status.dt += dt; + /* Discard data in case of full buffer */ if (sc->qcount == sizeof(sc->qbuf)) { DPRINTF(("Buffer full, discarded packet")); @@ -466,13 +493,13 @@ * In any other case we delete the timeout event. */ if (sc->flags & UMS_SPUR_BUT_UP && - dx == 0 && dy == 0 && dz == 0 && buttons == 0) { + dx == 0 && dy == 0 && dz == 0 && dt == 0 && buttons == 0) { usb_callout(sc->callout_handle, MS_TO_TICKS(50 /*msecs*/), ums_add_to_queue_timeout, (void *) sc); } else { usb_uncallout(sc->callout_handle, ums_add_to_queue_timeout, (void *) sc); - ums_add_to_queue(sc, dx, dy, dz, buttons); + ums_add_to_queue(sc, dx, dy, dz, dt, buttons); } } } @@ -484,12 +511,12 @@ int s; s = splusb(); - ums_add_to_queue(sc, 0, 0, 0, 0); + ums_add_to_queue(sc, 0, 0, 0, 0, 0); splx(s); } Static void -ums_add_to_queue(struct ums_softc *sc, int dx, int dy, int dz, int buttons) +ums_add_to_queue(struct ums_softc *sc, int dx, int dy, int dz, int dt, int buttons) { /* Discard data in case of full buffer */ if (sc->qhead+sc->mode.packetsize > sizeof(sc->qbuf)) { @@ -503,6 +530,8 @@ if (dy < -256) dy = -256; if (dz > 126) dz = 126; if (dz < -128) dz = -128; + if (dt > 126) dt = 126; + if (dt < -128) dt = -128; sc->qbuf[sc->qhead] = sc->mode.syncmask[1]; sc->qbuf[sc->qhead] |= ~buttons & MOUSE_MSC_BUTTONS; @@ -550,7 +579,7 @@ sc->qhead = sc->qtail = 0; sc->status.flags = 0; sc->status.button = sc->status.obutton = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; + sc->status.dx = sc->status.dy = sc->status.dz = sc->status.dt = 0; callout_handle_init((struct callout_handle *)&sc->callout_handle); @@ -807,10 +836,10 @@ *status = sc->status; sc->status.obutton = sc->status.button; sc->status.button = 0; - sc->status.dx = sc->status.dy = sc->status.dz = 0; + sc->status.dx = sc->status.dy = sc->status.dz = sc->status.dt = 0; splx(s); - if (status->dx || status->dy || status->dz) + if (status->dx || status->dy || status->dz || status->dt) status->flags |= MOUSE_POSCHANGED; if (status->button != status->obutton) status->flags |= MOUSE_BUTTONSCHANGED;