aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/devio.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 6ce77b33da61..263dd2f309fb 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1434,10 +1434,13 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1434 struct async *as = NULL; 1434 struct async *as = NULL;
1435 struct usb_ctrlrequest *dr = NULL; 1435 struct usb_ctrlrequest *dr = NULL;
1436 unsigned int u, totlen, isofrmlen; 1436 unsigned int u, totlen, isofrmlen;
1437 int i, ret, is_in, num_sgs = 0, ifnum = -1; 1437 int i, ret, num_sgs = 0, ifnum = -1;
1438 int number_of_packets = 0; 1438 int number_of_packets = 0;
1439 unsigned int stream_id = 0; 1439 unsigned int stream_id = 0;
1440 void *buf; 1440 void *buf;
1441 bool is_in;
1442 bool allow_short = false;
1443 bool allow_zero = false;
1441 unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK | 1444 unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK |
1442 USBDEVFS_URB_BULK_CONTINUATION | 1445 USBDEVFS_URB_BULK_CONTINUATION |
1443 USBDEVFS_URB_NO_FSBR | 1446 USBDEVFS_URB_NO_FSBR |
@@ -1471,6 +1474,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1471 u = 0; 1474 u = 0;
1472 switch (uurb->type) { 1475 switch (uurb->type) {
1473 case USBDEVFS_URB_TYPE_CONTROL: 1476 case USBDEVFS_URB_TYPE_CONTROL:
1477 if (is_in)
1478 allow_short = true;
1474 if (!usb_endpoint_xfer_control(&ep->desc)) 1479 if (!usb_endpoint_xfer_control(&ep->desc))
1475 return -EINVAL; 1480 return -EINVAL;
1476 /* min 8 byte setup packet */ 1481 /* min 8 byte setup packet */
@@ -1511,6 +1516,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1511 break; 1516 break;
1512 1517
1513 case USBDEVFS_URB_TYPE_BULK: 1518 case USBDEVFS_URB_TYPE_BULK:
1519 if (!is_in)
1520 allow_zero = true;
1521 else
1522 allow_short = true;
1514 switch (usb_endpoint_type(&ep->desc)) { 1523 switch (usb_endpoint_type(&ep->desc)) {
1515 case USB_ENDPOINT_XFER_CONTROL: 1524 case USB_ENDPOINT_XFER_CONTROL:
1516 case USB_ENDPOINT_XFER_ISOC: 1525 case USB_ENDPOINT_XFER_ISOC:
@@ -1531,6 +1540,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1531 if (!usb_endpoint_xfer_int(&ep->desc)) 1540 if (!usb_endpoint_xfer_int(&ep->desc))
1532 return -EINVAL; 1541 return -EINVAL;
1533 interrupt_urb: 1542 interrupt_urb:
1543 if (!is_in)
1544 allow_zero = true;
1545 else
1546 allow_short = true;
1534 break; 1547 break;
1535 1548
1536 case USBDEVFS_URB_TYPE_ISO: 1549 case USBDEVFS_URB_TYPE_ISO:
@@ -1676,9 +1689,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
1676 u = (is_in ? URB_DIR_IN : URB_DIR_OUT); 1689 u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
1677 if (uurb->flags & USBDEVFS_URB_ISO_ASAP) 1690 if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
1678 u |= URB_ISO_ASAP; 1691 u |= URB_ISO_ASAP;
1679 if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in) 1692 if (allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
1680 u |= URB_SHORT_NOT_OK; 1693 u |= URB_SHORT_NOT_OK;
1681 if (uurb->flags & USBDEVFS_URB_ZERO_PACKET) 1694 if (allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET)
1682 u |= URB_ZERO_PACKET; 1695 u |= URB_ZERO_PACKET;
1683 if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT) 1696 if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
1684 u |= URB_NO_INTERRUPT; 1697 u |= URB_NO_INTERRUPT;