Commit 775cd490 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: usb gadget drivers should be stricter about ZLPs

Some USB device controllers make it easy to handle all the various ways
hosts interpret the USB spec about when control-IN transfers need to send
a ZLP ... they can just send one if the host asks, or start the status
stage whenever the host thinks it's time.  Other controllers make it hard
to be forgiving in those cases.

This patch updates all the gadget drivers to explicitly set the req->zero
flag to reflect whether the USB spec says a ZLP "must" be sent by the
device.  "Forgiving" drivers won't notice the change, but the others need
to see this information passed down from the gadget driver.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 9475c0b7
...@@ -1597,6 +1597,8 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1597,6 +1597,8 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* respond with data transfer before status phase? */ /* respond with data transfer before status phase? */
if (value >= 0) { if (value >= 0) {
req->length = value; req->length = value;
req->zero = value < ctrl->wLength
&& (value % gadget->ep0->maxpacket) == 0;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) { if (value < 0) {
DEBUG (dev, "ep_queue --> %d\n", value); DEBUG (dev, "ep_queue --> %d\n", value);
......
...@@ -1465,6 +1465,8 @@ static int fsg_setup(struct usb_gadget *gadget, ...@@ -1465,6 +1465,8 @@ static int fsg_setup(struct usb_gadget *gadget,
/* Respond with data/status or defer until later? */ /* Respond with data/status or defer until later? */
if (rc >= 0 && rc != DELAYED_STATUS) { if (rc >= 0 && rc != DELAYED_STATUS) {
fsg->ep0req->length = rc; fsg->ep0req->length = rc;
fsg->ep0req->zero = rc < ctrl->wLength
&& (rc % gadget->ep0->maxpacket) == 0;
fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
"ep0-in" : "ep0-out"); "ep0-in" : "ep0-out");
rc = ep0_queue(fsg); rc = ep0_queue(fsg);
......
...@@ -1320,6 +1320,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1320,6 +1320,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* proceed with data transfer and status phases? */ /* proceed with data transfer and status phases? */
if (value >= 0 && dev->state != STATE_SETUP) { if (value >= 0 && dev->state != STATE_SETUP) {
req->length = value; req->length = value;
req->zero = value < ctrl->wLength
&& (value % gadget->ep0->maxpacket) == 0;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) { if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value); DBG (dev, "ep_queue --> %d\n", value);
......
...@@ -1573,6 +1573,8 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr ...@@ -1573,6 +1573,8 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr
/* respond with data transfer before status phase? */ /* respond with data transfer before status phase? */
if (ret >= 0) { if (ret >= 0) {
req->length = ret; req->length = ret;
req->zero = ret < ctrl->wLength
&& (ret % gadget->ep0->maxpacket) == 0;
ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR printk(KERN_ERR
......
...@@ -1037,6 +1037,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1037,6 +1037,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* respond with data transfer before status phase? */ /* respond with data transfer before status phase? */
if (value >= 0) { if (value >= 0) {
req->length = value; req->length = value;
req->zero = value < ctrl->wLength
&& (value % gadget->ep0->maxpacket) == 0;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
if (value < 0) { if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value); DBG (dev, "ep_queue --> %d\n", value);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment