aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-09-26 16:22:45 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:41 -0400
commitd09d36a91c70cb3cc609d693bf6a7e7a266ff9e6 (patch)
tree4a41ade8dc775ea6dc9154bc4fe006f75557f579
parentb13296c6617f22e8c0174a7af32780617db0e680 (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(-)
-rw-r--r--drivers/usb/core/message.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index ebf59ea99263..574d0d4b3401 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
187 * If a thread in your driver uses this call, make sure your disconnect() 187 * If a thread in your driver uses this call, make sure your disconnect()
188 * method can wait for it to complete. Since you don't have a handle on 188 * method can wait for it to complete. Since you don't have a handle on
189 * the URB used, you can't cancel the request. 189 * the URB used, you can't cancel the request.
190 *
191 * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
192 * ioctl, users are forced to abuse this routine by using it to submit
193 * URBs for interrupt endpoints. We will take the liberty of creating
194 * an interrupt URB (with the default interval) if the target is an
195 * interrupt endpoint.
190 */ 196 */
191int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, 197int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
192 void *data, int len, int *actual_length, int timeout) 198 void *data, int len, int *actual_length, int timeout)
193{ 199{
194 struct urb *urb; 200 struct urb *urb;
201 struct usb_host_endpoint *ep;
195 202
196 if (len < 0) 203 ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
204 [usb_pipeendpoint(pipe)];
205 if (!ep || len < 0)
197 return -EINVAL; 206 return -EINVAL;
198 207
199 urb=usb_alloc_urb(0, GFP_KERNEL); 208 urb = usb_alloc_urb(0, GFP_KERNEL);
200 if (!urb) 209 if (!urb)
201 return -ENOMEM; 210 return -ENOMEM;
202 211
203 usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, 212 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
204 usb_api_blocking_completion, NULL); 213 USB_ENDPOINT_XFER_INT) {
214 pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
215 usb_fill_int_urb(urb, usb_dev, pipe, data, len,
216 usb_api_blocking_completion, NULL,
217 ep->desc.bInterval);
218 } else
219 usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
220 usb_api_blocking_completion, NULL);
205 221
206 return usb_start_wait_urb(urb, timeout, actual_length); 222 return usb_start_wait_urb(urb, timeout, actual_length);
207} 223}