aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/net
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2005-08-31 12:54:36 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 19:28:33 -0400
commit64e049102d3de3e61409cb6019403a9e689dfda6 (patch)
treeede794cb59e0b5ae3fc72e901663646a12e04d38 /drivers/usb/net
parent4324fd493430c0ab99dd7e89d50540b5e70f8098 (diff)
[PATCH] USB: usbnet (8/9) module for RNDIS devices
This adds host-side RNDIS support to the "usbnet" driver, so Linux can talk to various devices (often based on WinCE) that otherwise only Windows could talk to. Tested with little-endian Linux talking to a Linux-USB Ethernet/RNDIS based peripheral. This also includes updates from Eddie C. Dost <ecd@brainaid.de> for big-endian SPARC Linux talking to a Nokia 9500 Communicator. It's still marked as EXPERIMENTAL because this code is so young. This ought to let Linux to work with various cable modems that previously would have been "Windows Only". Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/net')
-rw-r--r--drivers/usb/net/Kconfig13
-rw-r--r--drivers/usb/net/Makefile1
-rw-r--r--drivers/usb/net/rndis_host.c615
-rw-r--r--drivers/usb/net/usbnet.c9
4 files changed, 630 insertions, 8 deletions
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index 4921101d93d0..5f3ae1e06b1e 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -212,6 +212,19 @@ config USB_NET_NET1080
212 on this design: one NetChip 1080 chip and supporting logic, 212 on this design: one NetChip 1080 chip and supporting logic,
213 optionally with LEDs that indicate traffic 213 optionally with LEDs that indicate traffic
214 214
215config USB_NET_RNDIS_HOST
216 tristate "Host for RNDIS devices (EXPERIMENTAL)"
217 depends on USB_USBNET && EXPERIMENTAL
218 select USB_NET_CDCETHER
219 help
220 This option enables hosting "Remote NDIS" USB networking links,
221 as encouraged by Microsoft (instead of CDC Ethernet!) for use in
222 various devices that may only support this protocol.
223
224 Avoid using this protocol unless you have no better options.
225 The protocol specification is incomplete, and is controlled by
226 (and for) Microsoft; it isn't an "Open" ecosystem or market.
227
215config USB_NET_CDC_SUBSET 228config USB_NET_CDC_SUBSET
216 tristate "Simple USB Network Links (CDC Ethernet subset)" 229 tristate "Simple USB Network Links (CDC Ethernet subset)"
217 depends on USB_USBNET 230 depends on USB_USBNET
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index 697eb1913208..cb789c3ded53 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_NET_AX8817X) += asix.o
10obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o 10obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
11obj-$(CONFIG_USB_NET_GL620A) += gl620a.o 11obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
12obj-$(CONFIG_USB_NET_NET1080) += net1080.o 12obj-$(CONFIG_USB_NET_NET1080) += net1080.o
13obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o
13obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o 14obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o
14obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o 15obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o
15obj-$(CONFIG_USB_USBNET) += usbnet.o 16obj-$(CONFIG_USB_USBNET) += usbnet.o
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
new file mode 100644
index 000000000000..2ed2e5fb7778
--- /dev/null
+++ b/drivers/usb/net/rndis_host.c
@@ -0,0 +1,615 @@
1/*
2 * Host Side support for RNDIS Networking Links
3 * Copyright (C) 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/ethtool.h>
33#include <linux/workqueue.h>
34#include <linux/mii.h>
35#include <linux/usb.h>
36#include <linux/usb_cdc.h>
37
38#include "usbnet.h"
39
40
41/*
42 * RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of
43 * course ACM was intended for modems, not Ethernet links! USB's standard
44 * for Ethernet links is "CDC Ethernet", which is significantly simpler.
45 */
46
47/*
48 * CONTROL uses CDC "encapsulated commands" with funky notifications.
49 * - control-out: SEND_ENCAPSULATED
50 * - interrupt-in: RESPONSE_AVAILABLE
51 * - control-in: GET_ENCAPSULATED
52 *
53 * We'll try to ignore the RESPONSE_AVAILABLE notifications.
54 */
55struct rndis_msg_hdr {
56 __le32 msg_type; /* RNDIS_MSG_* */
57 __le32 msg_len;
58 // followed by data that varies between messages
59 __le32 request_id;
60 __le32 status;
61 // ... and more
62} __attribute__ ((packed));
63
64/* RNDIS defines this (absurdly huge) control timeout */
65#define RNDIS_CONTROL_TIMEOUT_MS (10 * 1000)
66
67
68#define ccpu2 __constant_cpu_to_le32
69
70#define RNDIS_MSG_COMPLETION ccpu2(0x80000000)
71
72/* codes for "msg_type" field of rndis messages;
73 * only the data channel uses packet messages (maybe batched);
74 * everything else goes on the control channel.
75 */
76#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */
77#define RNDIS_MSG_INIT ccpu2(0x00000002)
78#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
79#define RNDIS_MSG_HALT ccpu2(0x00000003)
80#define RNDIS_MSG_QUERY ccpu2(0x00000004)
81#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
82#define RNDIS_MSG_SET ccpu2(0x00000005)
83#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
84#define RNDIS_MSG_RESET ccpu2(0x00000006)
85#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
86#define RNDIS_MSG_INDICATE ccpu2(0x00000007)
87#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008)
88#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
89
90/* codes for "status" field of completion messages */
91#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000)
92#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001)
93#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015)
94#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb)
95#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b)
96#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c)
97
98
99struct rndis_data_hdr {
100 __le32 msg_type; /* RNDIS_MSG_PACKET */
101 __le32 msg_len; // rndis_data_hdr + data_len + pad
102 __le32 data_offset; // 36 -- right after header
103 __le32 data_len; // ... real packet size
104
105 __le32 oob_data_offset; // zero
106 __le32 oob_data_len; // zero
107 __le32 num_oob; // zero
108 __le32 packet_data_offset; // zero
109
110 __le32 packet_data_len; // zero
111 __le32 vc_handle; // zero
112 __le32 reserved; // zero
113} __attribute__ ((packed));
114
115struct rndis_init { /* OUT */
116 // header and:
117 __le32 msg_type; /* RNDIS_MSG_INIT */
118 __le32 msg_len; // 24
119 __le32 request_id;
120 __le32 major_version; // of rndis (1.0)
121 __le32 minor_version;
122 __le32 max_transfer_size;
123} __attribute__ ((packed));
124
125struct rndis_init_c { /* IN */
126 // header and:
127 __le32 msg_type; /* RNDIS_MSG_INIT_C */
128 __le32 msg_len;
129 __le32 request_id;
130 __le32 status;
131 __le32 major_version; // of rndis (1.0)
132 __le32 minor_version;
133 __le32 device_flags;
134 __le32 medium; // zero == 802.3
135 __le32 max_packets_per_message;
136 __le32 max_transfer_size;
137 __le32 packet_alignment; // max 7; (1<<n) bytes
138 __le32 af_list_offset; // zero
139 __le32 af_list_size; // zero
140} __attribute__ ((packed));
141
142struct rndis_halt { /* OUT (no reply) */
143 // header and:
144 __le32 msg_type; /* RNDIS_MSG_HALT */
145 __le32 msg_len;
146 __le32 request_id;
147} __attribute__ ((packed));
148
149struct rndis_query { /* OUT */
150 // header and:
151 __le32 msg_type; /* RNDIS_MSG_QUERY */
152 __le32 msg_len;
153 __le32 request_id;
154 __le32 oid;
155 __le32 len;
156 __le32 offset;
157/*?*/ __le32 handle; // zero
158} __attribute__ ((packed));
159
160struct rndis_query_c { /* IN */
161 // header and:
162 __le32 msg_type; /* RNDIS_MSG_QUERY_C */
163 __le32 msg_len;
164 __le32 request_id;
165 __le32 status;
166 __le32 len;
167 __le32 offset;
168} __attribute__ ((packed));
169
170struct rndis_set { /* OUT */
171 // header and:
172 __le32 msg_type; /* RNDIS_MSG_SET */
173 __le32 msg_len;
174 __le32 request_id;
175 __le32 oid;
176 __le32 len;
177 __le32 offset;
178/*?*/ __le32 handle; // zero
179} __attribute__ ((packed));
180
181struct rndis_set_c { /* IN */
182 // header and:
183 __le32 msg_type; /* RNDIS_MSG_SET_C */
184 __le32 msg_len;
185 __le32 request_id;
186 __le32 status;
187} __attribute__ ((packed));
188
189struct rndis_reset { /* IN */
190 // header and:
191 __le32 msg_type; /* RNDIS_MSG_RESET */
192 __le32 msg_len;
193 __le32 reserved;
194} __attribute__ ((packed));
195
196struct rndis_reset_c { /* OUT */
197 // header and:
198 __le32 msg_type; /* RNDIS_MSG_RESET_C */
199 __le32 msg_len;
200 __le32 status;
201 __le32 addressing_lost;
202} __attribute__ ((packed));
203
204struct rndis_indicate { /* IN (unrequested) */
205 // header and:
206 __le32 msg_type; /* RNDIS_MSG_INDICATE */
207 __le32 msg_len;
208 __le32 status;
209 __le32 length;
210 __le32 offset;
211/**/ __le32 diag_status;
212 __le32 error_offset;
213/**/ __le32 message;
214} __attribute__ ((packed));
215
216struct rndis_keepalive { /* OUT (optionally IN) */
217 // header and:
218 __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */
219 __le32 msg_len;
220 __le32 request_id;
221} __attribute__ ((packed));
222
223struct rndis_keepalive_c { /* IN (optionally OUT) */
224 // header and:
225 __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */
226 __le32 msg_len;
227 __le32 request_id;
228 __le32 status;
229} __attribute__ ((packed));
230
231/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and
232 * there are gobs more that may optionally be supported. We'll avoid as much
233 * of that mess as possible.
234 */
235#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101)
236#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e)
237
238/*
239 * RNDIS notifications from device: command completion; "reverse"
240 * keepalives; etc
241 */
242static void rndis_status(struct usbnet *dev, struct urb *urb)
243{
244 devdbg(dev, "rndis status urb, len %d stat %d",
245 urb->actual_length, urb->status);
246 // FIXME for keepalives, respond immediately (asynchronously)
247 // if not an RNDIS status, do like cdc_status(dev,urb) does
248}
249
250/*
251 * RPC done RNDIS-style. Caller guarantees:
252 * - message is properly byteswapped
253 * - there's no other request pending
254 * - buf can hold up to 1KB response (required by RNDIS spec)
255 * On return, the first few entries are already byteswapped.
256 *
257 * Call context is likely probe(), before interface name is known,
258 * which is why we won't try to use it in the diagnostics.
259 */
260static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
261{
262 struct cdc_state *info = (void *) &dev->data;
263 int retval;
264 unsigned count;
265 __le32 rsp;
266 u32 xid = 0, msg_len, request_id;
267
268 /* REVISIT when this gets called from contexts other than probe() or
269 * disconnect(): either serialize, or dispatch responses on xid
270 */
271
272 /* Issue the request; don't bother byteswapping our xid */
273 if (likely(buf->msg_type != RNDIS_MSG_HALT
274 && buf->msg_type != RNDIS_MSG_RESET)) {
275 xid = dev->xid++;
276 if (!xid)
277 xid = dev->xid++;
278 buf->request_id = (__force __le32) xid;
279 }
280 retval = usb_control_msg(dev->udev,
281 usb_sndctrlpipe(dev->udev, 0),
282 USB_CDC_SEND_ENCAPSULATED_COMMAND,
283 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
284 0, info->u->bMasterInterface0,
285 buf, le32_to_cpu(buf->msg_len),
286 RNDIS_CONTROL_TIMEOUT_MS);
287 if (unlikely(retval < 0 || xid == 0))
288 return retval;
289
290 // FIXME Seems like some devices discard responses when
291 // we time out and cancel our "get response" requests...
292 // so, this is fragile. Probably need to poll for status.
293
294 /* ignore status endpoint, just poll the control channel;
295 * the request probably completed immediately
296 */
297 rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
298 for (count = 0; count < 10; count++) {
299 memset(buf, 0, 1024);
300 retval = usb_control_msg(dev->udev,
301 usb_rcvctrlpipe(dev->udev, 0),
302 USB_CDC_GET_ENCAPSULATED_RESPONSE,
303 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
304 0, info->u->bMasterInterface0,
305 buf, 1024,
306 RNDIS_CONTROL_TIMEOUT_MS);
307 if (likely(retval >= 8)) {
308 msg_len = le32_to_cpu(buf->msg_len);
309 request_id = (__force u32) buf->request_id;
310 if (likely(buf->msg_type == rsp)) {
311 if (likely(request_id == xid)) {
312 if (unlikely(rsp == RNDIS_MSG_RESET_C))
313 return 0;
314 if (likely(RNDIS_STATUS_SUCCESS
315 == buf->status))
316 return 0;
317 dev_dbg(&info->control->dev,
318 "rndis reply status %08x\n",
319 le32_to_cpu(buf->status));
320 return -EL3RST;
321 }
322 dev_dbg(&info->control->dev,
323 "rndis reply id %d expected %d\n",
324 request_id, xid);
325 /* then likely retry */
326 } else switch (buf->msg_type) {
327 case RNDIS_MSG_INDICATE: { /* fault */
328 // struct rndis_indicate *msg = (void *)buf;
329 dev_info(&info->control->dev,
330 "rndis fault indication\n");
331 }
332 break;
333 case RNDIS_MSG_KEEPALIVE: { /* ping */
334 struct rndis_keepalive_c *msg = (void *)buf;
335
336 msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
337 msg->msg_len = ccpu2(sizeof *msg);
338 msg->status = RNDIS_STATUS_SUCCESS;
339 retval = usb_control_msg(dev->udev,
340 usb_sndctrlpipe(dev->udev, 0),
341 USB_CDC_SEND_ENCAPSULATED_COMMAND,
342 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
343 0, info->u->bMasterInterface0,
344 msg, sizeof *msg,
345 RNDIS_CONTROL_TIMEOUT_MS);
346 if (unlikely(retval < 0))
347 dev_dbg(&info->control->dev,
348 "rndis keepalive err %d\n",
349 retval);
350 }
351 break;
352 default:
353 dev_dbg(&info->control->dev,
354 "unexpected rndis msg %08x len %d\n",
355 le32_to_cpu(buf->msg_type), msg_len);
356 }
357 } else {
358 /* device probably issued a protocol stall; ignore */
359 dev_dbg(&info->control->dev,
360 "rndis response error, code %d\n", retval);
361 }
362 msleep(2);
363 }
364 dev_dbg(&info->control->dev, "rndis response timeout\n");
365 return -ETIMEDOUT;
366}
367
368static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
369{
370 int retval;
371 struct net_device *net = dev->net;
372 union {
373 void *buf;
374 struct rndis_msg_hdr *header;
375 struct rndis_init *init;
376 struct rndis_init_c *init_c;
377 struct rndis_query *get;
378 struct rndis_query_c *get_c;
379 struct rndis_set *set;
380 struct rndis_set_c *set_c;
381 } u;
382 u32 tmp;
383
384 /* we can't rely on i/o from stack working, or stack allocation */
385 u.buf = kmalloc(1024, GFP_KERNEL);
386 if (!u.buf)
387 return -ENOMEM;
388 retval = usbnet_generic_cdc_bind(dev, intf);
389 if (retval < 0)
390 goto done;
391
392 net->hard_header_len += sizeof (struct rndis_data_hdr);
393
394 /* initialize; max transfer is 16KB at full speed */
395 u.init->msg_type = RNDIS_MSG_INIT;
396 u.init->msg_len = ccpu2(sizeof *u.init);
397 u.init->major_version = ccpu2(1);
398 u.init->minor_version = ccpu2(0);
399 u.init->max_transfer_size = ccpu2(net->mtu + net->hard_header_len);
400
401 retval = rndis_command(dev, u.header);
402 if (unlikely(retval < 0)) {
403 /* it might not even be an RNDIS device!! */
404 dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
405fail:
406 usb_driver_release_interface(driver_of(intf),
407 ((struct cdc_state *)&(dev->data))->data);
408 goto done;
409 }
410 dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size);
411 /* REVISIT: peripheral "alignment" request is ignored ... */
412 dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu,
413 1 << le32_to_cpu(u.init_c->packet_alignment));
414
415 /* get designated host ethernet address */
416 memset(u.get, 0, sizeof *u.get);
417 u.get->msg_type = RNDIS_MSG_QUERY;
418 u.get->msg_len = ccpu2(sizeof *u.get);
419 u.get->oid = OID_802_3_PERMANENT_ADDRESS;
420
421 retval = rndis_command(dev, u.header);
422 if (unlikely(retval < 0)) {
423 dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
424 goto fail;
425 }
426 tmp = le32_to_cpu(u.get_c->offset);
427 if (unlikely((tmp + 8) > (1024 - ETH_ALEN)
428 || u.get_c->len != ccpu2(ETH_ALEN))) {
429 dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n",
430 tmp, le32_to_cpu(u.get_c->len));
431 retval = -EDOM;
432 goto fail;
433 }
434 memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN);
435
436 /* set a nonzero filter to enable data transfers */
437 memset(u.set, 0, sizeof *u.set);
438 u.set->msg_type = RNDIS_MSG_SET;
439 u.set->msg_len = ccpu2(4 + sizeof *u.set);
440 u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
441 u.set->len = ccpu2(4);
442 u.set->offset = ccpu2((sizeof *u.set) - 8);
443 *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER);
444
445 retval = rndis_command(dev, u.header);
446 if (unlikely(retval < 0)) {
447 dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
448 goto fail;
449 }
450
451 retval = 0;
452done:
453 kfree(u.buf);
454 return retval;
455}
456
457static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
458{
459 struct rndis_halt *halt;
460
461 /* try to clear any rndis state/activity (no i/o from stack!) */
462 halt = kcalloc(1, sizeof *halt, SLAB_KERNEL);
463 if (halt) {
464 halt->msg_type = RNDIS_MSG_HALT;
465 halt->msg_len = ccpu2(sizeof *halt);
466 (void) rndis_command(dev, (void *)halt);
467 kfree(halt);
468 }
469
470 return usbnet_cdc_unbind(dev, intf);
471}
472
473/*
474 * DATA -- host must not write zlps
475 */
476static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
477{
478 /* peripheral may have batched packets to us... */
479 while (likely(skb->len)) {
480 struct rndis_data_hdr *hdr = (void *)skb->data;
481 struct sk_buff *skb2;
482 u32 msg_len, data_offset, data_len;
483
484 msg_len = le32_to_cpu(hdr->msg_len);
485 data_offset = le32_to_cpu(hdr->data_offset);
486 data_len = le32_to_cpu(hdr->data_len);
487
488 /* don't choke if we see oob, per-packet data, etc */
489 if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
490 || skb->len < msg_len
491 || (data_offset + data_len + 8) > msg_len)) {
492 dev->stats.rx_frame_errors++;
493 devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
494 le32_to_cpu(hdr->msg_type),
495 msg_len, data_offset, data_len, skb->len);
496 return 0;
497 }
498 skb_pull(skb, 8 + data_offset);
499
500 /* at most one packet left? */
501 if (likely((data_len - skb->len) <= sizeof *hdr)) {
502 skb_trim(skb, data_len);
503 break;
504 }
505
506 /* try to return all the packets in the batch */
507 skb2 = skb_clone(skb, GFP_ATOMIC);
508 if (unlikely(!skb2))
509 break;
510 skb_pull(skb, msg_len - sizeof *hdr);
511 skb_trim(skb2, data_len);
512 usbnet_skb_return(dev, skb2);
513 }
514
515 /* caller will usbnet_skb_return the remaining packet */
516 return 1;
517}
518
519static struct sk_buff *
520rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, unsigned flags)
521{
522 struct rndis_data_hdr *hdr;
523 struct sk_buff *skb2;
524 unsigned len = skb->len;
525
526 if (likely(!skb_cloned(skb))) {
527 int room = skb_headroom(skb);
528
529 /* enough head room as-is? */
530 if (unlikely((sizeof *hdr) <= room))
531 goto fill;
532
533 /* enough room, but needs to be readjusted? */
534 room += skb_tailroom(skb);
535 if (likely((sizeof *hdr) <= room)) {
536 skb->data = memmove(skb->head + sizeof *hdr,
537 skb->data, len);
538 skb->tail = skb->data + len;
539 goto fill;
540 }
541 }
542
543 /* create a new skb, with the correct size (and tailpad) */
544 skb2 = skb_copy_expand(skb, sizeof *hdr, 1, flags);
545 dev_kfree_skb_any(skb);
546 if (unlikely(!skb2))
547 return skb2;
548 skb = skb2;
549
550 /* fill out the RNDIS header. we won't bother trying to batch
551 * packets; Linux minimizes wasted bandwidth through tx queues.
552 */
553fill:
554 hdr = (void *) __skb_push(skb, sizeof *hdr);
555 memset(hdr, 0, sizeof *hdr);
556 hdr->msg_type = RNDIS_MSG_PACKET;
557 hdr->msg_len = cpu_to_le32(skb->len);
558 hdr->data_offset = ccpu2(sizeof(*hdr) - 8);
559 hdr->data_len = cpu_to_le32(len);
560
561 /* FIXME make the last packet always be short ... */
562 return skb;
563}
564
565
566static const struct driver_info rndis_info = {
567 .description = "RNDIS device",
568 .flags = FLAG_ETHER | FLAG_FRAMING_RN,
569 .bind = rndis_bind,
570 .unbind = rndis_unbind,
571 .status = rndis_status,
572 .rx_fixup = rndis_rx_fixup,
573 .tx_fixup = rndis_tx_fixup,
574};
575
576#undef ccpu2
577
578
579/*-------------------------------------------------------------------------*/
580
581static const struct usb_device_id products [] = {
582{
583 /* RNDIS is MSFT's un-official variant of CDC ACM */
584 USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
585 .driver_info = (unsigned long) &rndis_info,
586},
587 { }, // END
588};
589MODULE_DEVICE_TABLE(usb, products);
590
591static struct usb_driver rndis_driver = {
592 .owner = THIS_MODULE,
593 .name = "rndis_host",
594 .id_table = products,
595 .probe = usbnet_probe,
596 .disconnect = usbnet_disconnect,
597 .suspend = usbnet_suspend,
598 .resume = usbnet_resume,
599};
600
601static int __init rndis_init(void)
602{
603 return usb_register(&rndis_driver);
604}
605module_init(rndis_init);
606
607static void __exit rndis_exit(void)
608{
609 usb_deregister(&rndis_driver);
610}
611module_exit(rndis_exit);
612
613MODULE_AUTHOR("David Brownell");
614MODULE_DESCRIPTION("USB Host side RNDIS driver");
615MODULE_LICENSE("GPL");
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 7703725327d2..6c78a42affaa 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -103,6 +103,7 @@
103 * disconnect; other cleanups. (db) Flush net1080 fifos 103 * disconnect; other cleanups. (db) Flush net1080 fifos
104 * after several sequential framing errors. (Johannes Erdfelt) 104 * after several sequential framing errors. (Johannes Erdfelt)
105 * 22-aug-2003 AX8817X support (Dave Hollis). 105 * 22-aug-2003 AX8817X support (Dave Hollis).
106 *
106 * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan 107 * 14-jun-2004 Trivial patch for AX8817X based Buffalo LUA-U2-KTX in Japan
107 * (Neil Bortnak) 108 * (Neil Bortnak)
108 * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell) 109 * 03-nov-2004 Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
@@ -1375,14 +1376,6 @@ static const struct usb_device_id products [] = {
1375 .driver_info = (unsigned long) &prolific_info, 1376 .driver_info = (unsigned long) &prolific_info,
1376}, 1377},
1377#endif 1378#endif
1378
1379#ifdef CONFIG_USB_RNDIS
1380{
1381 /* RNDIS is MSFT's un-official variant of CDC ACM */
1382 USB_INTERFACE_INFO (USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
1383 .driver_info = (unsigned long) &rndis_info,
1384},
1385#endif
1386 { }, // END 1379 { }, // END
1387}; 1380};
1388MODULE_DEVICE_TABLE (usb, products); 1381MODULE_DEVICE_TABLE (usb, products);