*      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);
 }