From d09d36a91c70cb3cc609d693bf6a7e7a266ff9e6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 26 Sep 2005 16:22:45 -0400 Subject: [PATCH] [PATCH] USB: usb_bulk_message() handles interrupts endpoints Because there is no bulk_interrupt_message() routine and no USBDEVFS_INTERRUPT ioctl, people have been forced to abuse the usb_bulk_message() routine and USBDEVFS_BULK by using them for interrupt transfers as well as bulk transfers. This patch (as567) formalizes this practice and adds code to usb_bulk_message() for detecting when the target is really an interrupt endpoint. If it is, the routine submits an interrupt URB (using the default interval) instead of a bulk URB. In theory this should help HCDs that don't like it when people try to mix transfer types, queuing both periodic and non-periodic types for the same endpoint. Not fully tested -- I don't have any programs that use USBDEVFS_BULK for interrupt transfers -- but it compiles okay and normal bulk messages work as well as before. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman drivers/usb/core/message.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) --- drivers/usb/core/message.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index ebf59ea..574d0d4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -187,21 +187,37 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u * If a thread in your driver uses this call, make sure your disconnect() * method can wait for it to complete. Since you don't have a handle on * the URB used, you can't cancel the request. + * + * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT + * ioctl, users are forced to abuse this routine by using it to submit + * URBs for interrupt endpoints. We will take the liberty of creating + * an interrupt URB (with the default interval) if the target is an + * interrupt endpoint. */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) { struct urb *urb; + struct usb_host_endpoint *ep; - if (len < 0) + ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out) + [usb_pipeendpoint(pipe)]; + if (!ep || len < 0) return -EINVAL; - urb=usb_alloc_urb(0, GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; - usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, - usb_api_blocking_completion, NULL); + if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT) { + 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); + } else + usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, + usb_api_blocking_completion, NULL); return usb_start_wait_urb(urb, timeout, actual_length); } -- 2.7.4