[PATCH 4/8] usb: Extract usb_select_configuration_no() helper

Jonas Karlman jonas at kwiboo.se
Sat Jul 11 18:08:02 CEST 2026


U-Boot only has support for one configuration for devices.

Extract handing of selecting active configuration to a helper function
to make it easier for drivers to select a different configuration.

This include a small change in behavior, errors from parsing config
descriptors are no longer ignored and is instead returned.

Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
---
 common/usb.c  | 59 ++++++++++++++++++++++++++++++---------------------
 include/usb.h | 10 +++++++++
 2 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/common/usb.c b/common/usb.c
index 6a4ad346f4ba..625512a1c99a 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -1149,11 +1149,38 @@ static int usb_device_is_ignored(u16 id_vendor, u16 id_product)
 	return 0;
 }
 
-int usb_select_config(struct usb_device *dev)
+int usb_select_configuration_no(struct usb_device *dev, int cfgno)
 {
 	unsigned char *tmpbuf = NULL;
 	int err;
 
+	err = usb_get_configuration_len(dev, cfgno);
+	if (err >= 0) {
+		tmpbuf = (unsigned char *)malloc_cache_aligned(err);
+		if (!tmpbuf)
+			err = -ENOMEM;
+		else
+			err = usb_get_configuration_no(dev, cfgno, tmpbuf, err);
+	}
+	if (err < 0) {
+		free(tmpbuf);
+		return err;
+	}
+
+	err = usb_parse_config(dev, tmpbuf, cfgno);
+	free(tmpbuf);
+	if (err < 0)
+		return err;
+
+	usb_set_maxpacket(dev);
+
+	return usb_set_configuration(dev, dev->config.desc.bConfigurationValue);
+}
+
+int usb_select_config(struct usb_device *dev)
+{
+	int err;
+
 	err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
 	if (err)
 		return err;
@@ -1193,34 +1220,18 @@ int usb_select_config(struct usb_device *dev)
 	 */
 	mdelay(1);
 
-	/* only support for one config for now */
-	err = usb_get_configuration_len(dev, 0);
-	if (err >= 0) {
-		tmpbuf = (unsigned char *)malloc_cache_aligned(err);
-		if (!tmpbuf)
-			err = -ENOMEM;
-		else
-			err = usb_get_configuration_no(dev, 0, tmpbuf, err);
-	}
-	if (err < 0) {
-		printf("usb_new_device: Cannot read configuration, " \
-		       "skipping device %04x:%04x\n",
-		       dev->descriptor.idVendor, dev->descriptor.idProduct);
-		free(tmpbuf);
-		return err;
-	}
-	usb_parse_config(dev, tmpbuf, 0);
-	free(tmpbuf);
-	usb_set_maxpacket(dev);
 	/*
-	 * we set the default configuration here
+	 * we select the default configuration here
 	 * This seems premature. If the driver wants a different configuration
 	 * it will need to select itself.
 	 */
-	err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue);
+	err = usb_select_configuration_no(dev, 0);
 	if (err < 0) {
-		printf("failed to set default configuration " \
-			"len %d, status %lX\n", dev->act_len, dev->status);
+		printf("failed to select default configuration " \
+			"len %d, status %lX, " \
+			"skipping device %04x:%04x\n",
+			dev->act_len, dev->status,
+			dev->descriptor.idVendor, dev->descriptor.idProduct);
 		return err;
 	}
 
diff --git a/include/usb.h b/include/usb.h
index 44c5d1cc5999..e9d16ee6c9fd 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -900,6 +900,16 @@ int usb_scan_device(struct udevice *parent, int port,
  */
 struct udevice *usb_get_bus(struct udevice *dev);
 
+/**
+ * usb_select_configuration_no() - Select configuration to use for a device
+ *
+ * This re-reads the configuration descriptor and sets the configuration.
+ *
+ * @dev:	Device to select configuration
+ * @cfgno:	Configuration number to set
+ */
+int usb_select_configuration_no(struct usb_device *dev, int cfgno);
+
 /**
  * usb_select_config() - Set up a device ready for use
  *
-- 
2.54.0



More information about the U-Boot mailing list