NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/41737: ums(4) / uhidev(4) doesn't support MS Wireless Laser Mouse 6000 v2.0



>Number:         41737
>Category:       kern
>Synopsis:       ums(4) / uhidev(4) doesn't support MS Wireless Laser Mouse 6000
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 16 02:30:00 +0000 2009
>Originator:     Rafal Boni
>Release:        NetBSD 5.0_STABLE
>Organization:
Wazzat?
>Environment:
System: NetBSD puck 5.0_STABLE NetBSD 5.0_STABLE (GENERIC_DRM) #21: Wed Jul 15 
17:21:41 EDT 2009  
rafal@puck:/extra/amd64/obj-5/sys/arch/amd64/compile/GENERIC_DRM amd64
Architecture: x86_64
Machine: amd64
>Description:
        Plugging a Microsoft Wireless Laser Mouse 6000 (v2.0) into a NetBSD
        5.0 (and I suspect -current as well, though I've not checked there),
        attaches a ums(4) device, and a wsmouse(4) instance to that, but the
        mouse doesn't generate any events, either for motion, buttons, or
        the wheel.

>How-To-Repeat:
        Plug the above mentioned device into a NetBSD 5.0 system.
        # od -c < /dev/wsmouseN

        Hit buttons, move the mouse, scroll the wheel, etc. and notice
        that no data comes out of the wsmouse device.
>Fix:

        Apply the following patch, rebuild kernel, have a working mouse.
        Thanks to plunky@ for feedback and pointer to btms(4), which I
        borrowed some of the wheel / Z axis / pan handling from.

        I don't have a -current system available to try this on right now,
        but will try to do that RSN and check it in if it works there and
        I haven't gotten other feedback...

diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index aa0b005..4f8e7ed 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -105,7 +105,7 @@ USB_ATTACH(uhidev)
        struct uhidev_attach_arg uha;
        device_t dev;
        struct uhidev *csc;
-       int size, nrepid, repid, repsz;
+       int maxinpktsize, size, nrepid, repid, repsz;
        int *repsizes;
        int i;
        void *desc;
@@ -137,6 +137,7 @@ USB_ATTACH(uhidev)
                (void)usbd_set_protocol(iface, 1);
 #endif
 
+       maxinpktsize = 0;
        sc->sc_iep_addr = sc->sc_oep_addr = -1;
        for (i = 0; i < id->bNumEndpoints; i++) {
                ed = usbd_interface2endpoint_descriptor(iface, i);
@@ -158,6 +159,7 @@ USB_ATTACH(uhidev)
 
                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
+                       maxinpktsize = UGETW(ed->wMaxPacketSize);
                        sc->sc_iep_addr = ed->bEndpointAddress;
                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
@@ -262,8 +264,10 @@ nomem:
                aprint_error_dev(self, "no memory\n");
                USB_ATTACH_ERROR_RETURN;
        }
+
+       /* Just request max packet size for the interrupt pipe */
+       sc->sc_isize = maxinpktsize;
        sc->sc_nrepid = nrepid;
-       sc->sc_isize = 0;
 
        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                           USBDEV(sc->sc_dev));
@@ -272,12 +276,8 @@ nomem:
                repsz = hid_report_size(desc, size, hid_input, repid);
                DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz));
                repsizes[repid] = repsz;
-               if (repsz > 0) {
-                       if (repsz > sc->sc_isize)
-                               sc->sc_isize = repsz;
-               }
        }
-       sc->sc_isize += nrepid != 1;    /* space for report ID */
+
        DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize));
 
        uha.parent = sc;
@@ -475,7 +475,7 @@ uhidev_intr(usbd_xfer_handle xfer, usbd_private_handle 
addr, usbd_status status)
                    rep, scd, scd ? scd->sc_state : 0));
        if (!(scd->sc_state & UHIDEV_OPEN))
                return;
-       if (scd->sc_in_rep_size != cc) {
+       if (scd->sc_in_rep_size > cc) {
                printf("%s: bad input length %d != %d\n",
                       USBDEVNAME(sc->sc_dev), scd->sc_in_rep_size, cc);
                return;
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index 88baea2..e1f7144 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -95,6 +95,7 @@ struct ums_softc {
 #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/tilt available */
 
        int nbuttons;
 
@@ -152,7 +153,8 @@ ums_attach(device_t parent, device_t self, void *aux)
        int size;
        void *desc;
        u_int32_t flags, quirks;
-       int i, wheel;
+       int i, hl;
+       struct hid_location *zloc;
        struct hid_location loc_btn;
 
        aprint_naive("\n");
@@ -198,10 +200,16 @@ ums_attach(device_t parent, device_t self, void *aux)
        }
 
        /* Try the wheel first as the Z activator since it's tradition. */
-       wheel = hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP,
-                                                 HUG_WHEEL),
-                          uha->reportid, hid_input, &sc->sc_loc_z, &flags);
-       if (wheel) {
+       hl = hid_locate(desc, 
+                       size, 
+                       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL), 
+                       uha->reportid, 
+                       hid_input, 
+                       &sc->sc_loc_z, 
+                       &flags);
+
+       zloc = &sc->sc_loc_z;
+       if (hl) {
                if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
                        aprint_verbose("\n%s: Wheel report 0x%04x not "
                            "supported\n", USBDEVNAME(sc->sc_hdev.sc_dev),
@@ -211,33 +219,59 @@ ums_attach(device_t parent, device_t self, void *aux)
                        sc->flags |= UMS_Z;
                        /* Wheels need the Z axis reversed. */
                        sc->flags ^= UMS_REVZ;
+                       /* Put Z on the W coordinate */
+                       zloc = &sc->sc_loc_w;
                }
-               /*
-                * We might have both a wheel and Z direction, if so put
-                * put the Z on the W coordinate.
-                */
-               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) {
-                               aprint_verbose("\n%s: Z report 0x%04x not "
-                                   "supported\n",
-                                      USBDEVNAME(sc->sc_hdev.sc_dev), flags);
-                               sc->sc_loc_w.size = 0;  /* Bad Z, ignore */
-                       }
-               }
-        } else if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP,
-                                                     HUG_Z),
-                     uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
+       }
+
+       hl = hid_locate(desc, 
+                       size, 
+                       HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
+                       uha->reportid,
+                       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(desc, 
+                               size, 
+                               HID_USAGE2(HUP_CONSUMER, HUC_AC_PAN), 
+                               uha->reportid,
+                               hid_input,
+                               zloc,
+                               &flags);
+       }
+
+       if (hl) {
                if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
                        aprint_verbose("\n%s: Z report 0x%04x not supported\n",
                               USBDEVNAME(sc->sc_hdev.sc_dev), flags);
-                       sc->sc_loc_z.size = 0;  /* Bad Z coord, ignore it */
+                       zloc->size = 0; /* Bad Z coord, ignore it */
                } else {
-                       sc->flags |= UMS_Z;
+                       if (sc->flags & UMS_Z)
+                               sc->flags |= UMS_W;
+                       else
+                               sc->flags |= UMS_Z;
                }
        }
 
+       /*
+        * The Microsoft Wireless Laser Mouse 6000 v2.0 reports a bad
+        * position for the wheel and wheel tilt controls -- should be
+        * in bytes 3 & 4 of the report.  Fix this if necessary.
+        */
+       if (uha->uaa->vendor == USB_VENDOR_MICROSOFT &&
+           uha->uaa->product == USB_PRODUCT_MICROSOFT_24GHZ_XCVR) {
+               if ((sc->flags & UMS_Z) && sc->sc_loc_z.pos == 0)
+                       sc->sc_loc_z.pos = 24;
+               if ((sc->flags & UMS_W) && sc->sc_loc_w.pos == 0)
+                       sc->sc_loc_w.pos = sc->sc_loc_z.pos + 8;
+       }
 
        /* figure out the number of buttons */
        for (i = 1; i <= MAX_BUTTONS; i++)
@@ -246,9 +280,11 @@ ums_attach(device_t parent, device_t self, void *aux)
                        break;
        sc->nbuttons = i - 1;
 
-       aprint_normal(": %d button%s%s\n",
+       aprint_normal(": %d button%s%s%s%s\n",
            sc->nbuttons, sc->nbuttons == 1 ? "" : "s",
-           sc->flags & UMS_Z ? " and Z dir." : "");
+           sc->flags & UMS_W ? ", W" : "",
+           sc->flags & UMS_Z ? " and Z dir" : "",
+           sc->flags & UMS_W ? "s" : "");
 
        for (i = 1; i <= sc->nbuttons; i++)
                hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
@@ -264,6 +300,9 @@ ums_attach(device_t parent, device_t self, void *aux)
        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));
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index e2b00bf..2c13c33 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1542,6 +1542,7 @@ product MICROSOFT XBOX_DVD_PLAYBACK       0x0284  Xbox 
DVD Movie Playback Kit
 product MICROSOFT XBOX_CONTROLLER_S10  0x0285  Xbox Controller S (1.0)
 product MICROSOFT XBOX_CONTROLLER_HUB  0x0288  Xbox Controller Hub
 product MICROSOFT XBOX_CONTROLLER_S12  0x0289  Xbox Controller S (1.2)
+product MICROSOFT 24GHZ_XCVR           0x071f  2.4GHz Transceiver V2.0
 
 /* Microtech products */
 product MICROTECH SCSIDB25     0x0004  USB-SCSI-DB25
diff --git a/sys/dev/usb/usbdevs.h b/sys/dev/usb/usbdevs.h
index 53372ec..6da5460 100644
--- a/sys/dev/usb/usbdevs.h
+++ b/sys/dev/usb/usbdevs.h
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdevs.h,v 1.515.4.1 2008/11/22 05:12:18 snj Exp $    */
+/*     $NetBSD$        */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -1549,6 +1549,7 @@
 #define        USB_PRODUCT_MICROSOFT_XBOX_CONTROLLER_S10       0x0285          
/* Xbox Controller S (1.0) */
 #define        USB_PRODUCT_MICROSOFT_XBOX_CONTROLLER_HUB       0x0288          
/* Xbox Controller Hub */
 #define        USB_PRODUCT_MICROSOFT_XBOX_CONTROLLER_S12       0x0289          
/* Xbox Controller S (1.2) */
+#define        USB_PRODUCT_MICROSOFT_24GHZ_XCVR        0x071f          /* 
2.4GHz Transceiver V2.0 */
 
 /* Microtech products */
 #define        USB_PRODUCT_MICROTECH_SCSIDB25  0x0004          /* 
USB-SCSI-DB25 */
diff --git a/sys/dev/usb/usbdevs_data.h b/sys/dev/usb/usbdevs_data.h
index 6759cdf..bb2b02b 100644
--- a/sys/dev/usb/usbdevs_data.h
+++ b/sys/dev/usb/usbdevs_data.h
@@ -1,4 +1,4 @@
-/*     $NetBSD: usbdevs_data.h,v 1.516.4.1 2008/11/22 05:12:18 snj Exp $       
*/
+/*     $NetBSD$        */
 
 /*
  * THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT.
@@ -4579,6 +4579,10 @@ const struct usb_product usb_products[] = {
            "Xbox Controller S (1.2)",
        },
        {
+           USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_24GHZ_XCVR,
+           "2.4GHz Transceiver V2.0",
+       },
+       {
            USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25,
            "USB-SCSI-DB25",
        },
@@ -6823,4 +6827,4 @@ const struct usb_product usb_products[] = {
            "Prestige",
        },
 };
-const int usb_nproducts = 1241;
+const int usb_nproducts = 1242;



Home | Main Index | Thread Index | Old Index