Pavlik,

Here is a small patch relative to 2.6.4-rc2 that does three things:

 - In hid_init_reports(), establish a idle-period of 1ms before
   initiating the Get_Request() requests.  It appears there are buggy
   keyboards (such as the BTC keyboard) where setting the idle period
   affects not just the Interrupt In pipe, but the control pipe's
   Get_Requests as well.  I _believe_ this should be harmless to
   properly operating HID devices, but I can't know for sure.

 - Enhance the "submitting ctrl urb" debug message with some additional,
   useful info

 - Replace hard-coded 0x0a with manifest constant "HID_REQ_SET_IDLE" to
   improve radability.

Without the first change, connecting the BTC keyboard to a host caused
the HID driver to timeout after a longish period of time.  Actually,
the exact behavior seemed to depend on a number of things:

 - After freshly booting the machine (which is an Itanium 2 box),
   loading hid.ko would cause a timeout on interface 0 (keyboard) and
   would function fine on interface 1 (power-control buttons).

 - After removing and re-inserting hid.ko, the timeouts happened
   on both interfaces (presumably because the previous loading
   of hid.ko established an infinite idle period).

I was able to get rid of the timeout on a freshly booted machine by
switching the keyboard interface to protocol 1 before doing the
Get_Reportss, but the timeouts came back after unloading/reloading
hid.ko, so that alone doesn't seem sufficient (plus I couldn't find a
good way to determine whether an interface is a keyboard supporting
the boot protocol...).

The other two changes are only cosmetic, but I think they're useful.

One question: isn't HID supposed to switch to protocol 1 for keyboards
supporting the boot protocol?  My reading of the specs is that, yes,
it should, but I couldn't find any place in the driver where this is
done.

Anyhow, if the patch looks good, please apply.

        --david

===== drivers/usb/input/hid-core.c 1.72 vs edited =====
--- 1.72/drivers/usb/input/hid-core.c   Wed Jan 28 23:12:59 2004
+++ edited/drivers/usb/input/hid-core.c Tue Mar  9 21:19:16 2004
@@ -1086,7 +1086,9 @@
        hid->cr->wIndex = cpu_to_le16(hid->ifnum);
        hid->cr->wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);
 
-       dbg("submitting ctrl urb");
+       dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+           hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+           hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
 
        if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
                err("usb_submit_urb(ctrl) failed");
@@ -1265,6 +1267,23 @@
        int len;
        int err, ret;
 
+       /*
+        * The Set_Idle request is supposed to affect only the
+        * "Interrupt In" pipe. Unfortunately, buggy devices such as
+        * the BTC keyboard (ID 046e:5303) the request also affects
+        * Get_Report requests on the control pipe.  In the worst
+        * case, if the device was put on idle for an indefinite
+        * amount of time (as we do below) and there are no input
+        * events to report, the Get_Report requests will just hang
+        * until we get a USB timeout.  To avoid this, we temporarily
+        * establish a minimal idle time of 1ms.  This shouldn't hurt
+        * bugfree devices and will cause a worst-case extra delay of
+        * 1ms for buggy ones.
+        */
+       usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
+                       HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (1 << 
8),
+                       hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+
        report_enum = hid->report_enum + HID_INPUT_REPORT;
        list = report_enum->report_list.next;
        while (list != &report_enum->report_list) {
@@ -1301,7 +1320,7 @@
                if (len > hid->urbin->transfer_buffer_length)
                        hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? 
len : HID_BUFFER_SIZE;
                usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-                       0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
+                       HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 
report->id,
                        hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
                list = list->next;
        }


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to