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