diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2018-09-30 14:54:59 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2018-09-30 22:32:19 -0400 |
commit | 92aea93500c7938c4744501ce58f62a502efa690 (patch) | |
tree | 34557baf6f6646f89fb77f9f0fb03f5f206de08c /src/generic/usb_cdc.c | |
parent | be1effebc30b86c2a372a978c22ad5018b373f9d (diff) | |
download | kutter-92aea93500c7938c4744501ce58f62a502efa690.tar.gz kutter-92aea93500c7938c4744501ce58f62a502efa690.tar.xz kutter-92aea93500c7938c4744501ce58f62a502efa690.zip |
usb_cdc: Fix handling of zero-length-packets
A zero length packet should only be sent at the end of a transmission
if the host is expecting more data.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/generic/usb_cdc.c')
-rw-r--r-- | src/generic/usb_cdc.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/src/generic/usb_cdc.c b/src/generic/usb_cdc.c index 05f1bf58..1e12f6a7 100644 --- a/src/generic/usb_cdc.c +++ b/src/generic/usb_cdc.c @@ -290,7 +290,7 @@ static const struct descriptor_s { // State tracking enum { - UX_READ = 1<<0, UX_SEND = 1<<1 + UX_READ = 1<<0, UX_SEND = 1<<1, UX_SEND_ZLP = 1<<2 }; static void *usb_xfer_data; @@ -321,13 +321,16 @@ usb_do_xfer(void *data, uint_fast8_t size, uint_fast8_t flags) // Success data += xs; size -= xs; - if (!size && xs < USB_CDC_EP0_SIZE) { - // Transfer completed successfully + if (!size) { + // Entire transfer completed successfully if (flags & UX_READ) { // Send status packet at end of read flags = UX_SEND; continue; } + if (xs == USB_CDC_EP0_SIZE && flags & UX_SEND_ZLP) + // Must send zero-length-packet + continue; usb_xfer_flags = 0; usb_notify_ep0(); return; @@ -356,10 +359,12 @@ usb_req_get_descriptor(struct usb_ctrlrequest *req) const struct descriptor_s *d = &cdc_descriptors[i]; if (READP(d->wValue) == req->wValue && READP(d->wIndex) == req->wIndex) { - uint_fast8_t size = READP(d->size); + uint_fast8_t size = READP(d->size), flags = UX_SEND; if (size > req->wLength) size = req->wLength; - usb_do_xfer((void*)READP(d->desc), size, UX_SEND); + else if (size < req->wLength) + flags |= UX_SEND_ZLP; + usb_do_xfer((void*)READP(d->desc), size, flags); return; } } |