From c377d241e28c08100cda56a3c0f3e7657195b9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 24 Jul 2024 08:41:14 +0200 Subject: [PATCH 1/5] usb: device_next: Unregister class according to speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix a typo resulted in USBD_SPEED_HS unregistering Full-Speed class instead of High-Speed. Signed-off-by: Tomasz Moń --- subsys/usb/device_next/usbd_class.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c index eeb2cfa5a20a3..76e5665dd985a 100644 --- a/subsys/usb/device_next/usbd_class.c +++ b/subsys/usb/device_next/usbd_class.c @@ -431,7 +431,7 @@ int usbd_unregister_class(struct usbd_context *const uds_ctx, * The atomic should be changed to something else. */ if (speed == USBD_SPEED_HS) { - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, i) { if ((i->c_data == c_nd->c_data) && atomic_test_bit(&i->state, USBD_CCTX_REGISTERED)) { @@ -440,7 +440,7 @@ int usbd_unregister_class(struct usbd_context *const uds_ctx, } } } else { - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, + STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, i) { if ((i->c_data == c_nd->c_data) && atomic_test_bit(&i->state, USBD_CCTX_REGISTERED)) { From 5b26d848340ed01fbf574748738d4a8cd194739a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 24 Jul 2024 08:55:48 +0200 Subject: [PATCH 2/5] usb: device_next: Add Kconfig to set maximum speed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two main ideas behind setting maximum speed are: * Allow code and RAM optimizations at compile time * Allow High-Speed capable drivers to limit operating speed to user choice. This commit only introduces the necessary Kconfig options but does not implement any code or RAM optimizations and does not modify any driver. Signed-off-by: Tomasz Moń --- drivers/usb/udc/Kconfig | 6 ++++++ drivers/usb/udc/Kconfig.dwc2 | 1 + drivers/usb/udc/Kconfig.mcux | 2 ++ drivers/usb/udc/Kconfig.skeleton | 1 + drivers/usb/udc/Kconfig.virtual | 1 + subsys/usb/device_next/Kconfig | 20 ++++++++++++++++++++ 6 files changed, 31 insertions(+) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index fd5e25cf11344..b13a2439c6fdf 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -11,6 +11,12 @@ menuconfig UDC_DRIVER if UDC_DRIVER +config UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT + bool + +config UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED + bool + config UDC_BUF_COUNT int "Number of buffers in the pool" range 16 256 diff --git a/drivers/usb/udc/Kconfig.dwc2 b/drivers/usb/udc/Kconfig.dwc2 index 2f40c8f71a283..9486f88c3ba5b 100644 --- a/drivers/usb/udc/Kconfig.dwc2 +++ b/drivers/usb/udc/Kconfig.dwc2 @@ -5,6 +5,7 @@ config UDC_DWC2 bool "DWC2 USB device controller driver" default y depends on DT_HAS_SNPS_DWC2_ENABLED + select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT select NRFS if NRFS_HAS_VBUS_DETECTOR_SERVICE select NRFS_VBUS_DETECTOR_SERVICE_ENABLED if NRFS_HAS_VBUS_DETECTOR_SERVICE select EVENTS diff --git a/drivers/usb/udc/Kconfig.mcux b/drivers/usb/udc/Kconfig.mcux index d68b21d171039..7ebace0e7f7c4 100644 --- a/drivers/usb/udc/Kconfig.mcux +++ b/drivers/usb/udc/Kconfig.mcux @@ -5,6 +5,7 @@ config UDC_NXP_EHCI bool "NXP MCUX USB EHCI Device controller driver" default y depends on DT_HAS_NXP_EHCI_ENABLED + select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT select PINCTRL select NOCACHE_MEMORY if CPU_HAS_DCACHE imply UDC_BUF_FORCE_NOCACHE @@ -16,6 +17,7 @@ config UDC_NXP_IP3511 bool "NXP MCUX USB IP3511 Device controller driver" default y depends on DT_HAS_NXP_LPCIP3511_ENABLED + select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT select PINCTRL imply UDC_WORKQUEUE help diff --git a/drivers/usb/udc/Kconfig.skeleton b/drivers/usb/udc/Kconfig.skeleton index bf7eb01323bf1..b6d96e0b89585 100644 --- a/drivers/usb/udc/Kconfig.skeleton +++ b/drivers/usb/udc/Kconfig.skeleton @@ -5,6 +5,7 @@ config UDC_SKELETON bool "Skeleton for an USB device controller driver" default y depends on DT_HAS_ZEPHYR_UDC_SKELETON_ENABLED + select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT help Skeleton for an USB device controller driver. diff --git a/drivers/usb/udc/Kconfig.virtual b/drivers/usb/udc/Kconfig.virtual index b84e14ba971e1..7aff8ca8e20d4 100644 --- a/drivers/usb/udc/Kconfig.virtual +++ b/drivers/usb/udc/Kconfig.virtual @@ -6,6 +6,7 @@ config UDC_VIRTUAL select UVB default y depends on DT_HAS_ZEPHYR_UDC_VIRTUAL_ENABLED + select UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT help Virtual USB device controller driver. diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index 52ce9d990858e..ce51d5e9077c0 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -16,6 +16,26 @@ module = USBD module-str = usbd source "subsys/logging/Kconfig.template.log_config" +choice USBD_MAX_SPEED_CHOICE + prompt "Max supported connection speed" + default USBD_MAX_SPEED_HIGH if UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT + default USBD_MAX_SPEED_FULL + +config USBD_MAX_SPEED_HIGH + bool "High-Speed" + depends on UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT + select UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED + +config USBD_MAX_SPEED_FULL + bool "Full-Speed" + +endchoice + +config USBD_MAX_SPEED + int + default 0 if USBD_MAX_SPEED_FULL + default 1 if USBD_MAX_SPEED_HIGH + config USBD_SHELL bool "USB device shell" depends on SHELL From 189d1301b7bd28e3861264f0f0daa04201dbefe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 4 Sep 2024 08:19:32 +0200 Subject: [PATCH 3/5] usb: device_next: Reduce code size on Full-Speed only configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow compiler optimizations to remove High-Speed handling code. Knowing that maximum operating speed is Full-Speed allows to reduce bulk buffers from 512 to 64 bytes. More RAM optimizations are possible but this commit only gets the low hanging fruits. Signed-off-by: Tomasz Moń --- include/zephyr/usb/usbd.h | 6 ++++++ samples/subsys/usb/common/sample_usbd_init.c | 3 ++- subsys/usb/device_next/class/bt_hci.c | 12 ++++++----- subsys/usb/device_next/class/loopback.c | 2 +- subsys/usb/device_next/class/usbd_cdc_acm.c | 16 ++++++++------ subsys/usb/device_next/class/usbd_cdc_ecm.c | 14 ++++++++----- subsys/usb/device_next/class/usbd_cdc_ncm.c | 14 ++++++++----- subsys/usb/device_next/class/usbd_hid.c | 2 +- subsys/usb/device_next/class/usbd_midi2.c | 12 ++++++++--- subsys/usb/device_next/class/usbd_msc.c | 10 +++++---- subsys/usb/device_next/class/usbd_uac2.c | 2 +- subsys/usb/device_next/usbd_ch9.c | 9 +++++--- subsys/usb/device_next/usbd_class.c | 8 +++---- subsys/usb/device_next/usbd_config.c | 6 ++++++ subsys/usb/device_next/usbd_core.c | 14 +++++++------ subsys/usb/device_next/usbd_device.h | 4 ++-- subsys/usb/device_next/usbd_init.c | 22 +++++++++++--------- subsys/usb/device_next/usbd_shell.c | 3 ++- tests/subsys/usb/device_next/src/main.c | 6 ++++-- 19 files changed, 105 insertions(+), 60 deletions(-) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index b85f6e2507fd5..5850643b31f7b 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -37,6 +37,12 @@ extern "C" { * @{ */ +/* 1 if USB device stack is compiled with High-Speed support */ +#define USBD_SUPPORTS_HIGH_SPEED IS_EQ(CONFIG_USBD_MAX_SPEED, 1) + +/* Maximum bulk max packet size the stack supports */ +#define USBD_MAX_BULK_MPS COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64)) + /* * The USB Unicode bString is encoded in UTF16LE, which means it takes up * twice the amount of bytes than the same string encoded in ASCII7. diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 9a187bc5f8df8..69642372a585a 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -126,7 +126,8 @@ struct usbd_context *sample_usbd_setup_device(usbd_msg_cb_t msg_cb) } /* doc add string descriptor end */ - if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS, &sample_hs_config); if (err) { diff --git a/subsys/usb/device_next/class/bt_hci.c b/subsys/usb/device_next/class/bt_hci.c index a7aed6378c623..150ef9569c205 100644 --- a/subsys/usb/device_next/class/bt_hci.c +++ b/subsys/usb/device_next/class/bt_hci.c @@ -68,13 +68,13 @@ static K_FIFO_DEFINE(bt_hci_tx_queue); /* * Transfers through three endpoints proceed in a synchronous manner, - * with maximum packet size of high speed bulk endpoint. + * with maximum packet size of max supported speed bulk endpoint. * * REVISE: global (bulk, interrupt, iso) specific pools would be more * RAM usage efficient. */ UDC_BUF_POOL_DEFINE(bt_hci_ep_pool, - 3, 512, + 3, USBD_MAX_BULK_MPS, sizeof(struct udc_buf_info), NULL); /* HCI RX/TX threads */ static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); @@ -138,7 +138,8 @@ static uint8_t bt_hci_get_bulk_in(struct usbd_class_data *const c_data) struct bt_hci_data *data = usbd_class_get_private(c_data); struct usbd_bt_hci_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_in_ep.bEndpointAddress; } @@ -151,7 +152,8 @@ static uint8_t bt_hci_get_bulk_out(struct usbd_class_data *const c_data) struct bt_hci_data *data = usbd_class_get_private(c_data); struct usbd_bt_hci_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_out_ep.bEndpointAddress; } @@ -449,7 +451,7 @@ static void *bt_hci_get_desc(struct usbd_class_data *const c_data, { struct bt_hci_data *data = usbd_class_get_private(c_data); - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return data->hs_desc; } diff --git a/subsys/usb/device_next/class/loopback.c b/subsys/usb/device_next/class/loopback.c index 0e5ba96f45932..85896cd549e21 100644 --- a/subsys/usb/device_next/class/loopback.c +++ b/subsys/usb/device_next/class/loopback.c @@ -254,7 +254,7 @@ static void *lb_get_desc(struct usbd_class_data *const c_data, { struct lb_data *data = usbd_class_get_private(c_data); - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return data->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_cdc_acm.c b/subsys/usb/device_next/class/usbd_cdc_acm.c index 15e3cab90a0e4..d3fef3b83b0f3 100644 --- a/subsys/usb/device_next/class/usbd_cdc_acm.c +++ b/subsys/usb/device_next/class/usbd_cdc_acm.c @@ -36,7 +36,7 @@ LOG_MODULE_REGISTER(usbd_cdc_acm, CONFIG_USBD_CDC_ACM_LOG_LEVEL); UDC_BUF_POOL_DEFINE(cdc_acm_ep_pool, DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 2, - 512, sizeof(struct udc_buf_info), NULL); + USBD_MAX_BULK_MPS, sizeof(struct udc_buf_info), NULL); #define CDC_ACM_DEFAULT_LINECODING {sys_cpu_to_le32(115200), 0, 0, 8} #define CDC_ACM_DEFAULT_INT_EP_MPS 16 @@ -171,7 +171,8 @@ static uint8_t cdc_acm_get_int_in(struct usbd_class_data *const c_data) const struct cdc_acm_uart_config *cfg = dev->config; struct usbd_cdc_acm_desc *desc = cfg->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_int_ep.bEndpointAddress; } @@ -185,7 +186,8 @@ static uint8_t cdc_acm_get_bulk_in(struct usbd_class_data *const c_data) const struct cdc_acm_uart_config *cfg = dev->config; struct usbd_cdc_acm_desc *desc = cfg->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_hs_in_ep.bEndpointAddress; } @@ -199,7 +201,8 @@ static uint8_t cdc_acm_get_bulk_out(struct usbd_class_data *const c_data) const struct cdc_acm_uart_config *cfg = dev->config; struct usbd_cdc_acm_desc *desc = cfg->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_hs_out_ep.bEndpointAddress; } @@ -210,7 +213,8 @@ static size_t cdc_acm_get_bulk_mps(struct usbd_class_data *const c_data) { struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return 512U; } @@ -350,7 +354,7 @@ static void *usbd_cdc_acm_get_desc(struct usbd_class_data *const c_data, const struct device *dev = usbd_class_get_private(c_data); const struct cdc_acm_uart_config *cfg = dev->config; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return cfg->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_cdc_ecm.c b/subsys/usb/device_next/class/usbd_cdc_ecm.c index e43f38bed6425..55aa2798a6471 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ecm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ecm.c @@ -106,7 +106,8 @@ static uint8_t cdc_ecm_get_int_in(struct usbd_class_data *const c_data) struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_int_ep.bEndpointAddress; } @@ -120,7 +121,8 @@ static uint8_t cdc_ecm_get_bulk_in(struct usbd_class_data *const c_data) struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_1_hs_in_ep.bEndpointAddress; } @@ -131,7 +133,8 @@ static uint16_t cdc_ecm_get_bulk_in_mps(struct usbd_class_data *const c_data) { struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return 512U; } @@ -145,7 +148,8 @@ static uint8_t cdc_ecm_get_bulk_out(struct usbd_class_data *const c_data) struct cdc_ecm_eth_data *data = dev->data; struct usbd_cdc_ecm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_1_hs_out_ep.bEndpointAddress; } @@ -475,7 +479,7 @@ static void *usbd_cdc_ecm_get_desc(struct usbd_class_data *const c_data, const struct device *dev = usbd_class_get_private(c_data); struct cdc_ecm_eth_data *const data = dev->data; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return data->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_cdc_ncm.c b/subsys/usb/device_next/class/usbd_cdc_ncm.c index a7ffb5f23f74d..c92754f72f839 100644 --- a/subsys/usb/device_next/class/usbd_cdc_ncm.c +++ b/subsys/usb/device_next/class/usbd_cdc_ncm.c @@ -249,7 +249,8 @@ static uint8_t cdc_ncm_get_int_in(struct usbd_class_data *const c_data) struct cdc_ncm_eth_data *data = dev->data; struct usbd_cdc_ncm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_int_ep.bEndpointAddress; } @@ -263,7 +264,8 @@ static uint8_t cdc_ncm_get_bulk_in(struct usbd_class_data *const c_data) struct cdc_ncm_eth_data *data = dev->data; struct usbd_cdc_ncm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_1_hs_in_ep.bEndpointAddress; } @@ -274,7 +276,8 @@ static uint16_t cdc_ncm_get_bulk_in_mps(struct usbd_class_data *const c_data) { struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return 512U; } @@ -288,7 +291,8 @@ static uint8_t cdc_ncm_get_bulk_out(struct usbd_class_data *const c_data) struct cdc_ncm_eth_data *data = dev->data; struct usbd_cdc_ncm_desc *desc = data->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if1_1_hs_out_ep.bEndpointAddress; } @@ -1009,7 +1013,7 @@ static void *usbd_cdc_ncm_get_desc(struct usbd_class_data *const c_data, const struct device *dev = usbd_class_get_private(c_data); struct cdc_ncm_eth_data *const data = dev->data; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return data->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index a3672148fd3d5..fd10eba3c8506 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -479,7 +479,7 @@ static void *usbd_hid_get_desc(struct usbd_class_data *const c_data, const struct device *dev = usbd_class_get_private(c_data); const struct hid_device_config *dcfg = dev->config; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return dcfg->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_midi2.c b/subsys/usb/device_next/class/usbd_midi2.c index 20d66590b5fae..1afab63b4d92f 100644 --- a/subsys/usb/device_next/class/usbd_midi2.c +++ b/subsys/usb/device_next/class/usbd_midi2.c @@ -344,7 +344,11 @@ static void *usbd_midi_class_get_desc(struct usbd_class_data *const class_data, LOG_DBG("Get descriptors for %s", dev->name); - return (speed == USBD_SPEED_HS) ? config->hs_descs : config->fs_descs; + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { + return config->hs_descs; + } + + return config->fs_descs; } @@ -382,7 +386,8 @@ static uint8_t usbd_midi_get_bulk_in(struct usbd_class_data *const class_data) const struct device *dev = usbd_class_get_private(class_data); const struct usbd_midi_config *cfg = dev->config; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return cfg->desc->if1_1_in_ep_hs.bEndpointAddress; } @@ -395,7 +400,8 @@ static uint8_t usbd_midi_get_bulk_out(struct usbd_class_data *const class_data) const struct device *dev = usbd_class_get_private(class_data); const struct usbd_midi_config *cfg = dev->config; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return cfg->desc->if1_1_out_ep_hs.bEndpointAddress; } diff --git a/subsys/usb/device_next/class/usbd_msc.c b/subsys/usb/device_next/class/usbd_msc.c index 6f8b7c4622634..07d5d09347f6a 100644 --- a/subsys/usb/device_next/class/usbd_msc.c +++ b/subsys/usb/device_next/class/usbd_msc.c @@ -61,7 +61,7 @@ struct CSW { #define MSC_NUM_INSTANCES CONFIG_USBD_MSC_INSTANCES_COUNT /* Can be 64 if device is not High-Speed capable */ -#define MSC_BUF_SIZE 512 +#define MSC_BUF_SIZE USBD_MAX_BULK_MPS UDC_BUF_POOL_DEFINE(msc_ep_pool, MSC_NUM_INSTANCES * 2, MSC_BUF_SIZE, @@ -149,7 +149,8 @@ static uint8_t msc_get_bulk_in(struct usbd_class_data *const c_data) struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct msc_bot_desc *desc = ctx->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_in_ep.bEndpointAddress; } @@ -162,7 +163,8 @@ static uint8_t msc_get_bulk_out(struct usbd_class_data *const c_data) struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); struct msc_bot_desc *desc = ctx->desc; - if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { return desc->if0_hs_out_ep.bEndpointAddress; } @@ -755,7 +757,7 @@ static void *msc_bot_get_desc(struct usbd_class_data *const c_data, { struct msc_bot_ctx *ctx = usbd_class_get_private(c_data); - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return ctx->hs_desc; } diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 77bfde9c47222..2e55a9a017afc 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -890,7 +890,7 @@ static void *uac2_get_desc(struct usbd_class_data *const c_data, struct device *dev = usbd_class_get_private(c_data); const struct uac2_cfg *cfg = dev->config; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { return cfg->hs_descriptors; } diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index b9bfd00b3ae55..827206af7c377 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -472,9 +472,11 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, /* * If the other-speed-configuration-descriptor is requested and the - * controller does not support high speed, respond with an error. + * controller (or stack) does not support high speed, respond with + * an error. */ - if (other_cfg && usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) { + if (other_cfg && !(USBD_SUPPORTS_HIGH_SPEED && + (usbd_caps_speed(uds_ctx) == USBD_SPEED_HS))) { errno = -ENOTSUP; return 0; } @@ -691,7 +693,8 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, * If the Device Qualifier descriptor is requested and the controller * does not support high speed, respond with an error. */ - if (usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) { + if (!USBD_SUPPORTS_HIGH_SPEED || + usbd_caps_speed(uds_ctx) != USBD_SPEED_HS) { errno = -ENOTSUP; return 0; } diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c index 76e5665dd985a..48f3d6d72681c 100644 --- a/subsys/usb/device_next/usbd_class.c +++ b/subsys/usb/device_next/usbd_class.c @@ -215,7 +215,7 @@ usbd_class_node_get(const char *name, const enum usbd_speed speed) return c_nd; } } - } else if (speed == USBD_SPEED_HS) { + } else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { if (strcmp(name, c_nd->c_data->name) == 0) { @@ -358,7 +358,7 @@ int usbd_register_all_classes(struct usbd_context *const uds_ctx, { int ret; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { if (blocklist != NULL && is_blocklisted(c_nd, blocklist)) { continue; @@ -430,7 +430,7 @@ int usbd_unregister_class(struct usbd_context *const uds_ctx, /* TODO: The use of atomic here does not make this code thread safe. * The atomic should be changed to something else. */ - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, i) { if ((i->c_data == c_nd->c_data) && @@ -470,7 +470,7 @@ int usbd_unregister_all_classes(struct usbd_context *const uds_ctx, { int ret; - if (speed == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { ret = usbd_unregister_class(uds_ctx, c_nd->c_data->name, speed, cfg); diff --git a/subsys/usb/device_next/usbd_config.c b/subsys/usb/device_next/usbd_config.c index 9d8627028a99b..8a589722e25d7 100644 --- a/subsys/usb/device_next/usbd_config.c +++ b/subsys/usb/device_next/usbd_config.c @@ -266,6 +266,12 @@ int usbd_add_configuration(struct usbd_context *const uds_ctx, goto add_configuration_exit; } + if (speed == USBD_SPEED_HS && !USBD_SUPPORTS_HIGH_SPEED) { + LOG_ERR("Stack was compiled without High-Speed support"); + ret = -ENOTSUP; + goto add_configuration_exit; + } + if (speed == USBD_SPEED_HS && usbd_caps_speed(uds_ctx) == USBD_SPEED_FS) { LOG_ERR("Controller doesn't support HS"); diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c index 64c0a0ab654cd..9f24530fc2c2c 100644 --- a/subsys/usb/device_next/usbd_core.c +++ b/subsys/usb/device_next/usbd_core.c @@ -228,12 +228,14 @@ int usbd_device_shutdown_core(struct usbd_context *const uds_ctx) struct usbd_config_node *cfg_nd; int ret; - SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) { - uint8_t cfg_value = usbd_config_get_value(cfg_nd); - - ret = usbd_class_remove_all(uds_ctx, USBD_SPEED_HS, cfg_value); - if (ret) { - LOG_ERR("Failed to cleanup registered classes, %d", ret); + if (USBD_SUPPORTS_HIGH_SPEED) { + SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) { + uint8_t cfg_value = usbd_config_get_value(cfg_nd); + + ret = usbd_class_remove_all(uds_ctx, USBD_SPEED_HS, cfg_value); + if (ret) { + LOG_ERR("Failed to cleanup registered classes, %d", ret); + } } } diff --git a/subsys/usb/device_next/usbd_device.h b/subsys/usb/device_next/usbd_device.h index e2f0d98ab8b4e..8d29a19e6a9d9 100644 --- a/subsys/usb/device_next/usbd_device.h +++ b/subsys/usb/device_next/usbd_device.h @@ -45,7 +45,7 @@ static inline uint8_t usbd_get_num_configs(const struct usbd_context *const uds_ if (speed == USBD_SPEED_FS) { desc = uds_ctx->fs_desc; - } else if (speed == USBD_SPEED_HS) { + } else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { desc = uds_ctx->hs_desc; } else { return 0; @@ -70,7 +70,7 @@ static inline void usbd_set_num_configs(struct usbd_context *const uds_ctx, if (speed == USBD_SPEED_FS) { desc = uds_ctx->fs_desc; - } else if (speed == USBD_SPEED_HS) { + } else if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) { desc = uds_ctx->hs_desc; } else { return; diff --git a/subsys/usb/device_next/usbd_init.c b/subsys/usb/device_next/usbd_init.c index fc31c8a211a93..021fc8f2fca5a 100644 --- a/subsys/usb/device_next/usbd_init.c +++ b/subsys/usb/device_next/usbd_init.c @@ -281,18 +281,20 @@ int usbd_init_configurations(struct usbd_context *const uds_ctx) usbd_init_update_fs_mps0(uds_ctx); - SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) { - int ret; + if (USBD_SUPPORTS_HIGH_SPEED) { + SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->hs_configs, cfg_nd, node) { + int ret; - ret = init_configuration(uds_ctx, USBD_SPEED_HS, cfg_nd); - if (ret) { - LOG_ERR("Failed to init HS configuration %u", - usbd_config_get_value(cfg_nd)); - return ret; - } + ret = init_configuration(uds_ctx, USBD_SPEED_HS, cfg_nd); + if (ret) { + LOG_ERR("Failed to init HS configuration %u", + usbd_config_get_value(cfg_nd)); + return ret; + } - LOG_INF("HS bNumConfigurations %u", - usbd_get_num_configs(uds_ctx, USBD_SPEED_HS)); + LOG_INF("HS bNumConfigurations %u", + usbd_get_num_configs(uds_ctx, USBD_SPEED_HS)); + } } SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->fs_configs, cfg_nd, node) { diff --git a/subsys/usb/device_next/usbd_shell.c b/subsys/usb/device_next/usbd_shell.c index 6b321204a24a3..4597143e78b96 100644 --- a/subsys/usb/device_next/usbd_shell.c +++ b/subsys/usb/device_next/usbd_shell.c @@ -147,7 +147,8 @@ static int register_classes(const struct shell *sh) shell_print(sh, "dev: register FS %s", c_nd->c_data->name); } - if (usbd_caps_speed(my_uds_ctx) != USBD_SPEED_HS) { + if (!USBD_SUPPORTS_HIGH_SPEED || + usbd_caps_speed(my_uds_ctx) != USBD_SPEED_HS) { return 0; } diff --git a/tests/subsys/usb/device_next/src/main.c b/tests/subsys/usb/device_next/src/main.c index 68dce57dfda46..0534a56141fad 100644 --- a/tests/subsys/usb/device_next/src/main.c +++ b/tests/subsys/usb/device_next/src/main.c @@ -136,7 +136,8 @@ static void *usb_test_enable(void) err = usbd_add_descriptor(&test_usbd, &test_sn); zassert_equal(err, 0, "Failed to initialize descriptor (%d)", err); - if (usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) { err = usbd_add_configuration(&test_usbd, USBD_SPEED_HS, &test_hs_config); zassert_equal(err, 0, "Failed to add configuration (%d)"); } @@ -144,7 +145,8 @@ static void *usb_test_enable(void) err = usbd_add_configuration(&test_usbd, USBD_SPEED_FS, &test_fs_config); zassert_equal(err, 0, "Failed to add configuration (%d)"); - if (usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_caps_speed(&test_usbd) == USBD_SPEED_HS) { err = usbd_register_all_classes(&test_usbd, USBD_SPEED_HS, 1, NULL); zassert_equal(err, 0, "Failed to unregister all instances(%d)"); From 0f771a46262c3bc4f117274f6207a41be04460f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Wed, 28 Aug 2024 06:32:06 +0200 Subject: [PATCH 4/5] drivers: udc_dwc2: Limit operating speed to stack configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit maximum operating speed in DCFG register if USB stack is configured to support only Full-Speed. Signed-off-by: Tomasz Moń --- drivers/usb/udc/udc_dwc2.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 2339356d8823c..915a4647e2736 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -2040,15 +2040,21 @@ static int udc_dwc2_init_controller(const struct device *dev) case USB_DWC2_GHWCFG2_HSPHYTYPE_ULPI: gusbcfg |= USB_DWC2_GUSBCFG_PHYSEL_USB20 | USB_DWC2_GUSBCFG_ULPI_UTMI_SEL_ULPI; - dcfg |= USB_DWC2_DCFG_DEVSPD_USBHS20 - << USB_DWC2_DCFG_DEVSPD_POS; + if (IS_ENABLED(CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED)) { + dcfg |= usb_dwc2_set_dcfg_devspd(USB_DWC2_DCFG_DEVSPD_USBHS20); + } else { + dcfg |= usb_dwc2_set_dcfg_devspd(USB_DWC2_DCFG_DEVSPD_USBFS20); + } hs_phy = true; break; case USB_DWC2_GHWCFG2_HSPHYTYPE_UTMIPLUS: gusbcfg |= USB_DWC2_GUSBCFG_PHYSEL_USB20 | USB_DWC2_GUSBCFG_ULPI_UTMI_SEL_UTMI; - dcfg |= USB_DWC2_DCFG_DEVSPD_USBHS20 - << USB_DWC2_DCFG_DEVSPD_POS; + if (IS_ENABLED(CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED)) { + dcfg |= usb_dwc2_set_dcfg_devspd(USB_DWC2_DCFG_DEVSPD_USBHS20); + } else { + dcfg |= usb_dwc2_set_dcfg_devspd(USB_DWC2_DCFG_DEVSPD_USBFS20); + } hs_phy = true; break; case USB_DWC2_GHWCFG2_HSPHYTYPE_NO_HS: @@ -2059,8 +2065,7 @@ static int udc_dwc2_init_controller(const struct device *dev) gusbcfg |= USB_DWC2_GUSBCFG_PHYSEL_USB11; } - dcfg |= USB_DWC2_DCFG_DEVSPD_USBFS1148 - << USB_DWC2_DCFG_DEVSPD_POS; + dcfg |= usb_dwc2_set_dcfg_devspd(USB_DWC2_DCFG_DEVSPD_USBFS1148); hs_phy = false; } From c9100dc695002860734a96063b4a5aadf49fece6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Mon, 7 Apr 2025 08:26:57 +0200 Subject: [PATCH 5/5] usb: device_next: Change speed selection Kconfig dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In my opinion, the user is supposed to configure the speed of the stack and drivers ough to honor that choice. However current Zephyr USB maintainer imposes that the dependency is the other way round, i.e. that user first needs to disable High-Speed chirp at driver level and only then can select Full-Speed only operation. Adhere to the arbitrarily set up rule to allow this really necessary functionality to enter Zephyr. I consider this change to be harmful because it opens up a Kconfig trap that allows configuring High-Speed capable stack with a device driver limited to Full-Speed only operation. Signed-off-by: Tomasz Moń --- drivers/usb/udc/Kconfig | 6 +++++- subsys/usb/device_next/Kconfig | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index b13a2439c6fdf..40a75ea68800f 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -15,7 +15,11 @@ config UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT bool config UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED - bool + bool "Allow High-Speed chirp" + default y if UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT + help + Allow High-Speed capable device to operate at High-Speed. Disable this + option to force Full-Speed only operation. config UDC_BUF_COUNT int "Number of buffers in the pool" diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index ce51d5e9077c0..68ae7559845c3 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -24,10 +24,10 @@ choice USBD_MAX_SPEED_CHOICE config USBD_MAX_SPEED_HIGH bool "High-Speed" depends on UDC_DRIVER_HAS_HIGH_SPEED_SUPPORT - select UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED config USBD_MAX_SPEED_FULL bool "Full-Speed" + depends on !UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED endchoice