diff options
author | David Brownell <david-b@pacbell.net> | 2005-08-31 12:54:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-08 19:28:32 -0400 |
commit | 4324fd493430c0ab99dd7e89d50540b5e70f8098 (patch) | |
tree | 66f1d16d895fd660ad8d5c7279e8bd08e6787eb8 | |
parent | 0aa599c5644fddd3052433c5335260108a8a39a2 (diff) |
[PATCH] USB: usbnet (7/9) module for CDC Ethernet
Makes the CDC Ethernet support live in a separate driver module.
This module is a bit special since it exports utility functions
that are reused by the the Zaurus and RNDIS drivers, but it's
not "core" like usbnet itself.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/net/Kconfig | 56 | ||||
-rw-r--r-- | drivers/usb/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/net/cdc_ether.c | 509 | ||||
-rw-r--r-- | drivers/usb/net/usbnet.c | 392 |
4 files changed, 537 insertions, 421 deletions
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 20de10916a4e..4921101d93d0 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig | |||
@@ -137,35 +137,6 @@ config USB_PL2301 | |||
137 | Choose this option if you're using a host-to-host cable | 137 | Choose this option if you're using a host-to-host cable |
138 | with one of these chips. | 138 | with one of these chips. |
139 | 139 | ||
140 | comment "Intelligent USB Devices/Gadgets" | ||
141 | depends on USB_USBNET | ||
142 | |||
143 | config USB_CDCETHER | ||
144 | boolean "CDC Ethernet support (smart devices such as cable modems)" | ||
145 | depends on USB_USBNET | ||
146 | default y | ||
147 | help | ||
148 | This option supports devices conforming to the Communication Device | ||
149 | Class (CDC) Ethernet Control Model, a specification that's easy to | ||
150 | implement in device firmware. The CDC specifications are available | ||
151 | from <http://www.usb.org/>. | ||
152 | |||
153 | CDC Ethernet is an implementation option for DOCSIS cable modems | ||
154 | that support USB connectivity, used for non-Microsoft USB hosts. | ||
155 | The Linux-USB CDC Ethernet Gadget driver is an open implementation. | ||
156 | This driver should work with at least the following devices: | ||
157 | |||
158 | * Ericsson PipeRider (all variants) | ||
159 | * Motorola (DM100 and SB4100) | ||
160 | * Broadcom Cable Modem (reference design) | ||
161 | * Toshiba PCX1100U | ||
162 | * ... | ||
163 | |||
164 | This driver creates an interface named "ethX", where X depends on | ||
165 | what other networking devices you have in use. However, if the | ||
166 | IEEE 802 "local assignment" bit is set in the address, a "usbX" | ||
167 | name is used instead. | ||
168 | |||
169 | comment "Drivers built using the usbnet core" | 140 | comment "Drivers built using the usbnet core" |
170 | 141 | ||
171 | config USB_NET_AX8817X | 142 | config USB_NET_AX8817X |
@@ -197,6 +168,32 @@ config USB_NET_AX8817X | |||
197 | what other networking devices you have in use. | 168 | what other networking devices you have in use. |
198 | 169 | ||
199 | 170 | ||
171 | config USB_NET_CDCETHER | ||
172 | tristate "CDC Ethernet support (smart devices such as cable modems)" | ||
173 | depends on USB_USBNET | ||
174 | default y | ||
175 | help | ||
176 | This option supports devices conforming to the Communication Device | ||
177 | Class (CDC) Ethernet Control Model, a specification that's easy to | ||
178 | implement in device firmware. The CDC specifications are available | ||
179 | from <http://www.usb.org/>. | ||
180 | |||
181 | CDC Ethernet is an implementation option for DOCSIS cable modems | ||
182 | that support USB connectivity, used for non-Microsoft USB hosts. | ||
183 | The Linux-USB CDC Ethernet Gadget driver is an open implementation. | ||
184 | This driver should work with at least the following devices: | ||
185 | |||
186 | * Ericsson PipeRider (all variants) | ||
187 | * Motorola (DM100 and SB4100) | ||
188 | * Broadcom Cable Modem (reference design) | ||
189 | * Toshiba PCX1100U | ||
190 | * ... | ||
191 | |||
192 | This driver creates an interface named "ethX", where X depends on | ||
193 | what other networking devices you have in use. However, if the | ||
194 | IEEE 802 "local assignment" bit is set in the address, a "usbX" | ||
195 | name is used instead. | ||
196 | |||
200 | config USB_NET_GL620A | 197 | config USB_NET_GL620A |
201 | tristate "GeneSys GL620USB-A based cables" | 198 | tristate "GeneSys GL620USB-A based cables" |
202 | depends on USB_USBNET | 199 | depends on USB_USBNET |
@@ -280,6 +277,7 @@ config USB_EPSON2888 | |||
280 | config USB_NET_ZAURUS | 277 | config USB_NET_ZAURUS |
281 | tristate "Sharp Zaurus (stock ROMs) and compatible" | 278 | tristate "Sharp Zaurus (stock ROMs) and compatible" |
282 | depends on USB_USBNET | 279 | depends on USB_USBNET |
280 | select USB_NET_CDCETHER | ||
283 | select CRC32 | 281 | select CRC32 |
284 | default y | 282 | default y |
285 | help | 283 | help |
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index e13d7af3114b..697eb1913208 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_USB_KAWETH) += kaweth.o | |||
7 | obj-$(CONFIG_USB_PEGASUS) += pegasus.o | 7 | obj-$(CONFIG_USB_PEGASUS) += pegasus.o |
8 | obj-$(CONFIG_USB_RTL8150) += rtl8150.o | 8 | obj-$(CONFIG_USB_RTL8150) += rtl8150.o |
9 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 9 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
10 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o | ||
10 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o | 11 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o |
11 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o | 12 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o |
12 | obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o | 13 | obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o |
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c new file mode 100644 index 000000000000..652b04bbf6af --- /dev/null +++ b/drivers/usb/net/cdc_ether.c | |||
@@ -0,0 +1,509 @@ | |||
1 | /* | ||
2 | * CDC Ethernet based networking peripherals | ||
3 | * Copyright (C) 2003-2005 by David Brownell | ||
4 | * | ||
5 | * 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 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | // #define DEBUG // error path messages, extra info | ||
21 | // #define VERBOSE // more; success messages | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #ifdef CONFIG_USB_DEBUG | ||
25 | # define DEBUG | ||
26 | #endif | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/ctype.h> | ||
33 | #include <linux/ethtool.h> | ||
34 | #include <linux/workqueue.h> | ||
35 | #include <linux/mii.h> | ||
36 | #include <linux/usb.h> | ||
37 | #include <linux/usb_cdc.h> | ||
38 | |||
39 | #include "usbnet.h" | ||
40 | |||
41 | |||
42 | /* | ||
43 | * probes control interface, claims data interface, collects the bulk | ||
44 | * endpoints, activates data interface (if needed), maybe sets MTU. | ||
45 | * all pure cdc, except for certain firmware workarounds, and knowing | ||
46 | * that rndis uses one different rule. | ||
47 | */ | ||
48 | int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) | ||
49 | { | ||
50 | u8 *buf = intf->cur_altsetting->extra; | ||
51 | int len = intf->cur_altsetting->extralen; | ||
52 | struct usb_interface_descriptor *d; | ||
53 | struct cdc_state *info = (void *) &dev->data; | ||
54 | int status; | ||
55 | int rndis; | ||
56 | struct usb_driver *driver = driver_of(intf); | ||
57 | |||
58 | if (sizeof dev->data < sizeof *info) | ||
59 | return -EDOM; | ||
60 | |||
61 | /* expect strict spec conformance for the descriptors, but | ||
62 | * cope with firmware which stores them in the wrong place | ||
63 | */ | ||
64 | if (len == 0 && dev->udev->actconfig->extralen) { | ||
65 | /* Motorola SB4100 (and others: Brad Hards says it's | ||
66 | * from a Broadcom design) put CDC descriptors here | ||
67 | */ | ||
68 | buf = dev->udev->actconfig->extra; | ||
69 | len = dev->udev->actconfig->extralen; | ||
70 | if (len) | ||
71 | dev_dbg(&intf->dev, | ||
72 | "CDC descriptors on config\n"); | ||
73 | } | ||
74 | |||
75 | /* this assumes that if there's a non-RNDIS vendor variant | ||
76 | * of cdc-acm, it'll fail RNDIS requests cleanly. | ||
77 | */ | ||
78 | rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); | ||
79 | |||
80 | memset(info, 0, sizeof *info); | ||
81 | info->control = intf; | ||
82 | while (len > 3) { | ||
83 | if (buf [1] != USB_DT_CS_INTERFACE) | ||
84 | goto next_desc; | ||
85 | |||
86 | /* use bDescriptorSubType to identify the CDC descriptors. | ||
87 | * We expect devices with CDC header and union descriptors. | ||
88 | * For CDC Ethernet we need the ethernet descriptor. | ||
89 | * For RNDIS, ignore two (pointless) CDC modem descriptors | ||
90 | * in favor of a complicated OID-based RPC scheme doing what | ||
91 | * CDC Ethernet achieves with a simple descriptor. | ||
92 | */ | ||
93 | switch (buf [2]) { | ||
94 | case USB_CDC_HEADER_TYPE: | ||
95 | if (info->header) { | ||
96 | dev_dbg(&intf->dev, "extra CDC header\n"); | ||
97 | goto bad_desc; | ||
98 | } | ||
99 | info->header = (void *) buf; | ||
100 | if (info->header->bLength != sizeof *info->header) { | ||
101 | dev_dbg(&intf->dev, "CDC header len %u\n", | ||
102 | info->header->bLength); | ||
103 | goto bad_desc; | ||
104 | } | ||
105 | break; | ||
106 | case USB_CDC_UNION_TYPE: | ||
107 | if (info->u) { | ||
108 | dev_dbg(&intf->dev, "extra CDC union\n"); | ||
109 | goto bad_desc; | ||
110 | } | ||
111 | info->u = (void *) buf; | ||
112 | if (info->u->bLength != sizeof *info->u) { | ||
113 | dev_dbg(&intf->dev, "CDC union len %u\n", | ||
114 | info->u->bLength); | ||
115 | goto bad_desc; | ||
116 | } | ||
117 | |||
118 | /* we need a master/control interface (what we're | ||
119 | * probed with) and a slave/data interface; union | ||
120 | * descriptors sort this all out. | ||
121 | */ | ||
122 | info->control = usb_ifnum_to_if(dev->udev, | ||
123 | info->u->bMasterInterface0); | ||
124 | info->data = usb_ifnum_to_if(dev->udev, | ||
125 | info->u->bSlaveInterface0); | ||
126 | if (!info->control || !info->data) { | ||
127 | dev_dbg(&intf->dev, | ||
128 | "master #%u/%p slave #%u/%p\n", | ||
129 | info->u->bMasterInterface0, | ||
130 | info->control, | ||
131 | info->u->bSlaveInterface0, | ||
132 | info->data); | ||
133 | goto bad_desc; | ||
134 | } | ||
135 | if (info->control != intf) { | ||
136 | dev_dbg(&intf->dev, "bogus CDC Union\n"); | ||
137 | /* Ambit USB Cable Modem (and maybe others) | ||
138 | * interchanges master and slave interface. | ||
139 | */ | ||
140 | if (info->data == intf) { | ||
141 | info->data = info->control; | ||
142 | info->control = intf; | ||
143 | } else | ||
144 | goto bad_desc; | ||
145 | } | ||
146 | |||
147 | /* a data interface altsetting does the real i/o */ | ||
148 | d = &info->data->cur_altsetting->desc; | ||
149 | if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { | ||
150 | dev_dbg(&intf->dev, "slave class %u\n", | ||
151 | d->bInterfaceClass); | ||
152 | goto bad_desc; | ||
153 | } | ||
154 | break; | ||
155 | case USB_CDC_ETHERNET_TYPE: | ||
156 | if (info->ether) { | ||
157 | dev_dbg(&intf->dev, "extra CDC ether\n"); | ||
158 | goto bad_desc; | ||
159 | } | ||
160 | info->ether = (void *) buf; | ||
161 | if (info->ether->bLength != sizeof *info->ether) { | ||
162 | dev_dbg(&intf->dev, "CDC ether len %u\n", | ||
163 | info->ether->bLength); | ||
164 | goto bad_desc; | ||
165 | } | ||
166 | dev->hard_mtu = le16_to_cpu( | ||
167 | info->ether->wMaxSegmentSize); | ||
168 | /* because of Zaurus, we may be ignoring the host | ||
169 | * side link address we were given. | ||
170 | */ | ||
171 | break; | ||
172 | } | ||
173 | next_desc: | ||
174 | len -= buf [0]; /* bLength */ | ||
175 | buf += buf [0]; | ||
176 | } | ||
177 | |||
178 | if (!info->header || !info->u || (!rndis && !info->ether)) { | ||
179 | dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", | ||
180 | info->header ? "" : "header ", | ||
181 | info->u ? "" : "union ", | ||
182 | info->ether ? "" : "ether "); | ||
183 | goto bad_desc; | ||
184 | } | ||
185 | |||
186 | /* claim data interface and set it up ... with side effects. | ||
187 | * network traffic can't flow until an altsetting is enabled. | ||
188 | */ | ||
189 | status = usb_driver_claim_interface(driver, info->data, dev); | ||
190 | if (status < 0) | ||
191 | return status; | ||
192 | status = usbnet_get_endpoints(dev, info->data); | ||
193 | if (status < 0) { | ||
194 | /* ensure immediate exit from usbnet_disconnect */ | ||
195 | usb_set_intfdata(info->data, NULL); | ||
196 | usb_driver_release_interface(driver, info->data); | ||
197 | return status; | ||
198 | } | ||
199 | |||
200 | /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ | ||
201 | dev->status = NULL; | ||
202 | if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { | ||
203 | struct usb_endpoint_descriptor *desc; | ||
204 | |||
205 | dev->status = &info->control->cur_altsetting->endpoint [0]; | ||
206 | desc = &dev->status->desc; | ||
207 | if (desc->bmAttributes != USB_ENDPOINT_XFER_INT | ||
208 | || !(desc->bEndpointAddress & USB_DIR_IN) | ||
209 | || (le16_to_cpu(desc->wMaxPacketSize) | ||
210 | < sizeof(struct usb_cdc_notification)) | ||
211 | || !desc->bInterval) { | ||
212 | dev_dbg(&intf->dev, "bad notification endpoint\n"); | ||
213 | dev->status = NULL; | ||
214 | } | ||
215 | } | ||
216 | if (rndis && !dev->status) { | ||
217 | dev_dbg(&intf->dev, "missing RNDIS status endpoint\n"); | ||
218 | usb_set_intfdata(info->data, NULL); | ||
219 | usb_driver_release_interface(driver, info->data); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | return 0; | ||
223 | |||
224 | bad_desc: | ||
225 | dev_info(&dev->udev->dev, "bad CDC descriptors\n"); | ||
226 | return -ENODEV; | ||
227 | } | ||
228 | EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); | ||
229 | |||
230 | void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) | ||
231 | { | ||
232 | struct cdc_state *info = (void *) &dev->data; | ||
233 | struct usb_driver *driver = driver_of(intf); | ||
234 | |||
235 | /* disconnect master --> disconnect slave */ | ||
236 | if (intf == info->control && info->data) { | ||
237 | /* ensure immediate exit from usbnet_disconnect */ | ||
238 | usb_set_intfdata(info->data, NULL); | ||
239 | usb_driver_release_interface(driver, info->data); | ||
240 | info->data = NULL; | ||
241 | } | ||
242 | |||
243 | /* and vice versa (just in case) */ | ||
244 | else if (intf == info->data && info->control) { | ||
245 | /* ensure immediate exit from usbnet_disconnect */ | ||
246 | usb_set_intfdata(info->control, NULL); | ||
247 | usb_driver_release_interface(driver, info->control); | ||
248 | info->control = NULL; | ||
249 | } | ||
250 | } | ||
251 | EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); | ||
252 | |||
253 | |||
254 | /*------------------------------------------------------------------------- | ||
255 | * | ||
256 | * Communications Device Class, Ethernet Control model | ||
257 | * | ||
258 | * Takes two interfaces. The DATA interface is inactive till an altsetting | ||
259 | * is selected. Configuration data includes class descriptors. There's | ||
260 | * an optional status endpoint on the control interface. | ||
261 | * | ||
262 | * This should interop with whatever the 2.4 "CDCEther.c" driver | ||
263 | * (by Brad Hards) talked with, with more functionality. | ||
264 | * | ||
265 | *-------------------------------------------------------------------------*/ | ||
266 | |||
267 | static void dumpspeed(struct usbnet *dev, __le32 *speeds) | ||
268 | { | ||
269 | if (netif_msg_timer(dev)) | ||
270 | devinfo(dev, "link speeds: %u kbps up, %u kbps down", | ||
271 | __le32_to_cpu(speeds[0]) / 1000, | ||
272 | __le32_to_cpu(speeds[1]) / 1000); | ||
273 | } | ||
274 | |||
275 | static void cdc_status(struct usbnet *dev, struct urb *urb) | ||
276 | { | ||
277 | struct usb_cdc_notification *event; | ||
278 | |||
279 | if (urb->actual_length < sizeof *event) | ||
280 | return; | ||
281 | |||
282 | /* SPEED_CHANGE can get split into two 8-byte packets */ | ||
283 | if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) { | ||
284 | dumpspeed(dev, (__le32 *) urb->transfer_buffer); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | event = urb->transfer_buffer; | ||
289 | switch (event->bNotificationType) { | ||
290 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | ||
291 | if (netif_msg_timer(dev)) | ||
292 | devdbg(dev, "CDC: carrier %s", | ||
293 | event->wValue ? "on" : "off"); | ||
294 | if (event->wValue) | ||
295 | netif_carrier_on(dev->net); | ||
296 | else | ||
297 | netif_carrier_off(dev->net); | ||
298 | break; | ||
299 | case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ | ||
300 | if (netif_msg_timer(dev)) | ||
301 | devdbg(dev, "CDC: speed change (len %d)", | ||
302 | urb->actual_length); | ||
303 | if (urb->actual_length != (sizeof *event + 8)) | ||
304 | set_bit(EVENT_STS_SPLIT, &dev->flags); | ||
305 | else | ||
306 | dumpspeed(dev, (__le32 *) &event[1]); | ||
307 | break; | ||
308 | /* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS), | ||
309 | * but there are no standard formats for the response data. | ||
310 | */ | ||
311 | default: | ||
312 | deverr(dev, "CDC: unexpected notification %02x!", | ||
313 | event->bNotificationType); | ||
314 | break; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static u8 nibble(unsigned char c) | ||
319 | { | ||
320 | if (likely(isdigit(c))) | ||
321 | return c - '0'; | ||
322 | c = toupper(c); | ||
323 | if (likely(isxdigit(c))) | ||
324 | return 10 + c - 'A'; | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static inline int | ||
329 | get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e) | ||
330 | { | ||
331 | int tmp, i; | ||
332 | unsigned char buf [13]; | ||
333 | |||
334 | tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf); | ||
335 | if (tmp != 12) { | ||
336 | dev_dbg(&dev->udev->dev, | ||
337 | "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp); | ||
338 | if (tmp >= 0) | ||
339 | tmp = -EINVAL; | ||
340 | return tmp; | ||
341 | } | ||
342 | for (i = tmp = 0; i < 6; i++, tmp += 2) | ||
343 | dev->net->dev_addr [i] = | ||
344 | (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) | ||
349 | { | ||
350 | int status; | ||
351 | struct cdc_state *info = (void *) &dev->data; | ||
352 | |||
353 | status = usbnet_generic_cdc_bind(dev, intf); | ||
354 | if (status < 0) | ||
355 | return status; | ||
356 | |||
357 | status = get_ethernet_addr(dev, info->ether); | ||
358 | if (status < 0) { | ||
359 | usb_set_intfdata(info->data, NULL); | ||
360 | usb_driver_release_interface(driver_of(intf), info->data); | ||
361 | return status; | ||
362 | } | ||
363 | |||
364 | /* FIXME cdc-ether has some multicast code too, though it complains | ||
365 | * in routine cases. info->ether describes the multicast support. | ||
366 | * Implement that here, manipulating the cdc filter as needed. | ||
367 | */ | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static const struct driver_info cdc_info = { | ||
372 | .description = "CDC Ethernet Device", | ||
373 | .flags = FLAG_ETHER, | ||
374 | // .check_connect = cdc_check_connect, | ||
375 | .bind = cdc_bind, | ||
376 | .unbind = usbnet_cdc_unbind, | ||
377 | .status = cdc_status, | ||
378 | }; | ||
379 | |||
380 | /*-------------------------------------------------------------------------*/ | ||
381 | |||
382 | |||
383 | static const struct usb_device_id products [] = { | ||
384 | /* | ||
385 | * BLACKLIST !! | ||
386 | * | ||
387 | * First blacklist any products that are egregiously nonconformant | ||
388 | * with the CDC Ethernet specs. Minor braindamage we cope with; when | ||
389 | * they're not even trying, needing a separate driver is only the first | ||
390 | * of the differences to show up. | ||
391 | */ | ||
392 | |||
393 | #define ZAURUS_MASTER_INTERFACE \ | ||
394 | .bInterfaceClass = USB_CLASS_COMM, \ | ||
395 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ | ||
396 | .bInterfaceProtocol = USB_CDC_PROTO_NONE | ||
397 | |||
398 | /* SA-1100 based Sharp Zaurus ("collie"), or compatible; | ||
399 | * wire-incompatible with true CDC Ethernet implementations. | ||
400 | * (And, it seems, needlessly so...) | ||
401 | */ | ||
402 | { | ||
403 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
404 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
405 | .idVendor = 0x04DD, | ||
406 | .idProduct = 0x8004, | ||
407 | ZAURUS_MASTER_INTERFACE, | ||
408 | .driver_info = 0, | ||
409 | }, | ||
410 | |||
411 | /* PXA-25x based Sharp Zaurii. Note that it seems some of these | ||
412 | * (later models especially) may have shipped only with firmware | ||
413 | * advertising false "CDC MDLM" compatibility ... but we're not | ||
414 | * clear which models did that, so for now let's assume the worst. | ||
415 | */ | ||
416 | { | ||
417 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
418 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
419 | .idVendor = 0x04DD, | ||
420 | .idProduct = 0x8005, /* A-300 */ | ||
421 | ZAURUS_MASTER_INTERFACE, | ||
422 | .driver_info = 0, | ||
423 | }, { | ||
424 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
425 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
426 | .idVendor = 0x04DD, | ||
427 | .idProduct = 0x8006, /* B-500/SL-5600 */ | ||
428 | ZAURUS_MASTER_INTERFACE, | ||
429 | .driver_info = 0, | ||
430 | }, { | ||
431 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
432 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
433 | .idVendor = 0x04DD, | ||
434 | .idProduct = 0x8007, /* C-700 */ | ||
435 | ZAURUS_MASTER_INTERFACE, | ||
436 | .driver_info = 0, | ||
437 | }, { | ||
438 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
439 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
440 | .idVendor = 0x04DD, | ||
441 | .idProduct = 0x9031, /* C-750 C-760 */ | ||
442 | ZAURUS_MASTER_INTERFACE, | ||
443 | .driver_info = 0, | ||
444 | }, { | ||
445 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
446 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
447 | .idVendor = 0x04DD, | ||
448 | .idProduct = 0x9032, /* SL-6000 */ | ||
449 | ZAURUS_MASTER_INTERFACE, | ||
450 | .driver_info = 0, | ||
451 | }, { | ||
452 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | ||
453 | | USB_DEVICE_ID_MATCH_DEVICE, | ||
454 | .idVendor = 0x04DD, | ||
455 | /* reported with some C860 units */ | ||
456 | .idProduct = 0x9050, /* C-860 */ | ||
457 | ZAURUS_MASTER_INTERFACE, | ||
458 | .driver_info = 0, | ||
459 | }, | ||
460 | |||
461 | /* | ||
462 | * WHITELIST!!! | ||
463 | * | ||
464 | * CDC Ether uses two interfaces, not necessarily consecutive. | ||
465 | * We match the main interface, ignoring the optional device | ||
466 | * class so we could handle devices that aren't exclusively | ||
467 | * CDC ether. | ||
468 | * | ||
469 | * NOTE: this match must come AFTER entries blacklisting devices | ||
470 | * because of bugs/quirks in a given product (like Zaurus, above). | ||
471 | */ | ||
472 | { | ||
473 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, | ||
474 | USB_CDC_PROTO_NONE), | ||
475 | .driver_info = (unsigned long) &cdc_info, | ||
476 | }, | ||
477 | { }, // END | ||
478 | }; | ||
479 | MODULE_DEVICE_TABLE(usb, products); | ||
480 | |||
481 | static struct usb_driver cdc_driver = { | ||
482 | .owner = THIS_MODULE, | ||
483 | .name = "cdc_ether", | ||
484 | .id_table = products, | ||
485 | .probe = usbnet_probe, | ||
486 | .disconnect = usbnet_disconnect, | ||
487 | .suspend = usbnet_suspend, | ||
488 | .resume = usbnet_resume, | ||
489 | }; | ||
490 | |||
491 | |||
492 | static int __init cdc_init(void) | ||
493 | { | ||
494 | BUG_ON((sizeof(((struct usbnet *)0)->data) | ||
495 | < sizeof(struct cdc_state))); | ||
496 | |||
497 | return usb_register(&cdc_driver); | ||
498 | } | ||
499 | module_init(cdc_init); | ||
500 | |||
501 | static void __exit cdc_exit(void) | ||
502 | { | ||
503 | usb_deregister(&cdc_driver); | ||
504 | } | ||
505 | module_exit(cdc_exit); | ||
506 | |||
507 | MODULE_AUTHOR("David Brownell"); | ||
508 | MODULE_DESCRIPTION("USB CDC Ethernet devices"); | ||
509 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 75a05ab0a642..7703725327d2 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c | |||
@@ -301,377 +301,6 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) | |||
301 | EXPORT_SYMBOL_GPL(usbnet_skb_return); | 301 | EXPORT_SYMBOL_GPL(usbnet_skb_return); |
302 | 302 | ||
303 | 303 | ||
304 | /*------------------------------------------------------------------------- | ||
305 | * | ||
306 | * Communications Device Class declarations. | ||
307 | * Used by CDC Ethernet, and some CDC variants | ||
308 | * | ||
309 | *-------------------------------------------------------------------------*/ | ||
310 | |||
311 | #ifdef CONFIG_USB_CDCETHER | ||
312 | #define NEED_GENERIC_CDC | ||
313 | #endif | ||
314 | |||
315 | #if defined(CONFIG_USB_ZAURUS) || defined(CONFIG_USB_ZAURUS_MODULE) | ||
316 | /* Ethernet variant uses funky framing, broken ethernet addressing */ | ||
317 | #define NEED_GENERIC_CDC | ||
318 | #endif | ||
319 | |||
320 | #ifdef CONFIG_USB_RNDIS | ||
321 | /* ACM variant uses even funkier framing, complex control RPC scheme */ | ||
322 | #define NEED_GENERIC_CDC | ||
323 | #endif | ||
324 | |||
325 | |||
326 | #ifdef NEED_GENERIC_CDC | ||
327 | |||
328 | #include <linux/usb_cdc.h> | ||
329 | |||
330 | static struct usb_driver usbnet_driver; | ||
331 | |||
332 | /* | ||
333 | * probes control interface, claims data interface, collects the bulk | ||
334 | * endpoints, activates data interface (if needed), maybe sets MTU. | ||
335 | * all pure cdc, except for certain firmware workarounds. | ||
336 | */ | ||
337 | int usbnet_generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf) | ||
338 | { | ||
339 | u8 *buf = intf->cur_altsetting->extra; | ||
340 | int len = intf->cur_altsetting->extralen; | ||
341 | struct usb_interface_descriptor *d; | ||
342 | struct cdc_state *info = (void *) &dev->data; | ||
343 | int status; | ||
344 | int rndis; | ||
345 | |||
346 | if (sizeof dev->data < sizeof *info) | ||
347 | return -EDOM; | ||
348 | |||
349 | /* expect strict spec conformance for the descriptors, but | ||
350 | * cope with firmware which stores them in the wrong place | ||
351 | */ | ||
352 | if (len == 0 && dev->udev->actconfig->extralen) { | ||
353 | /* Motorola SB4100 (and others: Brad Hards says it's | ||
354 | * from a Broadcom design) put CDC descriptors here | ||
355 | */ | ||
356 | buf = dev->udev->actconfig->extra; | ||
357 | len = dev->udev->actconfig->extralen; | ||
358 | if (len) | ||
359 | dev_dbg (&intf->dev, | ||
360 | "CDC descriptors on config\n"); | ||
361 | } | ||
362 | |||
363 | /* this assumes that if there's a non-RNDIS vendor variant | ||
364 | * of cdc-acm, it'll fail RNDIS requests cleanly. | ||
365 | */ | ||
366 | rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); | ||
367 | |||
368 | memset (info, 0, sizeof *info); | ||
369 | info->control = intf; | ||
370 | while (len > 3) { | ||
371 | if (buf [1] != USB_DT_CS_INTERFACE) | ||
372 | goto next_desc; | ||
373 | |||
374 | /* use bDescriptorSubType to identify the CDC descriptors. | ||
375 | * We expect devices with CDC header and union descriptors. | ||
376 | * For CDC Ethernet we need the ethernet descriptor. | ||
377 | * For RNDIS, ignore two (pointless) CDC modem descriptors | ||
378 | * in favor of a complicated OID-based RPC scheme doing what | ||
379 | * CDC Ethernet achieves with a simple descriptor. | ||
380 | */ | ||
381 | switch (buf [2]) { | ||
382 | case USB_CDC_HEADER_TYPE: | ||
383 | if (info->header) { | ||
384 | dev_dbg (&intf->dev, "extra CDC header\n"); | ||
385 | goto bad_desc; | ||
386 | } | ||
387 | info->header = (void *) buf; | ||
388 | if (info->header->bLength != sizeof *info->header) { | ||
389 | dev_dbg (&intf->dev, "CDC header len %u\n", | ||
390 | info->header->bLength); | ||
391 | goto bad_desc; | ||
392 | } | ||
393 | break; | ||
394 | case USB_CDC_UNION_TYPE: | ||
395 | if (info->u) { | ||
396 | dev_dbg (&intf->dev, "extra CDC union\n"); | ||
397 | goto bad_desc; | ||
398 | } | ||
399 | info->u = (void *) buf; | ||
400 | if (info->u->bLength != sizeof *info->u) { | ||
401 | dev_dbg (&intf->dev, "CDC union len %u\n", | ||
402 | info->u->bLength); | ||
403 | goto bad_desc; | ||
404 | } | ||
405 | |||
406 | /* we need a master/control interface (what we're | ||
407 | * probed with) and a slave/data interface; union | ||
408 | * descriptors sort this all out. | ||
409 | */ | ||
410 | info->control = usb_ifnum_to_if(dev->udev, | ||
411 | info->u->bMasterInterface0); | ||
412 | info->data = usb_ifnum_to_if(dev->udev, | ||
413 | info->u->bSlaveInterface0); | ||
414 | if (!info->control || !info->data) { | ||
415 | dev_dbg (&intf->dev, | ||
416 | "master #%u/%p slave #%u/%p\n", | ||
417 | info->u->bMasterInterface0, | ||
418 | info->control, | ||
419 | info->u->bSlaveInterface0, | ||
420 | info->data); | ||
421 | goto bad_desc; | ||
422 | } | ||
423 | if (info->control != intf) { | ||
424 | dev_dbg (&intf->dev, "bogus CDC Union\n"); | ||
425 | /* Ambit USB Cable Modem (and maybe others) | ||
426 | * interchanges master and slave interface. | ||
427 | */ | ||
428 | if (info->data == intf) { | ||
429 | info->data = info->control; | ||
430 | info->control = intf; | ||
431 | } else | ||
432 | goto bad_desc; | ||
433 | } | ||
434 | |||
435 | /* a data interface altsetting does the real i/o */ | ||
436 | d = &info->data->cur_altsetting->desc; | ||
437 | if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { | ||
438 | dev_dbg (&intf->dev, "slave class %u\n", | ||
439 | d->bInterfaceClass); | ||
440 | goto bad_desc; | ||
441 | } | ||
442 | break; | ||
443 | case USB_CDC_ETHERNET_TYPE: | ||
444 | if (info->ether) { | ||
445 | dev_dbg (&intf->dev, "extra CDC ether\n"); | ||
446 | goto bad_desc; | ||
447 | } | ||
448 | info->ether = (void *) buf; | ||
449 | if (info->ether->bLength != sizeof *info->ether) { | ||
450 | dev_dbg (&intf->dev, "CDC ether len %u\n", | ||
451 | info->ether->bLength); | ||
452 | goto bad_desc; | ||
453 | } | ||
454 | dev->hard_mtu = le16_to_cpu( | ||
455 | info->ether->wMaxSegmentSize); | ||
456 | /* because of Zaurus, we may be ignoring the host | ||
457 | * side link address we were given. | ||
458 | */ | ||
459 | break; | ||
460 | } | ||
461 | next_desc: | ||
462 | len -= buf [0]; /* bLength */ | ||
463 | buf += buf [0]; | ||
464 | } | ||
465 | |||
466 | if (!info->header || !info->u || (!rndis && !info->ether)) { | ||
467 | dev_dbg (&intf->dev, "missing cdc %s%s%sdescriptor\n", | ||
468 | info->header ? "" : "header ", | ||
469 | info->u ? "" : "union ", | ||
470 | info->ether ? "" : "ether "); | ||
471 | goto bad_desc; | ||
472 | } | ||
473 | |||
474 | /* claim data interface and set it up ... with side effects. | ||
475 | * network traffic can't flow until an altsetting is enabled. | ||
476 | */ | ||
477 | status = usb_driver_claim_interface (&usbnet_driver, info->data, dev); | ||
478 | if (status < 0) | ||
479 | return status; | ||
480 | status = usbnet_get_endpoints (dev, info->data); | ||
481 | if (status < 0) { | ||
482 | /* ensure immediate exit from usbnet_disconnect */ | ||
483 | usb_set_intfdata(info->data, NULL); | ||
484 | usb_driver_release_interface (&usbnet_driver, info->data); | ||
485 | return status; | ||
486 | } | ||
487 | |||
488 | /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ | ||
489 | dev->status = NULL; | ||
490 | if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { | ||
491 | struct usb_endpoint_descriptor *desc; | ||
492 | |||
493 | dev->status = &info->control->cur_altsetting->endpoint [0]; | ||
494 | desc = &dev->status->desc; | ||
495 | if (desc->bmAttributes != USB_ENDPOINT_XFER_INT | ||
496 | || !(desc->bEndpointAddress & USB_DIR_IN) | ||
497 | || (le16_to_cpu(desc->wMaxPacketSize) | ||
498 | < sizeof (struct usb_cdc_notification)) | ||
499 | || !desc->bInterval) { | ||
500 | dev_dbg (&intf->dev, "bad notification endpoint\n"); | ||
501 | dev->status = NULL; | ||
502 | } | ||
503 | } | ||
504 | if (rndis && !dev->status) { | ||
505 | dev_dbg (&intf->dev, "missing RNDIS status endpoint\n"); | ||
506 | usb_set_intfdata(info->data, NULL); | ||
507 | usb_driver_release_interface (&usbnet_driver, info->data); | ||
508 | return -ENODEV; | ||
509 | } | ||
510 | return 0; | ||
511 | |||
512 | bad_desc: | ||
513 | dev_info (&dev->udev->dev, "bad CDC descriptors\n"); | ||
514 | return -ENODEV; | ||
515 | } | ||
516 | EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); | ||
517 | |||
518 | void usbnet_cdc_unbind (struct usbnet *dev, struct usb_interface *intf) | ||
519 | { | ||
520 | struct cdc_state *info = (void *) &dev->data; | ||
521 | |||
522 | /* disconnect master --> disconnect slave */ | ||
523 | if (intf == info->control && info->data) { | ||
524 | /* ensure immediate exit from usbnet_disconnect */ | ||
525 | usb_set_intfdata(info->data, NULL); | ||
526 | usb_driver_release_interface (&usbnet_driver, info->data); | ||
527 | info->data = NULL; | ||
528 | } | ||
529 | |||
530 | /* and vice versa (just in case) */ | ||
531 | else if (intf == info->data && info->control) { | ||
532 | /* ensure immediate exit from usbnet_disconnect */ | ||
533 | usb_set_intfdata(info->control, NULL); | ||
534 | usb_driver_release_interface (&usbnet_driver, info->control); | ||
535 | info->control = NULL; | ||
536 | } | ||
537 | } | ||
538 | EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); | ||
539 | |||
540 | #endif /* NEED_GENERIC_CDC */ | ||
541 | |||
542 | |||
543 | #ifdef CONFIG_USB_CDCETHER | ||
544 | #define HAVE_HARDWARE | ||
545 | |||
546 | /*------------------------------------------------------------------------- | ||
547 | * | ||
548 | * Communications Device Class, Ethernet Control model | ||
549 | * | ||
550 | * Takes two interfaces. The DATA interface is inactive till an altsetting | ||
551 | * is selected. Configuration data includes class descriptors. | ||
552 | * | ||
553 | * This should interop with whatever the 2.4 "CDCEther.c" driver | ||
554 | * (by Brad Hards) talked with. | ||
555 | * | ||
556 | *-------------------------------------------------------------------------*/ | ||
557 | |||
558 | #include <linux/ctype.h> | ||
559 | |||
560 | |||
561 | static void dumpspeed (struct usbnet *dev, __le32 *speeds) | ||
562 | { | ||
563 | if (netif_msg_timer (dev)) | ||
564 | devinfo (dev, "link speeds: %u kbps up, %u kbps down", | ||
565 | __le32_to_cpu(speeds[0]) / 1000, | ||
566 | __le32_to_cpu(speeds[1]) / 1000); | ||
567 | } | ||
568 | |||
569 | static void cdc_status (struct usbnet *dev, struct urb *urb) | ||
570 | { | ||
571 | struct usb_cdc_notification *event; | ||
572 | |||
573 | if (urb->actual_length < sizeof *event) | ||
574 | return; | ||
575 | |||
576 | /* SPEED_CHANGE can get split into two 8-byte packets */ | ||
577 | if (test_and_clear_bit (EVENT_STS_SPLIT, &dev->flags)) { | ||
578 | dumpspeed (dev, (__le32 *) urb->transfer_buffer); | ||
579 | return; | ||
580 | } | ||
581 | |||
582 | event = urb->transfer_buffer; | ||
583 | switch (event->bNotificationType) { | ||
584 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | ||
585 | if (netif_msg_timer (dev)) | ||
586 | devdbg (dev, "CDC: carrier %s", | ||
587 | event->wValue ? "on" : "off"); | ||
588 | if (event->wValue) | ||
589 | netif_carrier_on(dev->net); | ||
590 | else | ||
591 | netif_carrier_off(dev->net); | ||
592 | break; | ||
593 | case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ | ||
594 | if (netif_msg_timer (dev)) | ||
595 | devdbg (dev, "CDC: speed change (len %d)", | ||
596 | urb->actual_length); | ||
597 | if (urb->actual_length != (sizeof *event + 8)) | ||
598 | set_bit (EVENT_STS_SPLIT, &dev->flags); | ||
599 | else | ||
600 | dumpspeed (dev, (__le32 *) &event[1]); | ||
601 | break; | ||
602 | // case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: /* RNDIS; or unsolicited */ | ||
603 | default: | ||
604 | deverr (dev, "CDC: unexpected notification %02x!", | ||
605 | event->bNotificationType); | ||
606 | break; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | static u8 nibble (unsigned char c) | ||
611 | { | ||
612 | if (likely (isdigit (c))) | ||
613 | return c - '0'; | ||
614 | c = toupper (c); | ||
615 | if (likely (isxdigit (c))) | ||
616 | return 10 + c - 'A'; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static inline int | ||
621 | get_ethernet_addr (struct usbnet *dev, struct usb_cdc_ether_desc *e) | ||
622 | { | ||
623 | int tmp, i; | ||
624 | unsigned char buf [13]; | ||
625 | |||
626 | tmp = usb_string (dev->udev, e->iMACAddress, buf, sizeof buf); | ||
627 | if (tmp != 12) { | ||
628 | dev_dbg (&dev->udev->dev, | ||
629 | "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp); | ||
630 | if (tmp >= 0) | ||
631 | tmp = -EINVAL; | ||
632 | return tmp; | ||
633 | } | ||
634 | for (i = tmp = 0; i < 6; i++, tmp += 2) | ||
635 | dev->net->dev_addr [i] = | ||
636 | (nibble (buf [tmp]) << 4) + nibble (buf [tmp + 1]); | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | static int cdc_bind (struct usbnet *dev, struct usb_interface *intf) | ||
641 | { | ||
642 | int status; | ||
643 | struct cdc_state *info = (void *) &dev->data; | ||
644 | |||
645 | status = usbnet_generic_cdc_bind (dev, intf); | ||
646 | if (status < 0) | ||
647 | return status; | ||
648 | |||
649 | status = get_ethernet_addr (dev, info->ether); | ||
650 | if (status < 0) { | ||
651 | usb_set_intfdata(info->data, NULL); | ||
652 | usb_driver_release_interface (&usbnet_driver, info->data); | ||
653 | return status; | ||
654 | } | ||
655 | |||
656 | /* FIXME cdc-ether has some multicast code too, though it complains | ||
657 | * in routine cases. info->ether describes the multicast support. | ||
658 | */ | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | static const struct driver_info cdc_info = { | ||
663 | .description = "CDC Ethernet Device", | ||
664 | .flags = FLAG_ETHER, | ||
665 | // .check_connect = cdc_check_connect, | ||
666 | .bind = cdc_bind, | ||
667 | .unbind = usbnet_cdc_unbind, | ||
668 | .status = cdc_status, | ||
669 | }; | ||
670 | |||
671 | #endif /* CONFIG_USB_CDCETHER */ | ||
672 | |||
673 | |||
674 | |||
675 | #ifdef CONFIG_USB_PL2301 | 304 | #ifdef CONFIG_USB_PL2301 |
676 | #define HAVE_HARDWARE | 305 | #define HAVE_HARDWARE |
677 | 306 | ||
@@ -1754,23 +1383,6 @@ static const struct usb_device_id products [] = { | |||
1754 | .driver_info = (unsigned long) &rndis_info, | 1383 | .driver_info = (unsigned long) &rndis_info, |
1755 | }, | 1384 | }, |
1756 | #endif | 1385 | #endif |
1757 | |||
1758 | #ifdef CONFIG_USB_CDCETHER | ||
1759 | { | ||
1760 | /* CDC Ether uses two interfaces, not necessarily consecutive. | ||
1761 | * We match the main interface, ignoring the optional device | ||
1762 | * class so we could handle devices that aren't exclusively | ||
1763 | * CDC ether. | ||
1764 | * | ||
1765 | * NOTE: this match must come AFTER entries working around | ||
1766 | * bugs/quirks in a given product (like Zaurus, above). | ||
1767 | */ | ||
1768 | USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, | ||
1769 | USB_CDC_PROTO_NONE), | ||
1770 | .driver_info = (unsigned long) &cdc_info, | ||
1771 | }, | ||
1772 | #endif | ||
1773 | |||
1774 | { }, // END | 1386 | { }, // END |
1775 | }; | 1387 | }; |
1776 | MODULE_DEVICE_TABLE (usb, products); | 1388 | MODULE_DEVICE_TABLE (usb, products); |
@@ -1792,10 +1404,6 @@ static int __init usbnet_init(void) | |||
1792 | // compiler should optimize these out | 1404 | // compiler should optimize these out |
1793 | BUG_ON (sizeof (((struct sk_buff *)0)->cb) | 1405 | BUG_ON (sizeof (((struct sk_buff *)0)->cb) |
1794 | < sizeof (struct skb_data)); | 1406 | < sizeof (struct skb_data)); |
1795 | #ifdef CONFIG_USB_CDCETHER | ||
1796 | BUG_ON ((sizeof (((struct usbnet *)0)->data) | ||
1797 | < sizeof (struct cdc_state))); | ||
1798 | #endif | ||
1799 | 1407 | ||
1800 | random_ether_addr(node_id); | 1408 | random_ether_addr(node_id); |
1801 | 1409 | ||