This is an automated email from the ASF dual-hosted git repository. lupyuen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 761c17f1e0c75abbeef0375510a3409893131f9d Author: daniellizewski <[email protected]> AuthorDate: Thu Apr 9 13:49:50 2026 -0400 drivers/usbhost/usbhost_enumerate.c: Allow selecting USB configuration Added support for selecting a different USB configuration. Certain USB devices offer different classes using different configurations. This allows a board file to provide a callback to select the proper configuration for a given USB device. Signed-off-by: daniellizewski <[email protected]> --- boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c | 25 ++++++++++++++++++-- drivers/usbhost/Kconfig | 11 +++++++++ drivers/usbhost/usbhost_enumerate.c | 30 ++++++++++++++++-------- include/nuttx/board.h | 30 ++++++++++++++++++++++++ include/nuttx/usb/usbhost.h | 1 - 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c index 64e2e6eb06f..796d4da62cd 100644 --- a/boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c +++ b/boards/arm/stm32h5/nucleo-h563zi/src/stm32_usb.c @@ -226,11 +226,32 @@ void stm32h5_usbhost_vbusdrive(int port, bool enable) /* The Nucleo-h563zi doesn't have hardware for a vbus drive. * Instead to get host working, you need to put an extra jumper * on the "PWR SEL" to jump "STLK" and "USB USER". - * This effectively supplies 5V power form the STLink to the USB device. - * The power output is limited so only relatively low power + * This effectively supplies 5V power from the STLink to the USB device. + * The power output is limited, so only relatively low power * devices can work. */ } #endif +#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION +int board_usbhost_select_configuration(FAR struct usbhost_hubport_s *hport, + FAR const struct usb_devdesc_s *devdesc, + FAR const struct usbhost_id_s *id) +{ + if (id->vid == 0x0bda && id->pid == 0x8153) + { + /* Use interface 1 (CDC-ECM) for this ethernet adapter. + * vid - Realtek Semiconductor Corp + * pid - RTL8153 Gigabit Ethernet Adapter + */ + + return 1; + } + + /* All other USB deices use configurion 0 */ + + return 0; +} +#endif + #endif /* CONFIG_STM32H5_USBFS_HOST */ diff --git a/drivers/usbhost/Kconfig b/drivers/usbhost/Kconfig index 4f9dc590238..7b12eea79bb 100644 --- a/drivers/usbhost/Kconfig +++ b/drivers/usbhost/Kconfig @@ -51,6 +51,17 @@ config USBHOST_ASYNCH I/O transfer. This may be required, for example, to receive infrequent, asynchronous input from an interrupt pipe. +config USBHOST_CONFIGURATION_SELECTION + bool "Per device configuration selection" + default n + ---help--- + Some devices have multiple USB configuration. By default the enumeration + selects the first configuration which may not be the desired configuration. + This features enables a board specific callback where it may choose which + configuration to apply based on the USB device descriptor. The callback may + choose by VID/PID or any other info it can acquire from a USB descriptor. + Board file must supply board_usbhost_select_configuration(). + config USBHOST_WAITER bool "USB Host Waiter Support" default n diff --git a/drivers/usbhost/usbhost_enumerate.c b/drivers/usbhost/usbhost_enumerate.c index 4e27a423dc1..c66036f2928 100644 --- a/drivers/usbhost/usbhost_enumerate.c +++ b/drivers/usbhost/usbhost_enumerate.c @@ -43,6 +43,10 @@ #include "usbhost_composite.h" +#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION +# include <nuttx/board.h> +#endif + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -295,6 +299,7 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport, uint16_t maxpacketsize; uint8_t descsize; uint8_t funcaddr = 0; + uint8_t cfgidx = 0; FAR uint8_t *buffer = NULL; int ret; @@ -454,14 +459,20 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport, DRVR_EP0CONFIGURE(hport->drvr, hport->ep0, hport->funcaddr, hport->speed, maxpacketsize); - /* Get the configuration descriptor (only), index == 0. Should not be - * hard-coded! More logic is needed in order to handle devices with - * multiple configurations. +#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION + /* Board specific callback to choose which configuration to use for + * this device. Supplied by board file */ + cfgidx = board_usbhost_select_configuration(hport, + (struct usb_devdesc_s *)buffer, &id); +#endif + + /* Get the configuration descriptor */ + ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; - usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8) | cfgidx); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, USB_SIZEOF_CFGDESC); @@ -488,13 +499,11 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport, goto errout; } - /* Get all of the configuration descriptor data, index == 0 (Should not be - * hard-coded!) - */ + /* Get all of the configuration descriptor data */ ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_GETDESCRIPTOR; - usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8)); + usbhost_putle16(ctrlreq->value, (USB_DESC_TYPE_CONFIG << 8) | cfgidx); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, cfglen); @@ -506,11 +515,12 @@ int usbhost_enumerate(FAR struct usbhost_hubport_s *hport, goto errout; } - /* Select device configuration 1 (Should not be hard-coded!) */ + /* Select this configuration using its bConfigurationValue */ ctrlreq->type = USB_REQ_DIR_OUT | USB_REQ_RECIPIENT_DEVICE; ctrlreq->req = USB_REQ_SETCONFIGURATION; - usbhost_putle16(ctrlreq->value, 1); + usbhost_putle16(ctrlreq->value, + ((struct usb_cfgdesc_s *)buffer)->cfgvalue); usbhost_putle16(ctrlreq->index, 0); usbhost_putle16(ctrlreq->len, 0); diff --git a/include/nuttx/board.h b/include/nuttx/board.h index e89f95922c2..bb5c8b4f6a8 100644 --- a/include/nuttx/board.h +++ b/include/nuttx/board.h @@ -102,6 +102,10 @@ # include <sys/boardctl.h> #endif +#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION +# include <nuttx/usb/usb.h> +#endif + /**************************************************************************** * Public Function Prototypes * @@ -865,6 +869,32 @@ int board_reset_cause(FAR struct boardioc_reset_cause_s *cause); int board_start_cpu(int cpuid); #endif +#ifdef CONFIG_USBHOST_CONFIGURATION_SELECTION + +/**************************************************************************** + * Name: board_usbhost_select_configuration + * + * Description: + * Board specific function to select the correct USB configuration + * for a given device. The function may use the device descriptor + * or make additional requests using the hport to decide which + * configuration to use. + * + * Input Parameters: + * hport - The port for the USB device + * devdesc - The device descriptor of the USB device + * id - device identification + * + * Returned Value: + * USB configuration index to use. + * + ****************************************************************************/ + +int board_usbhost_select_configuration(FAR struct usbhost_hubport_s *hport, + FAR const struct usb_devdesc_s *devdesc, + FAR const struct usbhost_id_s *id); +#endif /* CONFIG_USBHOST_CONFIGURATION_SELECTION */ + #undef EXTERN #ifdef __cplusplus } diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h index d0562994081..347896d661b 100644 --- a/include/nuttx/usb/usbhost.h +++ b/include/nuttx/usb/usbhost.h @@ -44,7 +44,6 @@ #ifdef CONFIG_USBHOST_MSC_NOTIFIER # include <nuttx/wqueue.h> #endif - #include <nuttx/usb/usbhost_devaddr.h> /****************************************************************************
