summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-10-01 09:59:48 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2018-10-02 08:53:12 +0200
commit0d9869010cbd727aa0ab48fbad0259b6590094b4 (patch)
treef5472ffb4d731ef935c2c32c589bfe3637a62c45 /drivers
parentd5d470b7612899d7419b2b5c9dcc8eabcce51773 (diff)
downloadbarebox-0d9869010cbd727aa0ab48fbad0259b6590094b4.tar.gz
barebox-0d9869010cbd727aa0ab48fbad0259b6590094b4.tar.xz
usb: gadget: fastboot: fix downloading files of wMaxPacketSize bytes
File transfers with sizes of exact multiples of wMaxPacketSize up to EP_BUFFER_SIZE do not work. For a typical scenario that would be files of 512, 1024 ... 3584 bytes. This happens because we unconditionally put EP_BUFFER_SIZE into the initial request length. For non wMaxPacketSize aligned lengths this works well because the transfer is completed with a short packet. For wMaxPacketSize aligned lengths there is no short packet though, so the transfer never completes. Instead we have to put the file size into the initial request length. Some controllers like the DWC3 do not work when the request length is not aligned to wMaxPacketSize, so we align up to wMaxPacketSize like done in U-Boot. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Reported-by: Gavin Schenk <g.schenk@eckelmann.de> Tested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/f_fastboot.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 74fb524c1c..2170dd45fb 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -614,6 +614,16 @@ static void cb_getvar(struct f_fastboot *f_fb, const char *cmd)
fastboot_tx_print(f_fb, "OKAY");
}
+static int rx_bytes_expected(struct f_fastboot *f_fb)
+{
+ int remaining = f_fb->download_size - f_fb->download_bytes;
+
+ if (remaining >= EP_BUFFER_SIZE)
+ return EP_BUFFER_SIZE;
+
+ return ALIGN(remaining, f_fb->out_ep->maxpacket);
+}
+
static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
{
struct f_fastboot *f_fb = req->context;
@@ -637,9 +647,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
f_fb->download_bytes += req->actual;
- req->length = f_fb->download_size - f_fb->download_bytes;
- if (req->length > EP_BUFFER_SIZE)
- req->length = EP_BUFFER_SIZE;
+ req->length = rx_bytes_expected(f_fb);
show_progress(f_fb->download_bytes);
@@ -692,9 +700,7 @@ static void cb_download(struct f_fastboot *f_fb, const char *cmd)
struct usb_ep *ep = f_fb->out_ep;
fastboot_tx_print(f_fb, "DATA%08x", f_fb->download_size);
req->complete = rx_handler_dl_image;
- req->length = EP_BUFFER_SIZE;
- if (req->length < ep->maxpacket)
- req->length = ep->maxpacket;
+ req->length = rx_bytes_expected(f_fb);
}
}