ChangeSet 1.1733, 2004/05/17 15:33:22-07:00, david-b@pacbell.net

[PATCH] USB: ethernet/rndis gadget address params

This resolves a FIXME by adding module parameters that can
be used to provide stable (vs random) addresses, and gets
rid of a runtime error from obsolete module parameter usage
in the RNDIS code.

The stable ethernet addresses are nice to hosts, which will
normally want to save them away in config databases.  For
example, without stable addresses Windows XP will end up
recording quite a lot of RNDIS devices.


 drivers/usb/gadget/ether.c |   59 +++++++++++++++++++++++++++++++++++----------
 drivers/usb/gadget/rndis.c |    3 +-
 2 files changed, 48 insertions(+), 14 deletions(-)


diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	Mon May 17 16:37:27 2004
+++ b/drivers/usb/gadget/ether.c	Mon May 17 16:37:27 2004
@@ -40,6 +40,7 @@
 #include <linux/version.h>
 #include <linux/device.h>
 #include <linux/moduleparam.h>
+#include <linux/ctype.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -193,6 +194,16 @@
 module_param(iProduct, charp, S_IRUGO);
 MODULE_PARM_DESC(iProduct, "USB Product string");
 
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *__initdata dev_addr;
+module_param(dev_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *__initdata host_addr;
+module_param(host_addr, charp, S_IRUGO);
+MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -2199,6 +2210,36 @@
 	set_gadget_data (gadget, 0);
 }
 
+static u8 __init nibble (unsigned char c)
+{
+	if (likely (isdigit (c)))
+		return c - '0';
+	c = toupper (c);
+	if (likely (isxdigit (c)))
+		return 10 + c - 'A';
+	return 0;
+}
+
+static void __init get_ether_addr (const char *str, u8 *dev_addr)
+{
+	if (str) {
+		unsigned	i;
+
+		for (i = 0; i < 6; i++) {
+			unsigned char num;
+
+			if((*str == '.') || (*str == ':'))
+				str++;
+			num = nibble(*str++) << 4;
+			num |= (nibble(*str++));
+			dev_addr [i] = num;
+		}
+		if (is_valid_ether_addr (dev_addr))
+			return;
+	}
+	random_ether_addr(dev_addr);
+}
+
 static int __init
 eth_bind (struct usb_gadget *gadget)
 {
@@ -2393,21 +2434,13 @@
 	dev->cdc = cdc;
 	dev->zlp = zlp;
 
-	/* FIXME make these addresses configurable with module params.
-	 * also the manufacturer and product strings.
-	 */
-
-	/* one random address for the gadget device ... both of these could
-	 * reasonably come from an id prom or a module parameter.
-	 */
-	random_ether_addr(net->dev_addr);
-
-	/* ... another address for the host, on the other end of the
-	 * link, gets exported through CDC (see CDC spec table 41)
-	 * and RNDIS.
+	/* Module params for these addresses should come from ID proms.
+	 * The host side address is used with CDC and RNDIS, and commonly
+	 * end ups in a persistent config database.
 	 */
+	get_ether_addr(dev_addr, net->dev_addr);
 	if (cdc || rndis) {
-		random_ether_addr(dev->host_mac);
+		get_ether_addr(host_addr, dev->host_mac);
 #ifdef	DEV_CONFIG_CDC
 		snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
 			dev->host_mac [0], dev->host_mac [1],
diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
--- a/drivers/usb/gadget/rndis.c	Mon May 17 16:37:27 2004
+++ b/drivers/usb/gadget/rndis.c	Mon May 17 16:37:27 2004
@@ -22,6 +22,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/version.h>
@@ -51,7 +52,7 @@
 #define DEBUG if (rndis_debug) printk 
 static int rndis_debug = 0;
 
-MODULE_PARM (rndis_debug, "i");
+module_param (rndis_debug, bool, 0);
 MODULE_PARM_DESC (rndis_debug, "enable debugging");
 
 #else
