diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2011-08-04 19:13:20 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2011-08-04 19:13:20 -0400 |
commit | 17b0436077d99211d8b26886235a36c5ec54ac57 (patch) | |
tree | 8bcd9b4a0f8285f749814e95ae0365c611ba2392 /drivers/net/usb | |
parent | aafade242ff24fac3aabf61c7861dfa44a3c2445 (diff) | |
parent | 02f8c6aee8df3cdc935e9bdd4f2d020306035dbe (diff) |
Merge commit 'v3.0' into x86/vdso
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/Kconfig | 10 | ||||
-rw-r--r-- | drivers/net/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/usb/hso.c | 7 | ||||
-rw-r--r-- | drivers/net/usb/kalmia.c | 392 | ||||
-rw-r--r-- | drivers/net/usb/zaurus.c | 10 |
5 files changed, 407 insertions, 13 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 9d4f9117260f..84d4608153c9 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -385,6 +385,16 @@ config USB_NET_CX82310_ETH | |||
385 | router with USB ethernet port. This driver is for routers only, | 385 | router with USB ethernet port. This driver is for routers only, |
386 | it will not work with ADSL modems (use cxacru driver instead). | 386 | it will not work with ADSL modems (use cxacru driver instead). |
387 | 387 | ||
388 | config USB_NET_KALMIA | ||
389 | tristate "Samsung Kalmia based LTE USB modem" | ||
390 | depends on USB_USBNET | ||
391 | help | ||
392 | Choose this option if you have a Samsung Kalmia based USB modem | ||
393 | as Samsung GT-B3730. | ||
394 | |||
395 | To compile this driver as a module, choose M here: the | ||
396 | module will be called kalmia. | ||
397 | |||
388 | config USB_HSO | 398 | config USB_HSO |
389 | tristate "Option USB High Speed Mobile Devices" | 399 | tristate "Option USB High Speed Mobile Devices" |
390 | depends on USB && RFKILL | 400 | depends on USB && RFKILL |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index c7ec8a5f0a90..c203fa21f6b1 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o | |||
23 | obj-$(CONFIG_USB_USBNET) += usbnet.o | 23 | obj-$(CONFIG_USB_USBNET) += usbnet.o |
24 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o | 24 | obj-$(CONFIG_USB_NET_INT51X1) += int51x1.o |
25 | obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o | 25 | obj-$(CONFIG_USB_CDC_PHONET) += cdc-phonet.o |
26 | obj-$(CONFIG_USB_NET_KALMIA) += kalmia.o | ||
26 | obj-$(CONFIG_USB_IPHETH) += ipheth.o | 27 | obj-$(CONFIG_USB_IPHETH) += ipheth.o |
27 | obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o | 28 | obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o |
28 | obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o | 29 | obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 387ca43f26f4..304fe78ff60e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -2421,10 +2421,8 @@ static void hso_free_net_device(struct hso_device *hso_dev) | |||
2421 | 2421 | ||
2422 | remove_net_device(hso_net->parent); | 2422 | remove_net_device(hso_net->parent); |
2423 | 2423 | ||
2424 | if (hso_net->net) { | 2424 | if (hso_net->net) |
2425 | unregister_netdev(hso_net->net); | 2425 | unregister_netdev(hso_net->net); |
2426 | free_netdev(hso_net->net); | ||
2427 | } | ||
2428 | 2426 | ||
2429 | /* start freeing */ | 2427 | /* start freeing */ |
2430 | for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { | 2428 | for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { |
@@ -2436,6 +2434,9 @@ static void hso_free_net_device(struct hso_device *hso_dev) | |||
2436 | kfree(hso_net->mux_bulk_tx_buf); | 2434 | kfree(hso_net->mux_bulk_tx_buf); |
2437 | hso_net->mux_bulk_tx_buf = NULL; | 2435 | hso_net->mux_bulk_tx_buf = NULL; |
2438 | 2436 | ||
2437 | if (hso_net->net) | ||
2438 | free_netdev(hso_net->net); | ||
2439 | |||
2439 | kfree(hso_dev); | 2440 | kfree(hso_dev); |
2440 | } | 2441 | } |
2441 | 2442 | ||
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c new file mode 100644 index 000000000000..a9b6c63d54e4 --- /dev/null +++ b/drivers/net/usb/kalmia.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * USB network interface driver for Samsung Kalmia based LTE USB modem like the | ||
3 | * Samsung GT-B3730 and GT-B3710. | ||
4 | * | ||
5 | * Copyright (C) 2011 Marius Bjoernstad Kotsbak <marius@kotsbak.com> | ||
6 | * | ||
7 | * Sponsored by Quicklink Video Distribution Services Ltd. | ||
8 | * | ||
9 | * Based on the cdc_eem module. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/netdevice.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/ctype.h> | ||
22 | #include <linux/ethtool.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/mii.h> | ||
25 | #include <linux/usb.h> | ||
26 | #include <linux/crc32.h> | ||
27 | #include <linux/usb/cdc.h> | ||
28 | #include <linux/usb/usbnet.h> | ||
29 | #include <linux/gfp.h> | ||
30 | |||
31 | /* | ||
32 | * The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control | ||
33 | * handled by the "option" module and an ethernet data port handled by this | ||
34 | * module. | ||
35 | * | ||
36 | * The stick must first be switched into modem mode by usb_modeswitch | ||
37 | * or similar tool. Then the modem gets sent two initialization packets by | ||
38 | * this module, which gives the MAC address of the device. User space can then | ||
39 | * connect the modem using AT commands through the ACM port and then use | ||
40 | * DHCP on the network interface exposed by this module. Network packets are | ||
41 | * sent to and from the modem in a proprietary format discovered after watching | ||
42 | * the behavior of the windows driver for the modem. | ||
43 | * | ||
44 | * More information about the use of the modem is available in usb_modeswitch | ||
45 | * forum and the project page: | ||
46 | * | ||
47 | * http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465 | ||
48 | * https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver | ||
49 | */ | ||
50 | |||
51 | /* #define DEBUG */ | ||
52 | /* #define VERBOSE */ | ||
53 | |||
54 | #define KALMIA_HEADER_LENGTH 6 | ||
55 | #define KALMIA_ALIGN_SIZE 4 | ||
56 | #define KALMIA_USB_TIMEOUT 10000 | ||
57 | |||
58 | /*-------------------------------------------------------------------------*/ | ||
59 | |||
60 | static int | ||
61 | kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len, | ||
62 | u8 *buffer, u8 expected_len) | ||
63 | { | ||
64 | int act_len; | ||
65 | int status; | ||
66 | |||
67 | netdev_dbg(dev->net, "Sending init packet"); | ||
68 | |||
69 | status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02), | ||
70 | init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT); | ||
71 | if (status != 0) { | ||
72 | netdev_err(dev->net, | ||
73 | "Error sending init packet. Status %i, length %i\n", | ||
74 | status, act_len); | ||
75 | return status; | ||
76 | } | ||
77 | else if (act_len != init_msg_len) { | ||
78 | netdev_err(dev->net, | ||
79 | "Did not send all of init packet. Bytes sent: %i", | ||
80 | act_len); | ||
81 | } | ||
82 | else { | ||
83 | netdev_dbg(dev->net, "Successfully sent init packet."); | ||
84 | } | ||
85 | |||
86 | status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81), | ||
87 | buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT); | ||
88 | |||
89 | if (status != 0) | ||
90 | netdev_err(dev->net, | ||
91 | "Error receiving init result. Status %i, length %i\n", | ||
92 | status, act_len); | ||
93 | else if (act_len != expected_len) | ||
94 | netdev_err(dev->net, "Unexpected init result length: %i\n", | ||
95 | act_len); | ||
96 | |||
97 | return status; | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr) | ||
102 | { | ||
103 | const static char init_msg_1[] = | ||
104 | { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, | ||
105 | 0x00, 0x00 }; | ||
106 | const static char init_msg_2[] = | ||
107 | { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4, | ||
108 | 0x00, 0x00 }; | ||
109 | const static int buflen = 28; | ||
110 | char *usb_buf; | ||
111 | int status; | ||
112 | |||
113 | usb_buf = kmalloc(buflen, GFP_DMA | GFP_KERNEL); | ||
114 | if (!usb_buf) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | memcpy(usb_buf, init_msg_1, 12); | ||
118 | status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_1) | ||
119 | / sizeof(init_msg_1[0]), usb_buf, 24); | ||
120 | if (status != 0) | ||
121 | return status; | ||
122 | |||
123 | memcpy(usb_buf, init_msg_2, 12); | ||
124 | status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_2) | ||
125 | / sizeof(init_msg_2[0]), usb_buf, 28); | ||
126 | if (status != 0) | ||
127 | return status; | ||
128 | |||
129 | memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN); | ||
130 | |||
131 | kfree(usb_buf); | ||
132 | return status; | ||
133 | } | ||
134 | |||
135 | static int | ||
136 | kalmia_bind(struct usbnet *dev, struct usb_interface *intf) | ||
137 | { | ||
138 | int status; | ||
139 | u8 ethernet_addr[ETH_ALEN]; | ||
140 | |||
141 | /* Don't bind to AT command interface */ | ||
142 | if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) | ||
143 | return -EINVAL; | ||
144 | |||
145 | dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK); | ||
146 | dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK); | ||
147 | dev->status = NULL; | ||
148 | |||
149 | dev->net->hard_header_len += KALMIA_HEADER_LENGTH; | ||
150 | dev->hard_mtu = 1400; | ||
151 | dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing | ||
152 | |||
153 | status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr); | ||
154 | |||
155 | if (status < 0) { | ||
156 | usb_set_intfdata(intf, NULL); | ||
157 | usb_driver_release_interface(driver_of(intf), intf); | ||
158 | return status; | ||
159 | } | ||
160 | |||
161 | memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN); | ||
162 | memcpy(dev->net->perm_addr, ethernet_addr, ETH_ALEN); | ||
163 | |||
164 | return status; | ||
165 | } | ||
166 | |||
167 | static struct sk_buff * | ||
168 | kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | ||
169 | { | ||
170 | struct sk_buff *skb2 = NULL; | ||
171 | u16 content_len; | ||
172 | unsigned char *header_start; | ||
173 | unsigned char ether_type_1, ether_type_2; | ||
174 | u8 remainder, padlen = 0; | ||
175 | |||
176 | if (!skb_cloned(skb)) { | ||
177 | int headroom = skb_headroom(skb); | ||
178 | int tailroom = skb_tailroom(skb); | ||
179 | |||
180 | if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom | ||
181 | >= KALMIA_HEADER_LENGTH)) | ||
182 | goto done; | ||
183 | |||
184 | if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH | ||
185 | + KALMIA_ALIGN_SIZE)) { | ||
186 | skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH, | ||
187 | skb->data, skb->len); | ||
188 | skb_set_tail_pointer(skb, skb->len); | ||
189 | goto done; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH, | ||
194 | KALMIA_ALIGN_SIZE, flags); | ||
195 | if (!skb2) | ||
196 | return NULL; | ||
197 | |||
198 | dev_kfree_skb_any(skb); | ||
199 | skb = skb2; | ||
200 | |||
201 | done: | ||
202 | header_start = skb_push(skb, KALMIA_HEADER_LENGTH); | ||
203 | ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12]; | ||
204 | ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13]; | ||
205 | |||
206 | netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1, | ||
207 | ether_type_2); | ||
208 | |||
209 | /* According to empiric data for data packages */ | ||
210 | header_start[0] = 0x57; | ||
211 | header_start[1] = 0x44; | ||
212 | content_len = skb->len - KALMIA_HEADER_LENGTH; | ||
213 | |||
214 | put_unaligned_le16(content_len, &header_start[2]); | ||
215 | header_start[4] = ether_type_1; | ||
216 | header_start[5] = ether_type_2; | ||
217 | |||
218 | /* Align to 4 bytes by padding with zeros */ | ||
219 | remainder = skb->len % KALMIA_ALIGN_SIZE; | ||
220 | if (remainder > 0) { | ||
221 | padlen = KALMIA_ALIGN_SIZE - remainder; | ||
222 | memset(skb_put(skb, padlen), 0, padlen); | ||
223 | } | ||
224 | |||
225 | netdev_dbg( | ||
226 | dev->net, | ||
227 | "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.", | ||
228 | content_len, padlen, header_start[0], header_start[1], | ||
229 | header_start[2], header_start[3], header_start[4], | ||
230 | header_start[5]); | ||
231 | |||
232 | return skb; | ||
233 | } | ||
234 | |||
235 | static int | ||
236 | kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
237 | { | ||
238 | /* | ||
239 | * Our task here is to strip off framing, leaving skb with one | ||
240 | * data frame for the usbnet framework code to process. | ||
241 | */ | ||
242 | const static u8 HEADER_END_OF_USB_PACKET[] = | ||
243 | { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 }; | ||
244 | const static u8 EXPECTED_UNKNOWN_HEADER_1[] = | ||
245 | { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 }; | ||
246 | const static u8 EXPECTED_UNKNOWN_HEADER_2[] = | ||
247 | { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 }; | ||
248 | int i = 0; | ||
249 | |||
250 | /* incomplete header? */ | ||
251 | if (skb->len < KALMIA_HEADER_LENGTH) | ||
252 | return 0; | ||
253 | |||
254 | do { | ||
255 | struct sk_buff *skb2 = NULL; | ||
256 | u8 *header_start; | ||
257 | u16 usb_packet_length, ether_packet_length; | ||
258 | int is_last; | ||
259 | |||
260 | header_start = skb->data; | ||
261 | |||
262 | if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) { | ||
263 | if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1, | ||
264 | sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp( | ||
265 | header_start, EXPECTED_UNKNOWN_HEADER_2, | ||
266 | sizeof(EXPECTED_UNKNOWN_HEADER_2))) { | ||
267 | netdev_dbg( | ||
268 | dev->net, | ||
269 | "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", | ||
270 | header_start[0], header_start[1], | ||
271 | header_start[2], header_start[3], | ||
272 | header_start[4], header_start[5], | ||
273 | skb->len - KALMIA_HEADER_LENGTH); | ||
274 | } | ||
275 | else { | ||
276 | netdev_err( | ||
277 | dev->net, | ||
278 | "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", | ||
279 | header_start[0], header_start[1], | ||
280 | header_start[2], header_start[3], | ||
281 | header_start[4], header_start[5], | ||
282 | skb->len - KALMIA_HEADER_LENGTH); | ||
283 | return 0; | ||
284 | } | ||
285 | } | ||
286 | else | ||
287 | netdev_dbg( | ||
288 | dev->net, | ||
289 | "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", | ||
290 | header_start[0], header_start[1], header_start[2], | ||
291 | header_start[3], header_start[4], header_start[5], | ||
292 | skb->len - KALMIA_HEADER_LENGTH); | ||
293 | |||
294 | /* subtract start header and end header */ | ||
295 | usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH); | ||
296 | ether_packet_length = get_unaligned_le16(&header_start[2]); | ||
297 | skb_pull(skb, KALMIA_HEADER_LENGTH); | ||
298 | |||
299 | /* Some small packets misses end marker */ | ||
300 | if (usb_packet_length < ether_packet_length) { | ||
301 | ether_packet_length = usb_packet_length | ||
302 | + KALMIA_HEADER_LENGTH; | ||
303 | is_last = true; | ||
304 | } | ||
305 | else { | ||
306 | netdev_dbg(dev->net, "Correct package length #%i", i | ||
307 | + 1); | ||
308 | |||
309 | is_last = (memcmp(skb->data + ether_packet_length, | ||
310 | HEADER_END_OF_USB_PACKET, | ||
311 | sizeof(HEADER_END_OF_USB_PACKET)) == 0); | ||
312 | if (!is_last) { | ||
313 | header_start = skb->data + ether_packet_length; | ||
314 | netdev_dbg( | ||
315 | dev->net, | ||
316 | "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n", | ||
317 | header_start[0], header_start[1], | ||
318 | header_start[2], header_start[3], | ||
319 | header_start[4], header_start[5], | ||
320 | skb->len - KALMIA_HEADER_LENGTH); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | if (is_last) { | ||
325 | skb2 = skb; | ||
326 | } | ||
327 | else { | ||
328 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
329 | if (unlikely(!skb2)) | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | skb_trim(skb2, ether_packet_length); | ||
334 | |||
335 | if (is_last) { | ||
336 | return 1; | ||
337 | } | ||
338 | else { | ||
339 | usbnet_skb_return(dev, skb2); | ||
340 | skb_pull(skb, ether_packet_length); | ||
341 | } | ||
342 | |||
343 | i++; | ||
344 | } | ||
345 | while (skb->len); | ||
346 | |||
347 | return 1; | ||
348 | } | ||
349 | |||
350 | static const struct driver_info kalmia_info = { | ||
351 | .description = "Samsung Kalmia LTE USB dongle", | ||
352 | .flags = FLAG_WWAN, | ||
353 | .bind = kalmia_bind, | ||
354 | .rx_fixup = kalmia_rx_fixup, | ||
355 | .tx_fixup = kalmia_tx_fixup | ||
356 | }; | ||
357 | |||
358 | /*-------------------------------------------------------------------------*/ | ||
359 | |||
360 | static const struct usb_device_id products[] = { | ||
361 | /* The unswitched USB ID, to get the module auto loaded: */ | ||
362 | { USB_DEVICE(0x04e8, 0x689a) }, | ||
363 | /* The stick swithed into modem (by e.g. usb_modeswitch): */ | ||
364 | { USB_DEVICE(0x04e8, 0x6889), | ||
365 | .driver_info = (unsigned long) &kalmia_info, }, | ||
366 | { /* EMPTY == end of list */} }; | ||
367 | MODULE_DEVICE_TABLE( usb, products); | ||
368 | |||
369 | static struct usb_driver kalmia_driver = { | ||
370 | .name = "kalmia", | ||
371 | .id_table = products, | ||
372 | .probe = usbnet_probe, | ||
373 | .disconnect = usbnet_disconnect, | ||
374 | .suspend = usbnet_suspend, | ||
375 | .resume = usbnet_resume | ||
376 | }; | ||
377 | |||
378 | static int __init kalmia_init(void) | ||
379 | { | ||
380 | return usb_register(&kalmia_driver); | ||
381 | } | ||
382 | module_init( kalmia_init); | ||
383 | |||
384 | static void __exit kalmia_exit(void) | ||
385 | { | ||
386 | usb_deregister(&kalmia_driver); | ||
387 | } | ||
388 | module_exit( kalmia_exit); | ||
389 | |||
390 | MODULE_AUTHOR("Marius Bjoernstad Kotsbak <marius@kotsbak.com>"); | ||
391 | MODULE_DESCRIPTION("Samsung Kalmia USB network driver"); | ||
392 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 241756e0e86f..1a2234c20514 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c | |||
@@ -331,17 +331,7 @@ static const struct usb_device_id products [] = { | |||
331 | ZAURUS_MASTER_INTERFACE, | 331 | ZAURUS_MASTER_INTERFACE, |
332 | .driver_info = ZAURUS_PXA_INFO, | 332 | .driver_info = ZAURUS_PXA_INFO, |
333 | }, | 333 | }, |
334 | |||
335 | |||
336 | /* At least some of the newest PXA units have very different lies about | ||
337 | * their standards support: they claim to be cell phones offering | ||
338 | * direct access to their radios! (No, they don't conform to CDC MDLM.) | ||
339 | */ | ||
340 | { | 334 | { |
341 | USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, | ||
342 | USB_CDC_PROTO_NONE), | ||
343 | .driver_info = (unsigned long) &bogus_mdlm_info, | ||
344 | }, { | ||
345 | /* Motorola MOTOMAGX phones */ | 335 | /* Motorola MOTOMAGX phones */ |
346 | USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, | 336 | USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM, |
347 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), | 337 | USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE), |