Index: linux-2.6.20.2/drivers/usb/gadget/ether.c
===================================================================
--- linux-2.6.20.2.orig/drivers/usb/gadget/ether.c	2007-03-30 15:10:57.000000000 +0200
+++ linux-2.6.20.2/drivers/usb/gadget/ether.c	2007-03-30 15:12:20.000000000 +0200
@@ -133,7 +133,7 @@
 	u16			cdc_filter;
 	unsigned long		todo;
 #define	WORK_RX_MEMORY		0
-	int			rndis_config;
+	int			rndis_config, rndis_config_low;
 	u8			host_mac [ETH_ALEN];
 };
 
@@ -416,13 +416,13 @@
  *
  * NOTE:  Controllers like superh_udc should probably be able to use
  * an RNDIS-only configuration.
- *
- * FIXME define some higher-powered configurations to make it easier
- * to recharge batteries ...
  */
 
 #define DEV_CONFIG_VALUE	1	/* cdc or subset */
 #define DEV_RNDIS_CONFIG_VALUE	2	/* rndis; optional */
+#define DEV_CONFIG_VALUE_LOW	3	/* cdc or subset; low power */
+#define DEV_RNDIS_CONFIG_VALUE_LOW	4	/* rndis; optional; low power */
+
 
 static struct usb_device_descriptor
 device_desc = {
@@ -439,7 +439,7 @@
 	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
-	.bNumConfigurations =	1,
+	.bNumConfigurations =	2,
 };
 
 static struct usb_otg_descriptor
@@ -459,7 +459,20 @@
 	.bNumInterfaces =	2,
 	.bConfigurationValue =	DEV_CONFIG_VALUE,
 	.iConfiguration =	STRING_CDC,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bmAttributes =		USB_CONFIG_ATT_ONE,
+	.bMaxPower =		250,
+};
+
+static struct usb_config_descriptor
+eth_config_low = {
+	.bLength =		sizeof eth_config_low,
+	.bDescriptorType =	USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =	2,
+	.bConfigurationValue = DEV_CONFIG_VALUE_LOW,
+	.iConfiguration =	STRING_CDC,
+	.bmAttributes =		USB_CONFIG_ATT_ONE,
 	.bMaxPower =		50,
 };
 
@@ -473,7 +486,20 @@
 	.bNumInterfaces =       2,
 	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE,
 	.iConfiguration =       STRING_RNDIS,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bmAttributes =		USB_CONFIG_ATT_ONE,
+	.bMaxPower =            250,
+};
+
+static struct usb_config_descriptor
+rndis_config_low = {
+	.bLength =              sizeof rndis_config_low,
+	.bDescriptorType =      USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =       2,
+	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE_LOW,
+	.iConfiguration =       STRING_RNDIS,
+	.bmAttributes =		USB_CONFIG_ATT_ONE,
 	.bMaxPower =            50,
 };
 #endif
@@ -800,7 +826,7 @@
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_COMM,
 
-	.bNumConfigurations =	1,
+	.bNumConfigurations =	2,
 };
 
 static const struct usb_descriptor_header *hs_eth_function [11] = {
@@ -935,14 +961,23 @@
 	/* list the RNDIS config first, to make Microsoft's drivers
 	 * happy. DOCSIS 1.0 needs this too.
 	 */
-	if (device_desc.bNumConfigurations == 2 && index == 0) {
+	if (device_desc.bNumConfigurations == 4 && index == 0) {
 		config = &rndis_config;
 		function = which_fn (rndis);
-	} else
+	} if (device_desc.bNumConfigurations == 4 && index == 3) {
+		config = &rndis_config_low;
+		function = which_fn (rndis);
+	}
 #endif
-	{
+	/* Index of the cdc_ether configs is important */
+	if ((device_desc.bNumConfigurations == 4 && index == 1) ||
+		(device_desc.bNumConfigurations == 2 && index == 0)) {
 		config = &eth_config;
 		function = which_fn (eth);
+	} if ((device_desc.bNumConfigurations == 4 && index == 2) ||
+		(device_desc.bNumConfigurations == 2 && index == 1)) {
+		config = &eth_config_low;
+		function = which_fn (eth);
 	}
 
 	/* for now, don't advertise srp-only devices */
@@ -1120,10 +1155,12 @@
 
 	switch (number) {
 	case DEV_CONFIG_VALUE:
+	case DEV_CONFIG_VALUE_LOW:
 		result = set_ether_config (dev, gfp_flags);
 		break;
 #ifdef	CONFIG_USB_ETH_RNDIS
 	case DEV_RNDIS_CONFIG_VALUE:
+	case DEV_RNDIS_CONFIG_VALUE_LOW:
 		dev->rndis = 1;
 		result = set_ether_config (dev, gfp_flags);
 		break;
@@ -2151,6 +2188,7 @@
 
 	DEBUG (dev, "unbind\n");
 	rndis_deregister (dev->rndis_config);
+	rndis_deregister (dev->rndis_config_low);
 	rndis_exit ();
 
 	/* we've already been disconnected ... no i/o is active */
@@ -2349,6 +2387,8 @@
 	if (!cdc) {
 		eth_config.bNumInterfaces = 1;
 		eth_config.iConfiguration = STRING_SUBSET;
+		eth_config_low.bNumInterfaces = 1;
+		eth_config_low.iConfiguration = STRING_SUBSET;
 		fs_subset_descriptors();
 		hs_subset_descriptors();
 	}
@@ -2356,13 +2396,13 @@
 	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 	usb_gadget_set_selfpowered (gadget);
 
-	/* For now RNDIS is always a second config */
+	/* For now RNDIS is always a second set of configs */
 	if (rndis)
-		device_desc.bNumConfigurations = 2;
+		device_desc.bNumConfigurations = 4;
 
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
 	if (rndis)
-		dev_qualifier.bNumConfigurations = 2;
+		dev_qualifier.bNumConfigurations = 4;
 	else if (!cdc)
 		dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
 
@@ -2383,9 +2423,13 @@
 		otg_descriptor.bmAttributes |= USB_OTG_HNP,
 		eth_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		eth_config.bMaxPower = 4;
+		eth_config_low.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		eth_config_low.bMaxPower = 4;
 #ifdef	CONFIG_USB_ETH_RNDIS
 		rndis_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 		rndis_config.bMaxPower = 4;
+		rndis_config_low.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		rndis_config_low.bMaxPower = 4;
 #endif
 	}
 
