aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/net/cdc_ether.c
diff options
context:
space:
mode:
authorOle Andre Vadla Ravnas <oleavr@gmail.com>2006-12-14 19:01:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:44:33 -0500
commitad55d71a3d4401f44b4ddee1412283c99eedd05c (patch)
treea416fe386d740506b01667d47466e6708f8a2388 /drivers/usb/net/cdc_ether.c
parent11d5489873facd395653a4ee14669751bfe9bab5 (diff)
rndis_host learns ActiveSync basics
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. (Note that a fancier patch is available at synce.sf.net.) Some bugfixes, affecting not just ActiveSync: (a) when cleaning up after RNDS init fails, scrub the second interface just like cdc_ether does, so disconnect won't oops. (b) handle peripherals that use the pad-to-end-of-packet option; some devices can't talk to us if that option doesn't work. (c) when choosing configurations, don't forget about an RNDIS config just because the RNDIS driver is dynamically linked. Cleanup, streamlining, bugfixes, Kconfig, and matching hub driver update. Also for paranoia's sake, refuse to talk to something that looks like a real modem instead of RNDIS. Signed-off-by: Ole Andre Vadla Ravnaas <oleavr@gmail.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/net/cdc_ether.c')
-rw-r--r--drivers/usb/net/cdc_ether.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index 44a91547146e..e5cdafa258dd 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * CDC Ethernet based networking peripherals 2 * CDC Ethernet based networking peripherals
3 * Copyright (C) 2003-2005 by David Brownell 3 * Copyright (C) 2003-2005 by David Brownell
4 * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync)
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -35,6 +36,29 @@
35#include "usbnet.h" 36#include "usbnet.h"
36 37
37 38
39#if defined(CONFIG_USB_NET_RNDIS_HOST) || defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
40
41static int is_rndis(struct usb_interface_descriptor *desc)
42{
43 return desc->bInterfaceClass == USB_CLASS_COMM
44 && desc->bInterfaceSubClass == 2
45 && desc->bInterfaceProtocol == 0xff;
46}
47
48static int is_activesync(struct usb_interface_descriptor *desc)
49{
50 return desc->bInterfaceClass == USB_CLASS_MISC
51 && desc->bInterfaceSubClass == 1
52 && desc->bInterfaceProtocol == 1;
53}
54
55#else
56
57#define is_rndis(desc) 0
58#define is_activesync(desc) 0
59
60#endif
61
38/* 62/*
39 * probes control interface, claims data interface, collects the bulk 63 * probes control interface, claims data interface, collects the bulk
40 * endpoints, activates data interface (if needed), maybe sets MTU. 64 * endpoints, activates data interface (if needed), maybe sets MTU.
@@ -71,7 +95,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
71 /* this assumes that if there's a non-RNDIS vendor variant 95 /* this assumes that if there's a non-RNDIS vendor variant
72 * of cdc-acm, it'll fail RNDIS requests cleanly. 96 * of cdc-acm, it'll fail RNDIS requests cleanly.
73 */ 97 */
74 rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); 98 rndis = is_rndis(&intf->cur_altsetting->desc)
99 || is_activesync(&intf->cur_altsetting->desc);
75 100
76 memset(info, 0, sizeof *info); 101 memset(info, 0, sizeof *info);
77 info->control = intf; 102 info->control = intf;
@@ -99,6 +124,23 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
99 goto bad_desc; 124 goto bad_desc;
100 } 125 }
101 break; 126 break;
127 case USB_CDC_ACM_TYPE:
128 /* paranoia: disambiguate a "real" vendor-specific
129 * modem interface from an RNDIS non-modem.
130 */
131 if (rndis) {
132 struct usb_cdc_acm_descriptor *d;
133
134 d = (void *) buf;
135 if (d->bmCapabilities) {
136 dev_dbg(&intf->dev,
137 "ACM capabilities %02x, "
138 "not really RNDIS?\n",
139 d->bmCapabilities);
140 goto bad_desc;
141 }
142 }
143 break;
102 case USB_CDC_UNION_TYPE: 144 case USB_CDC_UNION_TYPE:
103 if (info->u) { 145 if (info->u) {
104 dev_dbg(&intf->dev, "extra CDC union\n"); 146 dev_dbg(&intf->dev, "extra CDC union\n");
@@ -171,7 +213,21 @@ next_desc:
171 buf += buf [0]; 213 buf += buf [0];
172 } 214 }
173 215
174 if (!info->header || !info->u || (!rndis && !info->ether)) { 216 /* Microsoft ActiveSync based RNDIS devices lack the CDC descriptors,
217 * so we'll hard-wire the interfaces and not check for descriptors.
218 */
219 if (is_activesync(&intf->cur_altsetting->desc) && !info->u) {
220 info->control = usb_ifnum_to_if(dev->udev, 0);
221 info->data = usb_ifnum_to_if(dev->udev, 1);
222 if (!info->control || !info->data) {
223 dev_dbg(&intf->dev,
224 "activesync: master #0/%p slave #1/%p\n",
225 info->control,
226 info->data);
227 goto bad_desc;
228 }
229
230 } else if (!info->header || !info->u || (!rndis && !info->ether)) {
175 dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", 231 dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n",
176 info->header ? "" : "header ", 232 info->header ? "" : "header ",
177 info->u ? "" : "union ", 233 info->u ? "" : "union ",