aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/usbip/stub_rx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 11:41:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-06 11:41:17 -0700
commitcc41f5cede3c63836d1c0958204630b07f5b5ee7 (patch)
treedfd94451c919b5185d8a01fd3e5a90244fb0de1c /drivers/staging/usbip/stub_rx.c
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6 (diff)
parentStaging: wlan-ng: Update prism2_set_tx_power() to use mBm (diff)
downloadlinux-dev-cc41f5cede3c63836d1c0958204630b07f5b5ee7.tar.xz
linux-dev-cc41f5cede3c63836d1c0958204630b07f5b5ee7.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (524 commits) Staging: wlan-ng: Update prism2_set_tx_power() to use mBm Staging: ti-st: update TODO Staging: wlags49_h2: use common PCI_VENDOR/DEVICE_ID name format Staging: comedi : fix brace coding style issue in wwrap.c Staging: quatech_usb2: remove unused qt2_box_flush function Staging: slicoss: Remove net_device_stats from the driver's private staging: rtl8192su: check whether requests succeeded staging: panel: fix error path staging: otus: check kmalloc() return value staging: octeon: check request_irq() return value Staging: wlan-ng: remove typedef in p80211hdr.h Staging: wlan-ng: fix checkpatch issues in headers. Staging: wlan-ng: remove typedef in p80211ioctl.h Staging: wlan-ng: fix style issues in p80211conv.h Staging: wlan-ng: fix style issues for p80211hdr.h staging: vt6656: removed NTSTATUS definition staging: vt6656: simplified tests involving both multi/broad-casts Staging: vt6655: replace BOOL with in kernel bool Staging: vt6655: replace FALSE with in kernel false Staging: vt6655: replace TRUE with in kernel true ...
Diffstat (limited to 'drivers/staging/usbip/stub_rx.c')
-rw-r--r--drivers/staging/usbip/stub_rx.c101
1 files changed, 59 insertions, 42 deletions
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index 5972ae70e381..3de6fd2539dc 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -362,54 +362,16 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
return priv;
}
-
-static struct usb_host_endpoint *get_ep_from_epnum(struct usb_device *udev,
- int epnum0)
-{
- struct usb_host_config *config;
- int i = 0, j = 0;
- struct usb_host_endpoint *ep = NULL;
- int epnum;
- int found = 0;
-
- if (epnum0 == 0)
- return &udev->ep0;
-
- config = udev->actconfig;
- if (!config)
- return NULL;
-
- for (i = 0; i < config->desc.bNumInterfaces; i++) {
- struct usb_host_interface *setting;
-
- setting = config->interface[i]->cur_altsetting;
-
- for (j = 0; j < setting->desc.bNumEndpoints; j++) {
- ep = &setting->endpoint[j];
- epnum = (ep->desc.bEndpointAddress & 0x7f);
-
- if (epnum == epnum0) {
- /* usbip_uinfo("found epnum %d\n", epnum0);*/
- found = 1;
- break;
- }
- }
- }
-
- if (found)
- return ep;
- else
- return NULL;
-}
-
-
static int get_pipe(struct stub_device *sdev, int epnum, int dir)
{
struct usb_device *udev = interface_to_usbdev(sdev->interface);
struct usb_host_endpoint *ep;
struct usb_endpoint_descriptor *epd = NULL;
- ep = get_ep_from_epnum(udev, epnum);
+ if (dir == USBIP_DIR_IN)
+ ep = udev->ep_in[epnum & 0x7f];
+ else
+ ep = udev->ep_out[epnum & 0x7f];
if (!ep) {
dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
epnum);
@@ -462,6 +424,60 @@ static int get_pipe(struct stub_device *sdev, int epnum, int dir)
return 0;
}
+static void masking_bogus_flags(struct urb *urb)
+{
+ int xfertype;
+ struct usb_device *dev;
+ struct usb_host_endpoint *ep;
+ int is_out;
+ unsigned int allowed;
+
+ if (!urb || urb->hcpriv || !urb->complete)
+ return;
+ dev = urb->dev;
+ if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
+ return;
+
+ ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (!ep)
+ return;
+
+ xfertype = usb_endpoint_type(&ep->desc);
+ if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
+ struct usb_ctrlrequest *setup =
+ (struct usb_ctrlrequest *) urb->setup_packet;
+
+ if (!setup)
+ return;
+ is_out = !(setup->bRequestType & USB_DIR_IN) ||
+ !setup->wLength;
+ } else {
+ is_out = usb_endpoint_dir_out(&ep->desc);
+ }
+
+ /* enforce simple/standard policy */
+ allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT |
+ URB_DIR_MASK | URB_FREE_BUFFER);
+ switch (xfertype) {
+ case USB_ENDPOINT_XFER_BULK:
+ if (is_out)
+ allowed |= URB_ZERO_PACKET;
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_CONTROL:
+ allowed |= URB_NO_FSBR; /* only affects UHCI */
+ /* FALLTHROUGH */
+ default: /* all non-iso endpoints */
+ if (!is_out)
+ allowed |= URB_SHORT_NOT_OK;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ allowed |= URB_ISO_ASAP;
+ break;
+ }
+ urb->transfer_flags &= allowed;
+}
+
static void stub_recv_cmd_submit(struct stub_device *sdev,
struct usbip_header *pdu)
{
@@ -528,6 +544,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
/* no need to submit an intercepted request, but harmless? */
tweak_special_requests(priv->urb);
+ masking_bogus_flags(priv->urb);
/* urb is now ready to submit */
ret = usb_submit_urb(priv->urb, GFP_KERNEL);