USB: gadget: Add EEM gadget driver

This patch adds a CDC EEM ethernet gadget driver.  CDC EEM is a newer
USB ethernet specification that uses a simpler interface than the older
CDC ECM.  This makes CDC EEM usable by a wider set of USB hardware.
By default the ethernet gadget will still use CDC ECM/Subset, but kernel
configuration and/or a module parameter will allow alternative use of
the CDC EEM protocol.

Changes since last version:
	- Brought in missing RNDIS changes that caused compile error
	- Modified 'sentinel CRC' checking to match EEM host driver

Signed-off-by: Brian Niebuhr <bniebuhr@efjohnson.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index bd102f5..f37de28 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -61,6 +61,11 @@
  * simpler, Microsoft pushes their own approach: RNDIS.  The published
  * RNDIS specs are ambiguous and appear to be incomplete, and are also
  * needlessly complex.  They borrow more from CDC ACM than CDC ECM.
+ *
+ * While CDC ECM, CDC Subset, and RNDIS are designed to extend the ethernet
+ * interface to the target, CDC EEM was designed to use ethernet over the USB
+ * link between the host and target.  CDC EEM is implemented as an alternative
+ * to those other protocols when that communication model is more appropriate
  */
 
 #define DRIVER_DESC		"Ethernet Gadget"
@@ -114,6 +119,7 @@
 #include "f_rndis.c"
 #include "rndis.c"
 #endif
+#include "f_eem.c"
 #include "u_ether.c"
 
 /*-------------------------------------------------------------------------*/
@@ -150,6 +156,10 @@
 #define RNDIS_VENDOR_NUM	0x0525	/* NetChip */
 #define RNDIS_PRODUCT_NUM	0xa4a2	/* Ethernet/RNDIS Gadget */
 
+/* For EEM gadgets */
+#define EEM_VENDOR_NUM	0x0525	/* INVALID - NEEDS TO BE ALLOCATED */
+#define EEM_PRODUCT_NUM	0xa4a1	/* INVALID - NEEDS TO BE ALLOCATED */
+
 /*-------------------------------------------------------------------------*/
 
 static struct usb_device_descriptor device_desc = {
@@ -246,8 +256,16 @@
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_USB_ETH_EEM
+static int use_eem = 1;
+#else
+static int use_eem;
+#endif
+module_param(use_eem, bool, 0);
+MODULE_PARM_DESC(use_eem, "use CDC EEM mode");
+
 /*
- * We _always_ have an ECM or CDC Subset configuration.
+ * We _always_ have an ECM, CDC Subset, or EEM configuration.
  */
 static int __init eth_do_config(struct usb_configuration *c)
 {
@@ -258,7 +276,9 @@
 		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
-	if (can_support_ecm(c->cdev->gadget))
+	if (use_eem)
+		return eem_bind_config(c);
+	else if (can_support_ecm(c->cdev->gadget))
 		return ecm_bind_config(c, hostaddr);
 	else
 		return geth_bind_config(c, hostaddr);
@@ -286,7 +306,12 @@
 		return status;
 
 	/* set up main config label and device descriptor */
-	if (can_support_ecm(cdev->gadget)) {
+	if (use_eem) {
+		/* EEM */
+		eth_config_driver.label = "CDC Ethernet (EEM)";
+		device_desc.idVendor = cpu_to_le16(EEM_VENDOR_NUM);
+		device_desc.idProduct = cpu_to_le16(EEM_PRODUCT_NUM);
+	} else if (can_support_ecm(cdev->gadget)) {
 		/* ECM */
 		eth_config_driver.label = "CDC Ethernet (ECM)";
 	} else {