On Sun, Dec 14, 2003 at 04:40:54PM +0000, Johann Deneux wrote:
> I've had bug reports from users trying to use hid with force feed back
> enabled for logitech devices (kernel 2.6.0-test9). The device causing
> trouble is the cordless rumble pad. It is a low-speed device, and
> stubbornly refuses to rumble. It works fine as an input-only device,
> however.
>
> hid-lgff.c, which implements force feedback for this device, needs to
> submit output reports to the device. hid_submit_out submits an output
> bulk urb to the device. ohci-hcd seems fine with that (at least it used
> to, back in 2.4.x times), but uhci-hcd is not.
>
> I commented out two lines in uhci-hcd to force it to accept to submit
> bulk out urbs to low-speed devices:
>
> static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb
> *urb, struc
> t urb *eurb)
> {
> int ret;
>
> /* Can't have low speed bulk transfers */
> /* if (urb->dev->speed == USB_SPEED_LOW)
> return -EINVAL;*/
>
>
> It made by pad rumble, so this quick dirty fix does the job.
> Now, I don't know what the clean fix would be. Maybe change hid to
> submit one-shot-interrupt out urbs when dealing with low-speed devices,
> or just lift the restriction in uhci (I guess there are reasons for this
> restriction, though).
>
> PS: when replying, please include me. I am not subscribed to the list.
Seems that the real problem is in hid-core.c:
endpoint = &interface->endpoint[n].desc;
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt
endpoint */
continue;
if (endpoint->bEndpointAddress & USB_DIR_IN) {
if (hid->urbin)
continue;
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, 0,
hid_irq_in, hid, endpoint->bInterval);
hid->urbin->transfer_dma = hid->inbuf_dma;
hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
} else {
if (hid->urbout)
continue;
if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress);
usb_fill_bulk_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
hid_irq_out, hid);
hid->urbout->transfer_dma = hid->outbuf_dma;
hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
Notice that for the input endpoint it correctly uses usb_rcvintpipe()
and usb_fill_int_urb(), but for the output endpoint usb_sndbulkpipe()
and usb_fill_bulk_urb() are used (even though it is really an
interrupt endpoint). How could this work?
So it is the HID core which must be fixed. Unfortunately, I don't
have any HID device which would have an interrupt out endpoint...
pgp00000.pgp
Description: PGP signature
