From c0d442e9c3ed9f63237d46015179f109993a21b0 Mon Sep 17 00:00:00 2001 From: Chew Zeh Yang Date: Mon, 30 Sep 2024 17:14:56 +0800 Subject: [PATCH] usbd: device_next: cdc: add option to enable short packet terminate For usbser.sys driver, which is the default USB host driver for CDC devices in windows, it is expected that USB device always indicate completion of transmission by short packet. In case where the last packet length is multiple of max packet size of the BULK IN endpoint, the USB device shall indicate completion of transmission by sending a zero length packet. This commit adds an option to usbd_cdc_acm to enable the enforcement of zero length packet mentioned above, ensuring that condition of short packet terminate is fulfilled. Signed-off-by: Chew Zeh Yang --- subsys/usb/device_next/class/Kconfig.cdc_acm | 10 ++++++++++ subsys/usb/device_next/class/usbd_cdc_acm.c | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/subsys/usb/device_next/class/Kconfig.cdc_acm b/subsys/usb/device_next/class/Kconfig.cdc_acm index 997ded105f4eb3..d78132c9d3f41f 100644 --- a/subsys/usb/device_next/class/Kconfig.cdc_acm +++ b/subsys/usb/device_next/class/Kconfig.cdc_acm @@ -21,6 +21,16 @@ config USBD_CDC_ACM_STACK_SIZE help USB CDC ACM workqueue stack size. +config USBD_CDC_ACM_ENSURE_SHORT_PKT_FOR_LAST_TX_PKT + bool "USB CDC ACM transmission always end with short packet" + default n + help + If the length of CDC ACM TX payload to be sent to USB Host + is in multiple of max-packet-size of the BULK-IN endpoint, + a Zero-Length Packet will be sent followig the last packet + of the payload, to ensure short packet termination for the + BULK-IN endpoint. + module = USBD_CDC_ACM module-str = usbd cdc_acm default-count = 1 diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index eb0abb803cee3d..f851e870a2042b 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -549,6 +549,12 @@ static void cdc_acm_tx_fifo_handler(struct k_work *work) len = ring_buf_get(data->tx_fifo.rb, buf->data, buf->size); net_buf_add(buf, len); + if (IS_ENABLED(CONFIG_USBD_CDC_ACM_ENSURE_SHORT_PKT_FOR_LAST_TX_PKT)) { + if (len != 0 && len % cdc_acm_get_bulk_mps(c_data) == 0) { + udc_ep_buf_set_zlp(buf); + } + } + ret = usbd_ep_enqueue(c_data, buf); if (ret) { LOG_ERR("Failed to enqueue");