diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2025-02-06 01:32:05 -0500 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2025-02-15 18:22:45 -0500 |
commit | bf5c4daf869c0c3c44d4dd786e71e8813fe28b12 (patch) | |
tree | 82b59c55c67e92258d945b5d5d232437b4b72f15 | |
parent | ec56167032253b19bed362b25d3696f5d810633b (diff) | |
download | kutter-bf5c4daf869c0c3c44d4dd786e71e8813fe28b12.tar.gz kutter-bf5c4daf869c0c3c44d4dd786e71e8813fe28b12.tar.xz kutter-bf5c4daf869c0c3c44d4dd786e71e8813fe28b12.zip |
usb_cdc: Avoid ending a transmission with a max size usb packet
It seems the Linux kernel will consider a maximum size usb packet to
be a transaction that will continue into the next usb packet. It will
thus hold on to the traffic from the first packet until it gets the
next packet. However, if the mcu has no further data to send after
the first packet then the data could get delayed for an extended
period of time.
To avoid this, check for transmissions that could end on a maximum
sized packet and send that data in two packets instead. This avoids
this unusual corner case.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r-- | src/generic/usb_cdc.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/src/generic/usb_cdc.c b/src/generic/usb_cdc.c index 143c213f..961c6330 100644 --- a/src/generic/usb_cdc.c +++ b/src/generic/usb_cdc.c @@ -44,11 +44,13 @@ usb_bulk_in_task(void) { if (!sched_check_wake(&usb_bulk_in_wake)) return; - uint_fast8_t tpos = transmit_pos; + uint_fast8_t tpos = transmit_pos, max_tpos = tpos; if (!tpos) return; - uint_fast8_t max_tpos = (tpos > USB_CDC_EP_BULK_IN_SIZE - ? USB_CDC_EP_BULK_IN_SIZE : tpos); + if (max_tpos > USB_CDC_EP_BULK_IN_SIZE) + max_tpos = USB_CDC_EP_BULK_IN_SIZE; + else if (max_tpos == USB_CDC_EP_BULK_IN_SIZE) + max_tpos = USB_CDC_EP_BULK_IN_SIZE-1; // Avoid zero-length-packets int_fast8_t ret = usb_send_bulk_in(transmit_buf, max_tpos); if (ret <= 0) return; |