Subject: USB: usbnet (6/9) module for Zaurii and compatibles

From: David Brownell <[email-masked]>
Date: Sat, 13 Aug 2005 14:12:10 -0700

These run Linux inside, but rather gratuitously they all
break the CDC standards they claim to conform to.
This moves usbnet support for Zaurus and compatibles into its own module.
Other than exporting a couple of helper functions, this just involved
shuffling some code and updating the comments.

Signed-off-by: David Brownell <[email-masked]>
Signed-off-by: Greg Kroah-Hartman <[email-masked]>

---
 drivers/usb/net/Kconfig  |   33 +---
 drivers/usb/net/Makefile |    1 
 drivers/usb/net/usbnet.c |  349 ------------------------------------------
 drivers/usb/net/usbnet.h |   31 +++
 drivers/usb/net/zaurus.c |  385 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 440 insertions(+), 359 deletions(-)

--- gregkh-2.6.orig/drivers/usb/net/Makefile	2005-08-15 17:51:22.000000000 -0700
+++ gregkh-2.6/drivers/usb/net/Makefile	2005-08-15 17:51:23.000000000 -0700
@@ -10,6 +10,7 @@
 obj-$(CONFIG_USB_NET_GL620A)	+= gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)	+= net1080.o
 obj-$(CONFIG_USB_NET_SIMPLE)	+= simple.o
+obj-$(CONFIG_USB_NET_ZAURUS)	+= zaurus.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
 obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 
--- gregkh-2.6.orig/drivers/usb/net/Kconfig	2005-08-15 17:51:22.000000000 -0700
+++ gregkh-2.6/drivers/usb/net/Kconfig	2005-08-15 17:51:23.000000000 -0700
@@ -140,23 +140,6 @@
 comment "Intelligent USB Devices/Gadgets"
 	depends on USB_USBNET
 
-config USB_ZAURUS
-	boolean "Sharp Zaurus (stock ROMs) and compatible"
-	depends on USB_USBNET
-	select CRC32
-	default y
-	help
-	  Choose this option to support the usb networking links used by
-	  Zaurus models like the SL-5000D, SL-5500, SL-5600, A-300, B-500.
-	  This also supports some related device firmware, as used in some
-	  PDAs from Olympus and some cell phones from Motorola.
-
-	  If you install an alternate ROM image, such as the Linux 2.6 based
-	  versions of OpenZaurus, you should no longer need to support this
-	  protocol.  Only the "eth-fd" or "net_fd" drivers in these devices
-	  really need this non-conformant variant of CDC Ethernet (or in
-	  some cases CDC MDLM) protocol, not "g_ether".
-
 config USB_CDCETHER
 	boolean "CDC Ethernet support (smart devices such as cable modems)"
 	depends on USB_USBNET
@@ -297,6 +280,22 @@
 	  Choose this option to support the usb networking links used
 	  by some sample firmware from Epson.
 
+config USB_NET_ZAURUS
+	tristate "Sharp Zaurus (stock ROMs) and compatible"
+	depends on USB_USBNET
+	select CRC32
+	help
+	  Choose this option to support the usb networking links used by
+	  Zaurus models like the SL-5000D, SL-5500, SL-5600, A-300, B-500.
+	  This also supports some related device firmware, as used in some
+	  PDAs from Olympus and some cell phones from Motorola.
+
+	  If you install an alternate ROM image, such as the Linux 2.6 based
+	  versions of OpenZaurus, you should no longer need to support this
+	  protocol.  Only the "eth-fd" or "net_fd" drivers in these devices
+	  really need this non-conformant variant of CDC Ethernet (or in
+	  some cases CDC MDLM) protocol, not "g_ether".
+
 
 config USB_ZD1201
 	tristate "USB ZD1201 based Wireless device support"
--- gregkh-2.6.orig/drivers/usb/net/usbnet.h	2005-08-15 17:50:22.000000000 -0700
+++ gregkh-2.6/drivers/usb/net/usbnet.h	2005-08-15 17:51:23.000000000 -0700
@@ -122,6 +122,37 @@
 extern void usbnet_disconnect(struct usb_interface *);

+/* Drivers that reuse some of the standard USB CDC infrastructure
+ * (notably, using multiple interfaces according to the the CDC
+ * union descriptor) get some helper code.
+ */
+struct cdc_state {
+	struct usb_cdc_header_desc	*header;
+	struct usb_cdc_union_desc	*u;
+	struct usb_cdc_ether_desc	*ether;
+	struct usb_interface		*control;
+	struct usb_interface		*data;
+};
+
+extern int usbnet_generic_cdc_bind (struct usbnet *, struct usb_interface *);
+extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
+
+static inline struct usb_driver *driver_of(struct usb_interface *intf)
+{
+	struct device_driver	*drv = intf->dev.driver;
+
+	if (!drv)
+		return NULL;
+	return to_usb_driver(drv);
+}
+
+/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
+#define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
+ 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ 			|USB_CDC_PACKET_TYPE_DIRECTED)
+
+
 /* we record the state for each of our queued skbs */
 enum skb_state {
 	illegal = 0,
--- gregkh-2.6.orig/drivers/usb/net/usbnet.c	2005-08-15 17:51:22.000000000 -0700
+++ gregkh-2.6/drivers/usb/net/usbnet.c	2005-08-15 17:51:23.000000000 -0700
@@ -1,7 +1,6 @@
 /*
  * USB Networking Links
  * Copyright (C) 2000-2005 by David Brownell
- * Copyright (C) 2002 Pavel Machek <[email-masked]>
  * Copyright (C) 2003-2005 David Hollis <[email-masked]>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -169,14 +168,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static u32 usbnet_get_link (struct net_device *);
-
-/* mostly for PDA style devices, which are always connected if present */
-static int always_connected (struct usbnet *dev)
-{
-	return 0;
-}
-
 /* handles CDC Ethernet and many other network "bulk data" interfaces */
 int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
 {
@@ -317,7 +308,7 @@
 #define NEED_GENERIC_CDC
 #endif
 
-#ifdef	CONFIG_USB_ZAURUS
+#if defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_ZAURUS_MODULE)
 /* Ethernet variant uses funky framing, broken ethernet addressing */
 #define NEED_GENERIC_CDC
 #endif
@@ -347,7 +338,7 @@
  * endpoints, activates data interface (if needed), maybe sets MTU.
  * all pure cdc, except for certain firmware workarounds.
  */
-static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
+int usbnet_generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 {
 	u8				*buf = intf->cur_altsetting->extra;
 	int				len = intf->cur_altsetting->extralen;
@@ -526,8 +517,9 @@
 	dev_info (&dev->udev->dev, "bad CDC descriptors\n");
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
 
-static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
+void usbnet_cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
 {
 	struct cdc_state		*info = (void *) &dev->data;
 
@@ -547,6 +539,7 @@
 		info->control = NULL;
 	}
 }
+EXPORT_SYMBOL_GPL(usbnet_cdc_unbind);
 
 #endif	/* NEED_GENERIC_CDC */
 
@@ -653,7 +646,7 @@
 	int				status;
 	struct cdc_state		*info = (void *) &dev->data;
 
-	status = generic_cdc_bind (dev, intf);
+	status = usbnet_generic_cdc_bind (dev, intf);
 	if (status < 0)
 		return status;
 
@@ -675,7 +668,7 @@
 	.flags =	FLAG_ETHER,
 	// .check_connect = cdc_check_connect,
 	.bind =		cdc_bind,
-	.unbind =	cdc_unbind,
+	.unbind =	usbnet_cdc_unbind,
 	.status =	cdc_status,
 };
 
@@ -754,239 +747,6 @@
 #endif /* CONFIG_USB_PL2301 */
 
 
-#ifdef CONFIG_USB_ZAURUS
-#define	HAVE_HARDWARE
-
-#include <linux/crc32.h>
-
-/*-------------------------------------------------------------------------
- *
- * Zaurus is also a SA-1110 based PDA, but one using a different driver
- * (and framing) for its USB slave/gadget controller than the case above.
- *
- * For the current version of that driver, the main way that framing is
- * nonstandard (also from perspective of the CDC ethernet model!) is a
- * crc32, added to help detect when some sa1100 usb-to-memory DMA errata
- * haven't been fully worked around.  Also, all Zaurii use the same
- * default Ethernet address.
- *
- * PXA based models use the same framing, and also can't implement
- * set_interface properly.
- *
- * All known Zaurii lie about their standards conformance.  Most lie by
- * saying they support CDC Ethernet.  Some lie and say they support CDC
- * MDLM (as if for access to cell phone modems).  Someone, please beat 
- * on Sharp (and other such vendors) for a while with a cluestick.
- *
- *-------------------------------------------------------------------------*/
-
-static struct sk_buff *
-zaurus_tx_fixup (struct usbnet *dev, struct sk_buff *skb, unsigned flags)
-{
-	int			padlen;
-	struct sk_buff		*skb2;
-
-	padlen = 2;
-	if (!skb_cloned (skb)) {
-		int	tailroom = skb_tailroom (skb);
-		if ((padlen + 4) <= tailroom)
-			goto done;
-	}
-	skb2 = skb_copy_expand (skb, 0, 4 + padlen, flags);
-	dev_kfree_skb_any (skb);
-	skb = skb2;
-	if (skb) {
-		u32		fcs;
-done:
-		fcs = crc32_le (~0, skb->data, skb->len);
-		fcs = ~fcs;
-
-		*skb_put (skb, 1) = fcs       & 0xff;
-		*skb_put (skb, 1) = (fcs>> 8) & 0xff;
-		*skb_put (skb, 1) = (fcs>>16) & 0xff;
-		*skb_put (skb, 1) = (fcs>>24) & 0xff;
-	}
-	return skb;
-}
-
-static int zaurus_bind (struct usbnet *dev, struct usb_interface *intf)
-{
-	/* Belcarra's funky framing has other options; mostly
-	 * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
-	 */
-	dev->net->hard_header_len += 6;
-	return generic_cdc_bind(dev, intf);
-}
-
-static const struct driver_info	zaurus_sl5x00_info = {
-	.description =	"Sharp Zaurus SL-5x00",
-	.flags =	FLAG_FRAMING_Z,
-	.check_connect = usbnet_always_connected,
-	.bind =		zaurus_bind,
-	.unbind =	cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
-};
-#define	ZAURUS_STRONGARM_INFO	((unsigned long)&zaurus_sl5x00_info)
-
-static const struct driver_info	zaurus_pxa_info = {
-	.description =	"Sharp Zaurus, PXA-2xx based",
-	.flags =	FLAG_FRAMING_Z,
-	.check_connect = usbnet_always_connected,
-	.bind =		zaurus_bind,
-	.unbind =	cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
-};
-#define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
-
-static const struct driver_info	olympus_mxl_info = {
-	.description =	"Olympus R1000",
-	.flags =	FLAG_FRAMING_Z,
-	.check_connect = usbnet_always_connected,
-	.bind =		zaurus_bind,
-	.unbind =	cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
-};
-#define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)
-
-
-/* Some more recent products using Lineo/Belcarra code will wrongly claim
- * CDC MDLM conformance.  They aren't conformant:  data endpoints live
- * in the control interface, there's no data interface, and it's not used
- * to talk to a cell phone radio.  But at least we can detect these two
- * pseudo-classes, rather than growing this product list with entries for
- * each new nonconformant product (sigh).
- */
-static const u8 safe_guid[16] = {
-	0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
-	0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
-};
-static const u8 blan_guid[16] = {
-	0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
-	0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
-};
-
-static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
-{
-	u8				*buf = intf->cur_altsetting->extra;
-	int				len = intf->cur_altsetting->extralen;
-	struct usb_cdc_mdlm_desc	*desc = NULL;
-	struct usb_cdc_mdlm_detail_desc	*detail = NULL;
-
-	while (len > 3) {
-		if (buf [1] != USB_DT_CS_INTERFACE)
-			goto next_desc;
-
-		/* use bDescriptorSubType, and just verify that we get a
-		 * "BLAN" (or "SAFE") descriptor.
-		 */
-		switch (buf [2]) {
-		case USB_CDC_MDLM_TYPE:
-			if (desc) {
-				dev_dbg (&intf->dev, "extra MDLM\n");
-				goto bad_desc;
-			}
-			desc = (void *) buf;
-			if (desc->bLength != sizeof *desc) {
-				dev_dbg (&intf->dev, "MDLM len %u\n",
-					desc->bLength);
-				goto bad_desc;
-			}
-			/* expect bcdVersion 1.0, ignore */
-			if (memcmp(&desc->bGUID, blan_guid, 16)
-				    && memcmp(&desc->bGUID, safe_guid, 16) ) {
-				/* hey, this one might _really_ be MDLM! */
-				dev_dbg (&intf->dev, "MDLM guid\n");
-				goto bad_desc;
-			}
-			break;
-		case USB_CDC_MDLM_DETAIL_TYPE:
-			if (detail) {
-				dev_dbg (&intf->dev, "extra MDLM detail\n");
-				goto bad_desc;
-			}
-			detail = (void *) buf;
-			switch (detail->bGuidDescriptorType) {
-			case 0:			/* "SAFE" */
-				if (detail->bLength != (sizeof *detail + 2))
-					goto bad_detail;
-				break;
-			case 1:			/* "BLAN" */
-				if (detail->bLength != (sizeof *detail + 3))
-					goto bad_detail;
-				break;
-			default:
-				goto bad_detail;
-			}
-
-			/* assuming we either noticed BLAN already, or will
-			 * find it soon, there are some data bytes here:
-			 *  - bmNetworkCapabilities (unused)
-			 *  - bmDataCapabilities (bits, see below)
-			 *  - bPad (ignored, for PADAFTER -- BLAN-only)
-			 * bits are:
-			 *  - 0x01 -- Zaurus framing (add CRC)
-			 *  - 0x02 -- PADBEFORE (CRC includes some padding)
-			 *  - 0x04 -- PADAFTER (some padding after CRC)
-			 *  - 0x08 -- "fermat" packet mangling (for hw bugs)
-			 * the PADBEFORE appears not to matter; we interop
-			 * with devices that use it and those that don't.
-			 */
-			if ((detail->bDetailData[1] & ~02) != 0x01) {
-				/* bmDataCapabilites == 0 would be fine too,
-				 * but framing is minidriver-coupled for now.
-				 */
-bad_detail:
-				dev_dbg (&intf->dev,
-						"bad MDLM detail, %d %d %d\n",
-						detail->bLength,
-						detail->bDetailData[0],
-						detail->bDetailData[2]);
-				goto bad_desc;
-			}
-			break;
-		}
-next_desc:
-		len -= buf [0];	/* bLength */
-		buf += buf [0];
-	}
-
-	if (!desc || !detail) {
-		dev_dbg (&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
-			desc ? "" : "func ",
-			detail ? "" : "detail ");
-		goto bad_desc;
-	}
-
-	/* There's probably a CDC Ethernet descriptor there, but we can't
-	 * rely on the Ethernet address it provides since not all vendors
-	 * bother to make it unique.  Likewise there's no point in tracking
-	 * of the CDC event notifications.
-	 */
-	return usbnet_get_endpoints (dev, intf);
-
-bad_desc:
-	dev_info (&dev->udev->dev, "unsupported MDLM descriptors\n");
-	return -ENODEV;
-}
-
-static const struct driver_info	bogus_mdlm_info = {
-	.description =	"pseudo-MDLM (BLAN) device",
-	.flags =	FLAG_FRAMING_Z,
-	.check_connect = usbnet_always_connected,
-	.tx_fixup = 	zaurus_tx_fixup,
-	.bind =		blan_mdlm_bind,
-};
-
-#else
-
-/* blacklist all those devices */
-#define	ZAURUS_STRONGARM_INFO	0
-#define	ZAURUS_PXA_INFO		0
-#define	OLYMPUS_MXL_INFO	0
-
-#endif
-
-
 /*-------------------------------------------------------------------------
  *
  * Network Device Driver (peer link to "Host Device", from USB host)
@@ -1985,101 +1745,6 @@
 },
 #endif
 
-#if	defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_CDCETHER)
-/*
- * SA-1100 based Sharp Zaurus ("collie"), or compatible.
- * Same idea as above, but different framing.
- *
- * PXA-2xx based models are also lying-about-cdc.
- * Some models don't even tell the same lies ...
- *
- * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
- * unlike the older ones with 2.4 "embedix" kernels.
- *
- * NOTE:  These entries do double-duty, serving as blacklist entries
- * whenever Zaurus support isn't enabled, but CDC Ethernet is.
- */
-#define	ZAURUS_MASTER_INTERFACE \
-	.bInterfaceClass	= USB_CLASS_COMM, \
-	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
-	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
-{
-	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
-			  | USB_DEVICE_ID_MATCH_DEVICE, 
-	.idVendor		= 0x04DD,
-	.idProduct		= 0x8004,
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_STRONGARM_INFO,
-}, {
-	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
-			  | USB_DEVICE_ID_MATCH_DEVICE, 
-	.idVendor		= 0x04DD,
-	.idProduct		= 0x8005,	/* A-300 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-}, {
-	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
-			  | USB_DEVICE_ID_MATCH_DEVICE, 
-	.idVendor		= 0x04DD,
-	.idProduct		= 0x8006,	/* B-500/SL-5600 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-}, {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-	          | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor		= 0x04DD,
-	.idProduct		= 0x8007,	/* C-700 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-}, {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x04DD,
-	.idProduct              = 0x9031,	/* C-750 C-760 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-}, {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x04DD,
-	.idProduct              = 0x9032,	/* SL-6000 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-}, {
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x04DD,
-	/* reported with some C860 units */
-	.idProduct              = 0x9050,	/* C-860 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = ZAURUS_PXA_INFO,
-},
-
-#ifdef	CONFIG_USB_ZAURUS
-	/* At least some (reports vary) PXA units have very different lies
-	 * about their standards support:  they claim to be cell phones with
-	 * direct access to their radios.  (They don't conform to CDC MDLM.)
-	 */
-{
-	USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
-			USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long) &bogus_mdlm_info,
-},
-#endif
-
-/* Olympus has some models with a Zaurus-compatible option.
- * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
- */
-{
-	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
-		 | USB_DEVICE_ID_MATCH_DEVICE,
-	.idVendor               = 0x07B4,
-	.idProduct              = 0x0F02,	/* R-1000 */
-	ZAURUS_MASTER_INTERFACE,
-	.driver_info = OLYMPUS_MXL_INFO,
-},
-#endif
-
 #ifdef	CONFIG_USB_CDCETHER
 {
 	/* CDC Ether uses two interfaces, not necessarily consecutive.
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gregkh-2.6/drivers/usb/net/zaurus.c	2005-08-15 17:51:23.000000000 -0700
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2002 Pavel Machek <[email-masked]>
+ * Copyright (C) 2002-2005 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+// #define	DEBUG			// error path messages, extra info
+// #define	VERBOSE			// more; success messages
+
+#include <linux/config.h>
+#ifdef	CONFIG_USB_DEBUG
+#   define DEBUG
+#endif
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/usb_cdc.h>
+
+#include "usbnet.h"
+
+
+/*
+ * All known Zaurii lie about their standards conformance.  At least
+ * the earliest SA-1100 models lie by saying they support CDC Ethernet.
+ * Some later models (especially PXA-25x and PXA-27x based ones) lie
+ * and say they support CDC MDLM (for access to cell phone modems).
+ *
+ * There are non-Zaurus products that use these same protocols too.
+ *
+ * The annoying thing is that at the same time Sharp was developing
+ * that annoying standards-breaking software, the Linux community had
+ * a simple "CDC Subset" working reliably on the same SA-1100 hardware.
+ * That is, the same functionality but not violating standards.
+ *
+ * The CDC Ethernet nonconformance points are troublesome to hosts
+ * with a true CDC Ethernet implementation:
+ *   - Framing appends a CRC, which the spec says drivers "must not" do;
+ *   - Transfers data in altsetting zero, instead of altsetting 1;
+ *   - All these peripherals use the same ethernet address.
+ *
+ * The CDC MDLM nonconformance is less immediately troublesome, since all
+ * MDLM implementations are quasi-proprietary anyway.
+ */
+
+static struct sk_buff *
+zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
+{
+	int			padlen;
+	struct sk_buff		*skb2;
+
+	padlen = 2;
+	if (!skb_cloned(skb)) {
+		int	tailroom = skb_tailroom(skb);
+		if ((padlen + 4) <= tailroom)
+			goto done;
+	}
+	skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags);
+	dev_kfree_skb_any(skb);
+	skb = skb2;
+	if (skb) {
+		u32		fcs;
+done:
+		fcs = crc32_le(~0, skb->data, skb->len);
+		fcs = ~fcs;
+
+		*skb_put (skb, 1) = fcs       & 0xff;
+		*skb_put (skb, 1) = (fcs>> 8) & 0xff;
+		*skb_put (skb, 1) = (fcs>>16) & 0xff;
+		*skb_put (skb, 1) = (fcs>>24) & 0xff;
+	}
+	return skb;
+}
+
+static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	/* Belcarra's funky framing has other options; mostly
+	 * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes.
+	 */
+	dev->net->hard_header_len += 6;
+	return usbnet_generic_cdc_bind(dev, intf);
+}
+
+/* PDA style devices are always connected if present */
+static int always_connected (struct usbnet *dev)
+{
+	return 0;
+}
+
+static const struct driver_info	zaurus_sl5x00_info = {
+	.description =	"Sharp Zaurus SL-5x00",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.bind =		zaurus_bind,
+	.unbind =	usbnet_cdc_unbind,
+	.tx_fixup = 	zaurus_tx_fixup,
+};
+#define	ZAURUS_STRONGARM_INFO	((unsigned long)&zaurus_sl5x00_info)
+
+static const struct driver_info	zaurus_pxa_info = {
+	.description =	"Sharp Zaurus, PXA-2xx based",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.bind =		zaurus_bind,
+	.unbind =	usbnet_cdc_unbind,
+	.tx_fixup = 	zaurus_tx_fixup,
+};
+#define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
+
+static const struct driver_info	olympus_mxl_info = {
+	.description =	"Olympus R1000",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.bind =		zaurus_bind,
+	.unbind =	usbnet_cdc_unbind,
+	.tx_fixup = 	zaurus_tx_fixup,
+};
+#define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)
+
+
+/* Some more recent products using Lineo/Belcarra code will wrongly claim
+ * CDC MDLM conformance.  They aren't conformant:  data endpoints live
+ * in the control interface, there's no data interface, and it's not used
+ * to talk to a cell phone radio.  But at least we can detect these two
+ * pseudo-classes, rather than growing this product list with entries for
+ * each new nonconformant product (sigh).
+ */
+static const u8 safe_guid[16] = {
+	0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
+	0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
+};
+static const u8 blan_guid[16] = {
+	0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70,
+	0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37,
+};
+
+static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	u8				*buf = intf->cur_altsetting->extra;
+	int				len = intf->cur_altsetting->extralen;
+	struct usb_cdc_mdlm_desc	*desc = NULL;
+	struct usb_cdc_mdlm_detail_desc	*detail = NULL;
+
+	while (len > 3) {
+		if (buf [1] != USB_DT_CS_INTERFACE)
+			goto next_desc;
+
+		/* use bDescriptorSubType, and just verify that we get a
+		 * "BLAN" (or "SAFE") descriptor.
+		 */
+		switch (buf [2]) {
+		case USB_CDC_MDLM_TYPE:
+			if (desc) {
+				dev_dbg(&intf->dev, "extra MDLM\n");
+				goto bad_desc;
+			}
+			desc = (void *) buf;
+			if (desc->bLength != sizeof *desc) {
+				dev_dbg(&intf->dev, "MDLM len %u\n",
+					desc->bLength);
+				goto bad_desc;
+			}
+			/* expect bcdVersion 1.0, ignore */
+			if (memcmp(&desc->bGUID, blan_guid, 16)
+				    && memcmp(&desc->bGUID, safe_guid, 16) ) {
+				/* hey, this one might _really_ be MDLM! */
+				dev_dbg(&intf->dev, "MDLM guid\n");
+				goto bad_desc;
+			}
+			break;
+		case USB_CDC_MDLM_DETAIL_TYPE:
+			if (detail) {
+				dev_dbg(&intf->dev, "extra MDLM detail\n");
+				goto bad_desc;
+			}
+			detail = (void *) buf;
+			switch (detail->bGuidDescriptorType) {
+			case 0:			/* "SAFE" */
+				if (detail->bLength != (sizeof *detail + 2))
+					goto bad_detail;
+				break;
+			case 1:			/* "BLAN" */
+				if (detail->bLength != (sizeof *detail + 3))
+					goto bad_detail;
+				break;
+			default:
+				goto bad_detail;
+			}
+
+			/* assuming we either noticed BLAN already, or will
+			 * find it soon, there are some data bytes here:
+			 *  - bmNetworkCapabilities (unused)
+			 *  - bmDataCapabilities (bits, see below)
+			 *  - bPad (ignored, for PADAFTER -- BLAN-only)
+			 * bits are:
+			 *  - 0x01 -- Zaurus framing (add CRC)
+			 *  - 0x02 -- PADBEFORE (CRC includes some padding)
+			 *  - 0x04 -- PADAFTER (some padding after CRC)
+			 *  - 0x08 -- "fermat" packet mangling (for hw bugs)
+			 * the PADBEFORE appears not to matter; we interop
+			 * with devices that use it and those that don't.
+			 */
+			if ((detail->bDetailData[1] & ~02) != 0x01) {
+				/* bmDataCapabilites == 0 would be fine too,
+				 * but framing is minidriver-coupled for now.
+				 */
+bad_detail:
+				dev_dbg(&intf->dev,
+						"bad MDLM detail, %d %d %d\n",
+						detail->bLength,
+						detail->bDetailData[0],
+						detail->bDetailData[2]);
+				goto bad_desc;
+			}
+			break;
+		}
+next_desc:
+		len -= buf [0];	/* bLength */
+		buf += buf [0];
+	}
+
+	if (!desc || !detail) {
+		dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n",
+			desc ? "" : "func ",
+			detail ? "" : "detail ");
+		goto bad_desc;
+	}
+
+	/* There's probably a CDC Ethernet descriptor there, but we can't
+	 * rely on the Ethernet address it provides since not all vendors
+	 * bother to make it unique.  Likewise there's no point in tracking
+	 * of the CDC event notifications.
+	 */
+	return usbnet_get_endpoints(dev, intf);
+
+bad_desc:
+	dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n");
+	return -ENODEV;
+}
+
+static const struct driver_info	bogus_mdlm_info = {
+	.description =	"pseudo-MDLM (BLAN) device",
+	.flags =	FLAG_FRAMING_Z,
+	.check_connect = always_connected,
+	.tx_fixup = 	zaurus_tx_fixup,
+	.bind =		blan_mdlm_bind,
+};
+
+static const struct usb_device_id	products [] = {
+#define	ZAURUS_MASTER_INTERFACE \
+	.bInterfaceClass	= USB_CLASS_COMM, \
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
+
+/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
+{
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8004,
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_STRONGARM_INFO,
+},
+
+/* PXA-2xx based models are also lying-about-cdc.  If you add any
+ * more devices that claim to be CDC Ethernet, make sure they get
+ * added to the blacklist in cdc_ether too.
+ *
+ * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
+ * unlike the older ones with 2.4 "embedix" kernels.
+ */
+{
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8005,	/* A-300 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+}, {
+	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8006,	/* B-500/SL-5600 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+	          | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8007,	/* C-700 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	.idProduct              = 0x9031,	/* C-750 C-760 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	.idProduct              = 0x9032,	/* SL-6000 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
+	/* reported with some C860 units */
+	.idProduct              = 0x9050,	/* C-860 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = ZAURUS_PXA_INFO,
+},
+
+
+/* At least some of the newest PXA units have very different lies about
+ * their standards support:  they claim to be cell phones offering
+ * direct access to their radios!  (No, they don't conform to CDC MDLM.)
+ */
+{
+	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
+			USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long) &bogus_mdlm_info,
+},
+
+/* Olympus has some models with a Zaurus-compatible option.
+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
+ */
+{
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x07B4,
+	.idProduct              = 0x0F02,	/* R-1000 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info = OLYMPUS_MXL_INFO,
+},
+	{ },		// END
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver zaurus_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"zaurus",
+	.id_table =	products,
+	.probe =	usbnet_probe,
+	.disconnect =	usbnet_disconnect,
+	.suspend =	usbnet_suspend,
+	.resume =	usbnet_resume,
+};
+
+static int __init zaurus_init(void)
+{
+ 	return usb_register(&zaurus_driver);
+}
+module_init(zaurus_init);
+
+static void __exit zaurus_exit(void)
+{
+ 	usb_deregister(&zaurus_driver);
+}
+module_exit(zaurus_exit);
+
+MODULE_AUTHOR("Pavel Machek, David Brownell");
+MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products");
+MODULE_LICENSE("GPL");