Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Mar 2009 15:25:47 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189583 - head/sys/dev/usb/input
Message-ID:  <200903091525.n29FPlVv030219@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Mon Mar  9 15:25:46 2009
New Revision: 189583
URL: http://svn.freebsd.org/changeset/base/189583

Log:
  MFp4 //depot/projects/usb@158916
  
  USB mouse patch to address complicated data reporting descriptors.
  
  Reported by:	Boris Kotzev
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/input/ums.c

Modified: head/sys/dev/usb/input/ums.c
==============================================================================
--- head/sys/dev/usb/input/ums.c	Mon Mar  9 14:04:18 2009	(r189582)
+++ head/sys/dev/usb/input/ums.c	Mon Mar  9 15:25:46 2009	(r189583)
@@ -117,6 +117,12 @@ struct ums_softc {
 
 	uint8_t	sc_buttons;
 	uint8_t	sc_iid;
+	uint8_t	sc_iid_w;
+	uint8_t	sc_iid_x;
+	uint8_t	sc_iid_y;
+	uint8_t	sc_iid_z;
+	uint8_t	sc_iid_t;
+	uint8_t	sc_iid_btn[UMS_BUTTON_MAX];
 	uint8_t	sc_temp[64];
 };
 
@@ -168,6 +174,7 @@ ums_intr_callback(struct usb2_xfer *xfer
 	int32_t dz;
 	int32_t dt;
 	uint8_t i;
+	uint8_t id;
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
@@ -190,42 +197,14 @@ ums_intr_callback(struct usb2_xfer *xfer
 		    (len > 4) ? buf[4] : 0, (len > 5) ? buf[5] : 0,
 		    (len > 6) ? buf[6] : 0, (len > 7) ? buf[7] : 0);
 
-		/*
-		 * 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.  Currently it's the only user of
-		 * UMS_FLAG_T_AXIS so use it as an identifier.
-		 *
-		 *
-		 * UPDATE: This problem affects the M$ Wireless
-		 * Notebook Optical Mouse, too. However, the leading
-		 * byte for this mouse is normally 0x11, and the
-		 * phantom mouse click occurs when its 0x14.
-		 *
-		 * We probably should switch to some more official quirk.
-		 */
 		if (sc->sc_iid) {
-			if (sc->sc_flags & UMS_FLAG_T_AXIS) {
-				if (*buf == 0x02) {
-					goto tr_setup;
-				}
-			} else {
-				if (*buf != sc->sc_iid) {
-					goto tr_setup;
-				}
-			}
+			id = *buf;
 
 			len--;
 			buf++;
 
 		} else {
+			id = 0;
 			if (sc->sc_flags & UMS_FLAG_SBU) {
 				if ((*buf == 0x14) || (*buf == 0x15)) {
 					goto tr_setup;
@@ -233,25 +212,37 @@ ums_intr_callback(struct usb2_xfer *xfer
 			}
 		}
 
-		dw = (sc->sc_flags & UMS_FLAG_W_AXIS) ?
-		    hid_get_data(buf, len, &sc->sc_loc_w) : 0;
-
-		dx = (sc->sc_flags & UMS_FLAG_X_AXIS) ?
-		    hid_get_data(buf, len, &sc->sc_loc_x) : 0;
-
-		dy = (sc->sc_flags & UMS_FLAG_Y_AXIS) ?
-		    -hid_get_data(buf, len, &sc->sc_loc_y) : 0;
+		if ((sc->sc_flags & UMS_FLAG_W_AXIS) && (id == sc->sc_iid_w))
+			dw = hid_get_data(buf, len, &sc->sc_loc_w);
+		else
+			dw = 0;
+
+		if ((sc->sc_flags & UMS_FLAG_X_AXIS) && (id == sc->sc_iid_x))
+			dx = hid_get_data(buf, len, &sc->sc_loc_x);
+		else
+			dx = 0;
+
+		if ((sc->sc_flags & UMS_FLAG_Y_AXIS) && (id == sc->sc_iid_y))
+			dy = -hid_get_data(buf, len, &sc->sc_loc_y);
+		else
+			dy = 0;
+
+		if ((sc->sc_flags & UMS_FLAG_Z_AXIS) && (id == sc->sc_iid_z))
+			dz = -hid_get_data(buf, len, &sc->sc_loc_z);
+		else
+			dz = 0;
 
-		dz = (sc->sc_flags & UMS_FLAG_Z_AXIS) ?
-		    -hid_get_data(buf, len, &sc->sc_loc_z) : 0;
-
-		if (sc->sc_flags & UMS_FLAG_REVZ) {
+		if (sc->sc_flags & UMS_FLAG_REVZ)
 			dz = -dz;
-		}
-		dt = (sc->sc_flags & UMS_FLAG_T_AXIS) ?
-		    -hid_get_data(buf, len, &sc->sc_loc_t): 0;
+
+		if ((sc->sc_flags & UMS_FLAG_T_AXIS) && (id == sc->sc_iid_t))
+			dt = -hid_get_data(buf, len, &sc->sc_loc_t);
+		else
+			dt = 0;
 
 		for (i = 0; i < sc->sc_buttons; i++) {
+			if (id != sc->sc_iid_btn[i])
+				continue;
 			if (hid_get_data(buf, len, &sc->sc_loc_btn[i])) {
 				buttons |= (1 << UMS_BUT(i));
 			}
@@ -413,14 +404,14 @@ ums_attach(device_t dev)
 		goto detach;
 	}
 	if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
-	    hid_input, &sc->sc_loc_x, &flags, &sc->sc_iid)) {
+	    hid_input, &sc->sc_loc_x, &flags, &sc->sc_iid_x)) {
 
 		if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
 			sc->sc_flags |= UMS_FLAG_X_AXIS;
 		}
 	}
 	if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
-	    hid_input, &sc->sc_loc_y, &flags, &sc->sc_iid)) {
+	    hid_input, &sc->sc_loc_y, &flags, &sc->sc_iid_y)) {
 
 		if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
 			sc->sc_flags |= UMS_FLAG_Y_AXIS;
@@ -428,9 +419,9 @@ ums_attach(device_t dev)
 	}
 	/* Try the wheel first as the Z activator since it's tradition. */
 	if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
-	    HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid) ||
+	    HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z) ||
 	    hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
-	    HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid)) {
+	    HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z)) {
 		if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
 			sc->sc_flags |= UMS_FLAG_Z_AXIS;
 		}
@@ -439,14 +430,14 @@ ums_attach(device_t dev)
 		 * put the Z on the W coordinate.
 		 */
 		if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
-		    HUG_Z), hid_input, &sc->sc_loc_w, &flags, &sc->sc_iid)) {
+		    HUG_Z), hid_input, &sc->sc_loc_w, &flags, &sc->sc_iid_w)) {
 
 			if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
 				sc->sc_flags |= UMS_FLAG_W_AXIS;
 			}
 		}
 	} else if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
-	    HUG_Z), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid)) {
+	    HUG_Z), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z)) {
 
 		if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
 			sc->sc_flags |= UMS_FLAG_Z_AXIS;
@@ -460,7 +451,7 @@ ums_attach(device_t dev)
 	 * TWHEEL
 	 */
 	if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
-	    hid_input, &sc->sc_loc_t, &flags, &sc->sc_iid)) {
+	    hid_input, &sc->sc_loc_t, &flags, &sc->sc_iid_t)) {
 
 		sc->sc_loc_t.pos += 8;
 
@@ -472,14 +463,14 @@ ums_attach(device_t dev)
 
 	for (i = 0; i < UMS_BUTTON_MAX; i++) {
 		if (!hid_locate(d_ptr, d_len, HID_USAGE2(HUP_BUTTON, (i + 1)),
-			hid_input, &sc->sc_loc_btn[i], NULL, &sc->sc_iid)) {
+			hid_input, &sc->sc_loc_btn[i], NULL, &sc->sc_iid_btn[i])) {
 			break;
 		}
 	}
 
 	sc->sc_buttons = i;
 
-	isize = hid_report_size(d_ptr, d_len, hid_input, NULL);
+	isize = hid_report_size(d_ptr, d_len, hid_input, &sc->sc_iid);
 
 	/*
 	 * The Microsoft Wireless Notebook Optical Mouse seems to be in worse
@@ -495,6 +486,12 @@ ums_attach(device_t dev)
 		sc->sc_buttons = 3;
 		isize = 5;
 		sc->sc_iid = 0;
+		sc->sc_iid_x = 0;
+		sc->sc_iid_y = 0;
+		sc->sc_iid_z = 0;
+		sc->sc_iid_btn[0] = 0;
+		sc->sc_iid_btn[1] = 0;
+		sc->sc_iid_btn[2] = 0;
 		/* 1st byte of descriptor report contains garbage */
 		sc->sc_loc_x.pos = 16;
 		sc->sc_loc_y.pos = 24;
@@ -544,15 +541,21 @@ ums_attach(device_t dev)
 
 #if USB_DEBUG
 	DPRINTF("sc=%p\n", sc);
-	DPRINTF("X\t%d/%d\n", sc->sc_loc_x.pos, sc->sc_loc_x.size);
-	DPRINTF("Y\t%d/%d\n", sc->sc_loc_y.pos, sc->sc_loc_y.size);
-	DPRINTF("Z\t%d/%d\n", sc->sc_loc_z.pos, sc->sc_loc_z.size);
-	DPRINTF("T\t%d/%d\n", sc->sc_loc_t.pos, sc->sc_loc_t.size);
-	DPRINTF("W\t%d/%d\n", sc->sc_loc_w.pos, sc->sc_loc_w.size);
+	DPRINTF("X\t%d/%d id=%d\n", sc->sc_loc_x.pos,
+	    sc->sc_loc_x.size, sc->sc_iid_x);
+	DPRINTF("Y\t%d/%d id=%d\n", sc->sc_loc_y.pos,
+	    sc->sc_loc_y.size, sc->sc_iid_y);
+	DPRINTF("Z\t%d/%d id=%d\n", sc->sc_loc_z.pos,
+	    sc->sc_loc_z.size, sc->sc_iid_z);
+	DPRINTF("T\t%d/%d id=%d\n", sc->sc_loc_t.pos,
+	    sc->sc_loc_t.size, sc->sc_iid_t);
+	DPRINTF("W\t%d/%d id=%d\n", sc->sc_loc_w.pos,
+	    sc->sc_loc_w.size, sc->sc_iid_w);
 
 	for (i = 0; i < sc->sc_buttons; i++) {
-		DPRINTF("B%d\t%d/%d\n",
-		    i + 1, sc->sc_loc_btn[i].pos, sc->sc_loc_btn[i].size);
+		DPRINTF("B%d\t%d/%d id=%d\n",
+		    i + 1, sc->sc_loc_btn[i].pos,
+		    sc->sc_loc_btn[i].size, sc->sc_iid_btn[i]);
 	}
 	DPRINTF("size=%d, id=%d\n", isize, sc->sc_iid);
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903091525.n29FPlVv030219>