On Wed, 21 Feb 2007, Max Asbock wrote:
> I am looking at a UHCI usb device which has endpoints of type interrupt.
> A userspace daemon attempts to submit an urb of type bulk to the device.
> This fails and -EINVAl is returned.
> Is it legal to send a bulk request to an interrupt endpoint?
> proc_do_submiturb doesn't complain about this case.
You have found a bug in proc_do_submiturb(). It should indeed be legal to
submit a bulk request to an interrupt endpoint.
> The EINVAL comes from uhci_submit_interrupt because urb->interval is not
> initialized for a bulk request on an interrupt endpoint.
>
> I don't really know anything about USB, so I hope this makes some sense.
> The device and userspace daemon worked with earlier kernels. Maybe just
> by accident?
It used to be that uhci-hcd did not check for illegal intervals in
interrupt URBs. Now it does; that's why the behavior has changed.
I believe the patch below will fix your problem. Please let us know if it
works.
Alan Stern
Index: usb-2.6/drivers/usb/core/devio.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/devio.c
+++ usb-2.6/drivers/usb/core/devio.c
@@ -912,7 +912,7 @@ static int proc_do_submiturb(struct dev_
struct async *as;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
- int ret, interval = 0, ifnum = -1;
+ int ret, ifnum = -1;
if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
URB_NO_FSBR|URB_ZERO_PACKET))
@@ -992,7 +992,6 @@ static int proc_do_submiturb(struct dev_
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_ISOC)
return -EINVAL;
- interval = 1 << min (15, ep->desc.bInterval - 1);
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
uurb->number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
@@ -1021,10 +1020,6 @@ static int proc_do_submiturb(struct dev_
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT)
return -EINVAL;
- if (ps->dev->speed == USB_SPEED_HIGH)
- interval = 1 << min (15, ep->desc.bInterval - 1);
- else
- interval = ep->desc.bInterval;
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE :
VERIFY_READ, uurb->buffer, uurb->buffer_length))
@@ -1053,7 +1048,11 @@ static int proc_do_submiturb(struct dev_
as->urb->setup_packet = (unsigned char*)dr;
as->urb->start_frame = uurb->start_frame;
as->urb->number_of_packets = uurb->number_of_packets;
- as->urb->interval = interval;
+ if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
+ ps->dev->speed == USB_SPEED_HIGH)
+ as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
+ else
+ as->urb->interval = ep->desc.bInterval;
as->urb->context = as;
as->urb->complete = async_completed;
for (totlen = u = 0; u < uurb->number_of_packets; u++) {
Index: usb-2.6/drivers/usb/core/message.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/message.c
+++ usb-2.6/drivers/usb/core/message.c
@@ -221,10 +221,15 @@ int usb_bulk_msg(struct usb_device *usb_
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT) {
+ int interval;
+
+ if (usb_dev->speed == USB_SPEED_HIGH)
+ interval = 1 << min(15, ep->desc.bInterval - 1);
+ else
+ interval = ep->desc.bInterval;
pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
usb_fill_int_urb(urb, usb_dev, pipe, data, len,
- usb_api_blocking_completion, NULL,
- ep->desc.bInterval);
+ usb_api_blocking_completion, NULL, interval);
} else
usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
usb_api_blocking_completion, NULL);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel