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>
 
 /****************************************************************************

Reply via email to