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>
This commit is contained in:
Kevin O'Connor 2018-09-30 14:54:59 -04:00
parent be1effebc3
commit 92aea93500
1 changed files with 10 additions and 5 deletions

View File

@ -290,7 +290,7 @@ static const struct descriptor_s {
// State tracking // State tracking
enum { 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; static void *usb_xfer_data;
@ -321,13 +321,16 @@ usb_do_xfer(void *data, uint_fast8_t size, uint_fast8_t flags)
// Success // Success
data += xs; data += xs;
size -= xs; size -= xs;
if (!size && xs < USB_CDC_EP0_SIZE) { if (!size) {
// Transfer completed successfully // Entire transfer completed successfully
if (flags & UX_READ) { if (flags & UX_READ) {
// Send status packet at end of read // Send status packet at end of read
flags = UX_SEND; flags = UX_SEND;
continue; continue;
} }
if (xs == USB_CDC_EP0_SIZE && flags & UX_SEND_ZLP)
// Must send zero-length-packet
continue;
usb_xfer_flags = 0; usb_xfer_flags = 0;
usb_notify_ep0(); usb_notify_ep0();
return; return;
@ -356,10 +359,12 @@ usb_req_get_descriptor(struct usb_ctrlrequest *req)
const struct descriptor_s *d = &cdc_descriptors[i]; const struct descriptor_s *d = &cdc_descriptors[i];
if (READP(d->wValue) == req->wValue if (READP(d->wValue) == req->wValue
&& READP(d->wIndex) == req->wIndex) { && 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) if (size > req->wLength)
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; return;
} }
} }