Browse Source

[PATCH] USB: ethernet gadget driver section fixups

This patch allows you to set the iSerialNumber field in the
usb_device_descriptor structure for your USB ethernet gadget.

It also changes the parameters shown through sysfs so they're
no longer declared as __initdata, preventing potential oopses.

That's most useful for the Ethernet addresses, which may in
some cases be random "locally administered" addresses.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Aras Vaichas 19 years ago
parent
commit
1afc64a3d6
1 changed files with 27 additions and 11 deletions
  1. 27 11
      drivers/usb/gadget/ether.c

+ 27 - 11
drivers/usb/gadget/ether.c

@@ -182,33 +182,37 @@ struct eth_dev {
  * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
  */
 
-static ushort __initdata idVendor;
+static ushort idVendor;
 module_param(idVendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(idVendor, "USB Vendor ID");
 
-static ushort __initdata idProduct;
+static ushort idProduct;
 module_param(idProduct, ushort, S_IRUGO);
 MODULE_PARM_DESC(idProduct, "USB Product ID");
 
-static ushort __initdata bcdDevice;
+static ushort bcdDevice;
 module_param(bcdDevice, ushort, S_IRUGO);
 MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
 
-static char *__initdata iManufacturer;
+static char *iManufacturer;
 module_param(iManufacturer, charp, S_IRUGO);
 MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
 
-static char *__initdata iProduct;
+static char *iProduct;
 module_param(iProduct, charp, S_IRUGO);
 MODULE_PARM_DESC(iProduct, "USB Product string");
 
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
+
 /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
-static char *__initdata dev_addr;
+static char *dev_addr;
 module_param(dev_addr, charp, S_IRUGO);
 MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
 
 /* this address is invisible to ifconfig */
-static char *__initdata host_addr;
+static char *host_addr;
 module_param(host_addr, charp, S_IRUGO);
 MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 
@@ -403,6 +407,7 @@ static inline int BITRATE(struct usb_gadget *g)
 #define STRING_CDC			7
 #define STRING_SUBSET			8
 #define STRING_RNDIS			9
+#define STRING_SERIALNUMBER		10
 
 /* holds our biggest descriptor (or RNDIS response) */
 #define USB_BUFSIZ	256
@@ -870,6 +875,7 @@ static inline void __init hs_subset_descriptors(void)
 
 static char				manufacturer [50];
 static char				product_desc [40] = DRIVER_DESC;
+static char				serial_number [20];
 
 #ifdef	DEV_CONFIG_CDC
 /* address that the host will use ... usually assigned at random */
@@ -880,6 +886,7 @@ static char				ethaddr [2 * ETH_ALEN + 1];
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER,	manufacturer, },
 	{ STRING_PRODUCT,	product_desc, },
+	{ STRING_SERIALNUMBER,	serial_number, },
 	{ STRING_DATA,		"Ethernet Data", },
 #ifdef	DEV_CONFIG_CDC
 	{ STRING_CDC,		"CDC Ethernet", },
@@ -2162,7 +2169,7 @@ static u8 __init nibble (unsigned char c)
 	return 0;
 }
 
-static void __init get_ether_addr (const char *str, u8 *dev_addr)
+static int __init get_ether_addr(const char *str, u8 *dev_addr)
 {
 	if (str) {
 		unsigned	i;
@@ -2177,9 +2184,10 @@ static void __init get_ether_addr (const char *str, u8 *dev_addr)
 			dev_addr [i] = num;
 		}
 		if (is_valid_ether_addr (dev_addr))
-			return;
+			return 0;
 	}
 	random_ether_addr(dev_addr);
+	return 1;
 }
 
 static int __init
@@ -2277,6 +2285,10 @@ eth_bind (struct usb_gadget *gadget)
 		strlcpy (manufacturer, iManufacturer, sizeof manufacturer);
 	if (iProduct)
 		strlcpy (product_desc, iProduct, sizeof product_desc);
+	if (iSerialNumber) {
+		device_desc.iSerialNumber = STRING_SERIALNUMBER,
+		strlcpy(serial_number, iSerialNumber, sizeof serial_number);
+	}
 
 	/* all we really need is bulk IN/OUT */
 	usb_ep_autoconfig_reset (gadget);
@@ -2386,9 +2398,13 @@ autoconf_fail:
 	 * The host side address is used with CDC and RNDIS, and commonly
 	 * ends up in a persistent config database.
 	 */
-	get_ether_addr(dev_addr, net->dev_addr);
+	if (get_ether_addr(dev_addr, net->dev_addr))
+		dev_warn(&gadget->dev,
+			"using random %s ethernet address\n", "self");
 	if (cdc || rndis) {
-		get_ether_addr(host_addr, dev->host_mac);
+		if (get_ether_addr(host_addr, dev->host_mac))
+			dev_warn(&gadget->dev,
+				"using random %s ethernet address\n", "host");
 #ifdef	DEV_CONFIG_CDC
 		snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
 			dev->host_mac [0], dev->host_mac [1],