diff options
| author | Alan Stern <stern@rowland.harvard.edu> | 2005-09-26 16:22:45 -0400 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 16:47:41 -0700 | 
| commit | d09d36a91c70cb3cc609d693bf6a7e7a266ff9e6 (patch) | |
| tree | 4a41ade8dc775ea6dc9154bc4fe006f75557f579 /drivers/usb/core/message.c | |
| parent | b13296c6617f22e8c0174a7af32780617db0e680 (diff) | |
[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 <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
 drivers/usb/core/message.c |   24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)
Diffstat (limited to 'drivers/usb/core/message.c')
| -rw-r--r-- | drivers/usb/core/message.c | 24 | 
1 files changed, 20 insertions, 4 deletions
| diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index ebf59ea9926..574d0d4b340 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);  } | 
