Ole, can you verify this version works for you?  This version is slimmed
down (no kmalloc!) and includes a few missing pieces like Kconfig and hub.c
updates..

- Dave

From: Ole Andre Vadla Ravnas <[EMAIL PROTECTED]>

Windows Mobile 5 based devices described as supporting "ActiveSync":

 - Speak RNDIS but lack the CDC and union descriptors.  This patch
   updates the cdc ethernet code to fake ACM descriptors we need.

 - Require RNDIS_MSG_QUERY messages to include a buffer of the size the
   response should generate.  This patch updates the rndis host code to
   pass this will-be-ignored data.

The resulting RNDIS host code has been reported to work with several
WM5 based devices.

Signed-off-by: Ole Andre Vadla Ravnaas <[EMAIL PROTECTED]>

Cleanup, streamlining, bugfixes, Kconfig, and matching hub driver update.

Signed-off-by: David Brownell <[EMAIL PROTECTED]>

Index: g26/drivers/usb/net/cdc_ether.c
===================================================================
--- g26.orig/drivers/usb/net/cdc_ether.c	2006-06-28 22:02:21.000000000 -0700
+++ g26/drivers/usb/net/cdc_ether.c	2006-06-29 21:40:40.000000000 -0700
@@ -1,6 +1,7 @@
 /*
  * CDC Ethernet based networking peripherals
  * Copyright (C) 2003-2005 by David Brownell
+ * Copyrignt (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync)
  *
  * 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
@@ -36,6 +37,29 @@
 #include "usbnet.h"
 
 
+#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
+
+static int is_rndis(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceClass == USB_CLASS_COMM
+		&& desc->bInterfaceSubClass == 2
+		&& desc->bInterfaceProtocol == 0xff;
+}
+
+static int is_activesync(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceClass == USB_CLASS_MISC
+		&& desc->bInterfaceSubClass == 1
+		&& desc->bInterfaceProtocol == 1;
+}
+
+#else
+
+#define is_rndis(desc)		0
+#define is_activesync(desc)	0
+
+#endif
+
 /*
  * probes control interface, claims data interface, collects the bulk
  * endpoints, activates data interface (if needed), maybe sets MTU.
@@ -72,7 +96,7 @@ int usbnet_generic_cdc_bind(struct usbne
 	/* this assumes that if there's a non-RNDIS vendor variant
 	 * of cdc-acm, it'll fail RNDIS requests cleanly.
 	 */
-	rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff);
+	rndis = is_rndis(&intf->cur_altsetting->desc);
 
 	memset(info, 0, sizeof *info);
 	info->control = intf;
@@ -172,7 +196,26 @@ next_desc:
 		buf += buf [0];
 	}
 
-	if (!info->header || !info->u || (!rndis && !info->ether)) {
+	/* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors,
+	 * so we'll hard-wire the interfaces and not check for descriptors.
+	 */
+	if (is_activesync(&intf->cur_altsetting->desc)) {
+		rndis = 1;
+
+		/* initialize */
+		info->control = usb_ifnum_to_if(dev->udev, 0);
+		info->data = usb_ifnum_to_if(dev->udev, 1);
+		if (!info->control || !info->data) {
+			dev_dbg(&intf->dev,
+				"activesync: master #%u/%p slave #%u/%p\n",
+				info->u->bMasterInterface0,
+				info->control,
+				info->u->bSlaveInterface0,
+				info->data);
+			goto bad_desc;
+		}
+
+	} else if (!info->header || !info->u || (!rndis && !info->ether)) {
 		dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n",
 			info->header ? "" : "header ",
 			info->u ? "" : "union ",
Index: g26/drivers/usb/net/rndis_host.c
===================================================================
--- g26.orig/drivers/usb/net/rndis_host.c	2006-06-28 22:02:21.000000000 -0700
+++ g26/drivers/usb/net/rndis_host.c	2006-06-29 21:32:29.000000000 -0700
@@ -50,6 +50,8 @@
  *    - In some cases, MS-Windows will emit undocumented requests; this
  *	matters more to peripheral implementations than host ones.
  *
+ * Moreover there's a no-open-specs variant of RNDIS called "ActiveSync".
+ *
  * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in
  * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and
  * currently rare) "Ethernet Emulation Model" (EEM).
@@ -423,11 +425,19 @@ fail:
 	dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu,
 		1 << le32_to_cpu(u.init_c->packet_alignment));
 
-	/* get designated host ethernet address */
-	memset(u.get, 0, sizeof *u.get);
+	/* Get designated host ethernet address.
+	 *
+	 * Adding a payload exactly the same size as the expected response
+	 * payload is an evident requirement MSFT added for ActiveSync.
+	 * This undocumented (and nonsensical) issue was found by sniffing
+	 * protocol requests from the ActiveSync 4.1 Windows driver.
+	 */
+	memset(u.get, 0, sizeof *u.get + 48);
 	u.get->msg_type = RNDIS_MSG_QUERY;
-	u.get->msg_len = ccpu2(sizeof *u.get);
+	u.get->msg_len = ccpu2(sizeof *u.get + 48);
 	u.get->oid = OID_802_3_PERMANENT_ADDRESS;
+	u.get->len = ccpu2(48);
+	u.get->offset = ccpu2(20);
 
 	retval = rndis_command(dev, u.header);
 	if (unlikely(retval < 0)) {
@@ -594,6 +604,10 @@ static const struct usb_device_id	produc
 	/* RNDIS is MSFT's un-official variant of CDC ACM */
 	USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
 	.driver_info = (unsigned long) &rndis_info,
+}, {
+	/* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
+	USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
+	.driver_info = (unsigned long) &rndis_info,
 },
 	{ },		// END
 };
Index: g26/include/linux/usb_ch9.h
===================================================================
--- g26.orig/include/linux/usb_ch9.h	2006-06-29 10:13:25.000000000 -0700
+++ g26/include/linux/usb_ch9.h	2006-06-29 10:55:55.000000000 -0700
@@ -217,6 +217,7 @@ struct usb_device_descriptor {
 #define USB_CLASS_CONTENT_SEC		0x0d	/* content security */
 #define USB_CLASS_VIDEO			0x0e
 #define USB_CLASS_WIRELESS_CONTROLLER	0xe0
+#define USB_CLASS_MISC			0xef
 #define USB_CLASS_APP_SPEC		0xfe
 #define USB_CLASS_VENDOR_SPEC		0xff
 
Index: g26/drivers/usb/net/Kconfig
===================================================================
--- g26.orig/drivers/usb/net/Kconfig	2006-06-28 22:02:21.000000000 -0700
+++ g26/drivers/usb/net/Kconfig	2006-06-29 20:57:42.000000000 -0700
@@ -208,13 +208,15 @@ config USB_NET_PLUSB
 	  with one of these chips.
 
 config USB_NET_RNDIS_HOST
-	tristate "Host for RNDIS devices (EXPERIMENTAL)"
+	tristate "Host for RNDIS and ActiveSync devices (EXPERIMENTAL)"
 	depends on USB_USBNET && EXPERIMENTAL
 	select USB_NET_CDCETHER
 	help
 	  This option enables hosting "Remote NDIS" USB networking links,
 	  as encouraged by Microsoft (instead of CDC Ethernet!) for use in
-	  various devices that may only support this protocol.
+	  various devices that may only support this protocol.  A variant
+	  of this protocol (with even less public documentation) seems to
+	  be at the root of Microsoft's "Active Sync" too.
 
 	  Avoid using this protocol unless you have no better options.
 	  The protocol specification is incomplete, and is controlled by
Index: g26/drivers/usb/core/hub.c
===================================================================
--- g26.orig/drivers/usb/core/hub.c	2006-06-29 10:13:26.000000000 -0700
+++ g26/drivers/usb/core/hub.c	2006-06-29 21:43:39.000000000 -0700
@@ -1176,6 +1176,21 @@ static inline const char *plural(int n)
 	return (n == 1 ? "" : "s");
 }
 
+static int is_rndis(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceClass == USB_CLASS_COMM
+		&& desc->bInterfaceSubClass == 2
+		&& desc->bInterfaceProtocol == 0xff;
+}
+
+static int is_activesync(struct usb_interface_descriptor *desc)
+{
+	return desc->bInterfaceClass == USB_CLASS_MISC
+		&& desc->bInterfaceSubClass == 1
+		&& desc->bInterfaceProtocol == 1;
+}
+
+
 static int choose_configuration(struct usb_device *udev)
 {
 	int i;
@@ -1238,19 +1253,16 @@ static int choose_configuration(struct u
 			continue;
 		}
 
-		/* If the first config's first interface is COMM/2/0xff
-		 * (MSFT RNDIS), rule it out unless Linux has host-side
-		 * RNDIS support. */
-		if (i == 0 && desc
-				&& desc->bInterfaceClass == USB_CLASS_COMM
-				&& desc->bInterfaceSubClass == 2
-				&& desc->bInterfaceProtocol == 0xff) {
-#ifndef CONFIG_USB_NET_RNDIS_HOST
-			continue;
-#else
+		/* When the first config's first interface is one of Microsoft's
+		 * pet nonstandard Ethernet-over-USB protocols, ignore it unless
+		 * this kernel has enabled the necessary host side driver.
+		 */
+		if (i == 0 && desc && (is_rndis(desc) || is_activesync(desc)))
+#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
 			best = c;
+#else
+			continue;
 #endif
-		}
 
 		/* From the remaining configs, choose the first one whose
 		 * first interface is for a non-vendor-specific class.
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to