Skip to content

Commit

Permalink
usb: dwc3: ep0: fix Data Phase for transfer sizes aligned to wMaxPack…
Browse files Browse the repository at this point in the history
…etSize

According to Section 8.5.3.2 of the USB 2.0 specification,
a USB device must terminate a Data Phase with either a
short packet or a ZLP (if the previous transfer was
a multiple of wMaxPacketSize).

For reference, here's what the USB 2.0 specification, section
8.5.3.2 says:

"
8.5.3.2 Variable-length Data Stage

A control pipe may have a variable-length data phase
in which the host requests more data than is contained
in the specified data structure. When all of the data
structure is returned to the host, the function should
indicate that the Data stage is ended by returning a
packet that is shorter than the MaxPacketSize for the
pipe. If the data structure is an exact multiple of
wMaxPacketSize for the pipe, the function will return
a zero-length packet to indicate the end of the Data
stage.
"

Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Felipe Balbi committed Oct 23, 2014
1 parent 6856d30 commit 36f84ff
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,

dwc3_ep0_stall_and_restart(dwc);
} else {
/*
* handle the case where we have to send a zero packet. This
* seems to be case when req.length > maxpacket. Could it be?
*/
if (r)
dwc3_gadget_giveback(ep0, r, 0);
dwc3_gadget_giveback(ep0, r, 0);

if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
ur->length && ur->zero) {
int ret;

dwc->ep0_next_event = DWC3_EP0_COMPLETE;

ret = dwc3_ep0_start_trans(dwc, epnum,
dwc->ctrl_req_addr, 0,
DWC3_TRBCTL_CONTROL_DATA);
WARN_ON(ret < 0);
}
}
}

Expand Down

0 comments on commit 36f84ff

Please sign in to comment.