MFp4 //depot/projects/usb@158916

USB mouse patch to address complicated data reporting descriptors.

Reported by:	Boris Kotzev
Submitted by:	Hans Petter Selasky
This commit is contained in:
thompsa 2009-03-09 15:25:46 +00:00
parent 0f54c73393
commit 7739f9f0ee

View File

@ -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;
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;
dx = (sc->sc_flags & UMS_FLAG_X_AXIS) ?
hid_get_data(buf, len, &sc->sc_loc_x) : 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;
dy = (sc->sc_flags & UMS_FLAG_Y_AXIS) ?
-hid_get_data(buf, len, &sc->sc_loc_y) : 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;
dz = (sc->sc_flags & UMS_FLAG_Z_AXIS) ?
-hid_get_data(buf, len, &sc->sc_loc_z) : 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;
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