OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [usb/] [rndis_host.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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/module.h>
24
#include <linux/init.h>
25
#include <linux/netdevice.h>
26
#include <linux/etherdevice.h>
27
#include <linux/ethtool.h>
28
#include <linux/workqueue.h>
29
#include <linux/mii.h>
30
#include <linux/usb.h>
31
#include <linux/usb/cdc.h>
32
 
33
#include "usbnet.h"
34
 
35
 
36
/*
37
 * RNDIS is NDIS remoted over USB.  It's a MSFT variant of CDC ACM ... of
38
 * course ACM was intended for modems, not Ethernet links!  USB's standard
39
 * for Ethernet links is "CDC Ethernet", which is significantly simpler.
40
 *
41
 * NOTE that Microsoft's "RNDIS 1.0" specification is incomplete.  Issues
42
 * include:
43
 *    - Power management in particular relies on information that's scattered
44
 *      through other documentation, and which is incomplete or incorrect even
45
 *      there.
46
 *    - There are various undocumented protocol requirements, such as the
47
 *      need to send unused garbage in control-OUT messages.
48
 *    - In some cases, MS-Windows will emit undocumented requests; this
49
 *      matters more to peripheral implementations than host ones.
50
 *
51
 * Moreover there's a no-open-specs variant of RNDIS called "ActiveSync".
52
 *
53
 * For these reasons and others, ** USE OF RNDIS IS STRONGLY DISCOURAGED ** in
54
 * favor of such non-proprietary alternatives as CDC Ethernet or the newer (and
55
 * currently rare) "Ethernet Emulation Model" (EEM).
56
 */
57
 
58
/*
59
 * CONTROL uses CDC "encapsulated commands" with funky notifications.
60
 *  - control-out:  SEND_ENCAPSULATED
61
 *  - interrupt-in:  RESPONSE_AVAILABLE
62
 *  - control-in:  GET_ENCAPSULATED
63
 *
64
 * We'll try to ignore the RESPONSE_AVAILABLE notifications.
65
 *
66
 * REVISIT some RNDIS implementations seem to have curious issues still
67
 * to be resolved.
68
 */
69
struct rndis_msg_hdr {
70
        __le32  msg_type;                       /* RNDIS_MSG_* */
71
        __le32  msg_len;
72
        // followed by data that varies between messages
73
        __le32  request_id;
74
        __le32  status;
75
        // ... and more
76
} __attribute__ ((packed));
77
 
78
/* MS-Windows uses this strange size, but RNDIS spec says 1024 minimum */
79
#define CONTROL_BUFFER_SIZE             1025
80
 
81
/* RNDIS defines an (absurdly huge) 10 second control timeout,
82
 * but ActiveSync seems to use a more usual 5 second timeout
83
 * (which matches the USB 2.0 spec).
84
 */
85
#define RNDIS_CONTROL_TIMEOUT_MS        (5 * 1000)
86
 
87
 
88
#define ccpu2 __constant_cpu_to_le32
89
 
90
#define RNDIS_MSG_COMPLETION    ccpu2(0x80000000)
91
 
92
/* codes for "msg_type" field of rndis messages;
93
 * only the data channel uses packet messages (maybe batched);
94
 * everything else goes on the control channel.
95
 */
96
#define RNDIS_MSG_PACKET        ccpu2(0x00000001)       /* 1-N packets */
97
#define RNDIS_MSG_INIT          ccpu2(0x00000002)
98
#define RNDIS_MSG_INIT_C        (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION)
99
#define RNDIS_MSG_HALT          ccpu2(0x00000003)
100
#define RNDIS_MSG_QUERY         ccpu2(0x00000004)
101
#define RNDIS_MSG_QUERY_C       (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION)
102
#define RNDIS_MSG_SET           ccpu2(0x00000005)
103
#define RNDIS_MSG_SET_C         (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION)
104
#define RNDIS_MSG_RESET         ccpu2(0x00000006)
105
#define RNDIS_MSG_RESET_C       (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION)
106
#define RNDIS_MSG_INDICATE      ccpu2(0x00000007)
107
#define RNDIS_MSG_KEEPALIVE     ccpu2(0x00000008)
108
#define RNDIS_MSG_KEEPALIVE_C   (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION)
109
 
110
/* codes for "status" field of completion messages */
111
#define RNDIS_STATUS_SUCCESS            ccpu2(0x00000000)
112
#define RNDIS_STATUS_FAILURE            ccpu2(0xc0000001)
113
#define RNDIS_STATUS_INVALID_DATA       ccpu2(0xc0010015)
114
#define RNDIS_STATUS_NOT_SUPPORTED      ccpu2(0xc00000bb)
115
#define RNDIS_STATUS_MEDIA_CONNECT      ccpu2(0x4001000b)
116
#define RNDIS_STATUS_MEDIA_DISCONNECT   ccpu2(0x4001000c)
117
 
118
 
119
struct rndis_data_hdr {
120
        __le32  msg_type;               /* RNDIS_MSG_PACKET */
121
        __le32  msg_len;                // rndis_data_hdr + data_len + pad
122
        __le32  data_offset;            // 36 -- right after header
123
        __le32  data_len;               // ... real packet size
124
 
125
        __le32  oob_data_offset;        // zero
126
        __le32  oob_data_len;           // zero
127
        __le32  num_oob;                // zero
128
        __le32  packet_data_offset;     // zero
129
 
130
        __le32  packet_data_len;        // zero
131
        __le32  vc_handle;              // zero
132
        __le32  reserved;               // zero
133
} __attribute__ ((packed));
134
 
135
struct rndis_init {             /* OUT */
136
        // header and:
137
        __le32  msg_type;                       /* RNDIS_MSG_INIT */
138
        __le32  msg_len;                        // 24
139
        __le32  request_id;
140
        __le32  major_version;                  // of rndis (1.0)
141
        __le32  minor_version;
142
        __le32  max_transfer_size;
143
} __attribute__ ((packed));
144
 
145
struct rndis_init_c {           /* IN */
146
        // header and:
147
        __le32  msg_type;                       /* RNDIS_MSG_INIT_C */
148
        __le32  msg_len;
149
        __le32  request_id;
150
        __le32  status;
151
        __le32  major_version;                  // of rndis (1.0)
152
        __le32  minor_version;
153
        __le32  device_flags;
154
        __le32  medium;                         // zero == 802.3
155
        __le32  max_packets_per_message;
156
        __le32  max_transfer_size;
157
        __le32  packet_alignment;               // max 7; (1<<n) bytes
158
        __le32  af_list_offset;                 // zero
159
        __le32  af_list_size;                   // zero
160
} __attribute__ ((packed));
161
 
162
struct rndis_halt {             /* OUT (no reply) */
163
        // header and:
164
        __le32  msg_type;                       /* RNDIS_MSG_HALT */
165
        __le32  msg_len;
166
        __le32  request_id;
167
} __attribute__ ((packed));
168
 
169
struct rndis_query {            /* OUT */
170
        // header and:
171
        __le32  msg_type;                       /* RNDIS_MSG_QUERY */
172
        __le32  msg_len;
173
        __le32  request_id;
174
        __le32  oid;
175
        __le32  len;
176
        __le32  offset;
177
/*?*/   __le32  handle;                         // zero
178
} __attribute__ ((packed));
179
 
180
struct rndis_query_c {          /* IN */
181
        // header and:
182
        __le32  msg_type;                       /* RNDIS_MSG_QUERY_C */
183
        __le32  msg_len;
184
        __le32  request_id;
185
        __le32  status;
186
        __le32  len;
187
        __le32  offset;
188
} __attribute__ ((packed));
189
 
190
struct rndis_set {              /* OUT */
191
        // header and:
192
        __le32  msg_type;                       /* RNDIS_MSG_SET */
193
        __le32  msg_len;
194
        __le32  request_id;
195
        __le32  oid;
196
        __le32  len;
197
        __le32  offset;
198
/*?*/   __le32  handle;                         // zero
199
} __attribute__ ((packed));
200
 
201
struct rndis_set_c {            /* IN */
202
        // header and:
203
        __le32  msg_type;                       /* RNDIS_MSG_SET_C */
204
        __le32  msg_len;
205
        __le32  request_id;
206
        __le32  status;
207
} __attribute__ ((packed));
208
 
209
struct rndis_reset {            /* IN */
210
        // header and:
211
        __le32  msg_type;                       /* RNDIS_MSG_RESET */
212
        __le32  msg_len;
213
        __le32  reserved;
214
} __attribute__ ((packed));
215
 
216
struct rndis_reset_c {          /* OUT */
217
        // header and:
218
        __le32  msg_type;                       /* RNDIS_MSG_RESET_C */
219
        __le32  msg_len;
220
        __le32  status;
221
        __le32  addressing_lost;
222
} __attribute__ ((packed));
223
 
224
struct rndis_indicate {         /* IN (unrequested) */
225
        // header and:
226
        __le32  msg_type;                       /* RNDIS_MSG_INDICATE */
227
        __le32  msg_len;
228
        __le32  status;
229
        __le32  length;
230
        __le32  offset;
231
/**/    __le32  diag_status;
232
        __le32  error_offset;
233
/**/    __le32  message;
234
} __attribute__ ((packed));
235
 
236
struct rndis_keepalive {        /* OUT (optionally IN) */
237
        // header and:
238
        __le32  msg_type;                       /* RNDIS_MSG_KEEPALIVE */
239
        __le32  msg_len;
240
        __le32  request_id;
241
} __attribute__ ((packed));
242
 
243
struct rndis_keepalive_c {      /* IN (optionally OUT) */
244
        // header and:
245
        __le32  msg_type;                       /* RNDIS_MSG_KEEPALIVE_C */
246
        __le32  msg_len;
247
        __le32  request_id;
248
        __le32  status;
249
} __attribute__ ((packed));
250
 
251
/* NOTE:  about 30 OIDs are "mandatory" for peripherals to support ... and
252
 * there are gobs more that may optionally be supported.  We'll avoid as much
253
 * of that mess as possible.
254
 */
255
#define OID_802_3_PERMANENT_ADDRESS     ccpu2(0x01010101)
256
#define OID_GEN_MAXIMUM_FRAME_SIZE      ccpu2(0x00010106)
257
#define OID_GEN_CURRENT_PACKET_FILTER   ccpu2(0x0001010e)
258
 
259
/*
260
 * RNDIS notifications from device: command completion; "reverse"
261
 * keepalives; etc
262
 */
263
static void rndis_status(struct usbnet *dev, struct urb *urb)
264
{
265
        devdbg(dev, "rndis status urb, len %d stat %d",
266
                urb->actual_length, urb->status);
267
        // FIXME for keepalives, respond immediately (asynchronously)
268
        // if not an RNDIS status, do like cdc_status(dev,urb) does
269
}
270
 
271
/*
272
 * RPC done RNDIS-style.  Caller guarantees:
273
 * - message is properly byteswapped
274
 * - there's no other request pending
275
 * - buf can hold up to 1KB response (required by RNDIS spec)
276
 * On return, the first few entries are already byteswapped.
277
 *
278
 * Call context is likely probe(), before interface name is known,
279
 * which is why we won't try to use it in the diagnostics.
280
 */
281
static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf)
282
{
283
        struct cdc_state        *info = (void *) &dev->data;
284
        int                     master_ifnum;
285
        int                     retval;
286
        unsigned                count;
287
        __le32                  rsp;
288
        u32                     xid = 0, msg_len, request_id;
289
 
290
        /* REVISIT when this gets called from contexts other than probe() or
291
         * disconnect(): either serialize, or dispatch responses on xid
292
         */
293
 
294
        /* Issue the request; xid is unique, don't bother byteswapping it */
295
        if (likely(buf->msg_type != RNDIS_MSG_HALT
296
                        && buf->msg_type != RNDIS_MSG_RESET)) {
297
                xid = dev->xid++;
298
                if (!xid)
299
                        xid = dev->xid++;
300
                buf->request_id = (__force __le32) xid;
301
        }
302
        master_ifnum = info->control->cur_altsetting->desc.bInterfaceNumber;
303
        retval = usb_control_msg(dev->udev,
304
                usb_sndctrlpipe(dev->udev, 0),
305
                USB_CDC_SEND_ENCAPSULATED_COMMAND,
306
                USB_TYPE_CLASS | USB_RECIP_INTERFACE,
307
                0, master_ifnum,
308
                buf, le32_to_cpu(buf->msg_len),
309
                RNDIS_CONTROL_TIMEOUT_MS);
310
        if (unlikely(retval < 0 || xid == 0))
311
                return retval;
312
 
313
        // FIXME Seems like some devices discard responses when
314
        // we time out and cancel our "get response" requests...
315
        // so, this is fragile.  Probably need to poll for status.
316
 
317
        /* ignore status endpoint, just poll the control channel;
318
         * the request probably completed immediately
319
         */
320
        rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
321
        for (count = 0; count < 10; count++) {
322
                memset(buf, 0, CONTROL_BUFFER_SIZE);
323
                retval = usb_control_msg(dev->udev,
324
                        usb_rcvctrlpipe(dev->udev, 0),
325
                        USB_CDC_GET_ENCAPSULATED_RESPONSE,
326
                        USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
327
                        0, master_ifnum,
328
                        buf, CONTROL_BUFFER_SIZE,
329
                        RNDIS_CONTROL_TIMEOUT_MS);
330
                if (likely(retval >= 8)) {
331
                        msg_len = le32_to_cpu(buf->msg_len);
332
                        request_id = (__force u32) buf->request_id;
333
                        if (likely(buf->msg_type == rsp)) {
334
                                if (likely(request_id == xid)) {
335
                                        if (unlikely(rsp == RNDIS_MSG_RESET_C))
336
                                                return 0;
337
                                        if (likely(RNDIS_STATUS_SUCCESS
338
                                                        == buf->status))
339
                                                return 0;
340
                                        dev_dbg(&info->control->dev,
341
                                                "rndis reply status %08x\n",
342
                                                le32_to_cpu(buf->status));
343
                                        return -EL3RST;
344
                                }
345
                                dev_dbg(&info->control->dev,
346
                                        "rndis reply id %d expected %d\n",
347
                                        request_id, xid);
348
                                /* then likely retry */
349
                        } else switch (buf->msg_type) {
350
                        case RNDIS_MSG_INDICATE: {      /* fault */
351
                                // struct rndis_indicate *msg = (void *)buf;
352
                                dev_info(&info->control->dev,
353
                                        "rndis fault indication\n");
354
                                }
355
                                break;
356
                        case RNDIS_MSG_KEEPALIVE: {     /* ping */
357
                                struct rndis_keepalive_c *msg = (void *)buf;
358
 
359
                                msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
360
                                msg->msg_len = ccpu2(sizeof *msg);
361
                                msg->status = RNDIS_STATUS_SUCCESS;
362
                                retval = usb_control_msg(dev->udev,
363
                                        usb_sndctrlpipe(dev->udev, 0),
364
                                        USB_CDC_SEND_ENCAPSULATED_COMMAND,
365
                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE,
366
                                        0, master_ifnum,
367
                                        msg, sizeof *msg,
368
                                        RNDIS_CONTROL_TIMEOUT_MS);
369
                                if (unlikely(retval < 0))
370
                                        dev_dbg(&info->control->dev,
371
                                                "rndis keepalive err %d\n",
372
                                                retval);
373
                                }
374
                                break;
375
                        default:
376
                                dev_dbg(&info->control->dev,
377
                                        "unexpected rndis msg %08x len %d\n",
378
                                        le32_to_cpu(buf->msg_type), msg_len);
379
                        }
380
                } else {
381
                        /* device probably issued a protocol stall; ignore */
382
                        dev_dbg(&info->control->dev,
383
                                "rndis response error, code %d\n", retval);
384
                }
385
                msleep(2);
386
        }
387
        dev_dbg(&info->control->dev, "rndis response timeout\n");
388
        return -ETIMEDOUT;
389
}
390
 
391
/*
392
 * rndis_query:
393
 *
394
 * Performs a query for @oid along with 0 or more bytes of payload as
395
 * specified by @in_len. If @reply_len is not set to -1 then the reply
396
 * length is checked against this value, resulting in an error if it
397
 * doesn't match.
398
 *
399
 * NOTE: Adding a payload exactly or greater than the size of the expected
400
 * response payload is an evident requirement MSFT added for ActiveSync.
401
 *
402
 * The only exception is for OIDs that return a variably sized response,
403
 * in which case no payload should be added.  This undocumented (and
404
 * nonsensical!) issue was found by sniffing protocol requests from the
405
 * ActiveSync 4.1 Windows driver.
406
 */
407
static int rndis_query(struct usbnet *dev, struct usb_interface *intf,
408
                void *buf, u32 oid, u32 in_len,
409
                void **reply, int *reply_len)
410
{
411
        int retval;
412
        union {
413
                void                    *buf;
414
                struct rndis_msg_hdr    *header;
415
                struct rndis_query      *get;
416
                struct rndis_query_c    *get_c;
417
        } u;
418
        u32 off, len;
419
 
420
        u.buf = buf;
421
 
422
        memset(u.get, 0, sizeof *u.get + in_len);
423
        u.get->msg_type = RNDIS_MSG_QUERY;
424
        u.get->msg_len = cpu_to_le32(sizeof *u.get + in_len);
425
        u.get->oid = oid;
426
        u.get->len = cpu_to_le32(in_len);
427
        u.get->offset = ccpu2(20);
428
 
429
        retval = rndis_command(dev, u.header);
430
        if (unlikely(retval < 0)) {
431
                dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) failed, %d\n",
432
                                oid, retval);
433
                return retval;
434
        }
435
 
436
        off = le32_to_cpu(u.get_c->offset);
437
        len = le32_to_cpu(u.get_c->len);
438
        if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE))
439
                goto response_error;
440
 
441
        if (*reply_len != -1 && len != *reply_len)
442
                goto response_error;
443
 
444
        *reply = (unsigned char *) &u.get_c->request_id + off;
445
        *reply_len = len;
446
 
447
        return retval;
448
 
449
response_error:
450
        dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) "
451
                        "invalid response - off %d len %d\n",
452
                oid, off, len);
453
        return -EDOM;
454
}
455
 
456
static int rndis_bind(struct usbnet *dev, struct usb_interface *intf)
457
{
458
        int                     retval;
459
        struct net_device       *net = dev->net;
460
        struct cdc_state        *info = (void *) &dev->data;
461
        union {
462
                void                    *buf;
463
                struct rndis_msg_hdr    *header;
464
                struct rndis_init       *init;
465
                struct rndis_init_c     *init_c;
466
                struct rndis_query      *get;
467
                struct rndis_query_c    *get_c;
468
                struct rndis_set        *set;
469
                struct rndis_set_c      *set_c;
470
        } u;
471
        u32                     tmp;
472
        int                     reply_len;
473
        unsigned char           *bp;
474
 
475
        /* we can't rely on i/o from stack working, or stack allocation */
476
        u.buf = kmalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
477
        if (!u.buf)
478
                return -ENOMEM;
479
        retval = usbnet_generic_cdc_bind(dev, intf);
480
        if (retval < 0)
481
                goto fail;
482
 
483
        u.init->msg_type = RNDIS_MSG_INIT;
484
        u.init->msg_len = ccpu2(sizeof *u.init);
485
        u.init->major_version = ccpu2(1);
486
        u.init->minor_version = ccpu2(0);
487
 
488
        /* max transfer (in spec) is 0x4000 at full speed, but for
489
         * TX we'll stick to one Ethernet packet plus RNDIS framing.
490
         * For RX we handle drivers that zero-pad to end-of-packet.
491
         * Don't let userspace change these settings.
492
         *
493
         * NOTE: there still seems to be wierdness here, as if we need
494
         * to do some more things to make sure WinCE targets accept this.
495
         * They default to jumbograms of 8KB or 16KB, which is absurd
496
         * for such low data rates and which is also more than Linux
497
         * can usually expect to allocate for SKB data...
498
         */
499
        net->hard_header_len += sizeof (struct rndis_data_hdr);
500
        dev->hard_mtu = net->mtu + net->hard_header_len;
501
 
502
        dev->rx_urb_size = dev->hard_mtu + (dev->maxpacket + 1);
503
        dev->rx_urb_size &= ~(dev->maxpacket - 1);
504
        u.init->max_transfer_size = cpu_to_le32(dev->rx_urb_size);
505
 
506
        net->change_mtu = NULL;
507
        retval = rndis_command(dev, u.header);
508
        if (unlikely(retval < 0)) {
509
                /* it might not even be an RNDIS device!! */
510
                dev_err(&intf->dev, "RNDIS init failed, %d\n", retval);
511
                goto fail_and_release;
512
        }
513
        tmp = le32_to_cpu(u.init_c->max_transfer_size);
514
        if (tmp < dev->hard_mtu) {
515
                if (tmp <= net->hard_header_len) {
516
                        dev_err(&intf->dev,
517
                                "dev can't take %u byte packets (max %u)\n",
518
                                dev->hard_mtu, tmp);
519
                        retval = -EINVAL;
520
                        goto fail_and_release;
521
                }
522
                dev->hard_mtu = tmp;
523
                net->mtu = dev->hard_mtu - net->hard_header_len;
524
                dev_warn(&intf->dev,
525
                         "dev can't take %u byte packets (max %u), "
526
                         "adjusting MTU to %u\n",
527
                         dev->hard_mtu, tmp, net->mtu);
528
        }
529
 
530
        /* REVISIT:  peripheral "alignment" request is ignored ... */
531
        dev_dbg(&intf->dev,
532
                "hard mtu %u (%u from dev), rx buflen %Zu, align %d\n",
533
                dev->hard_mtu, tmp, dev->rx_urb_size,
534
                1 << le32_to_cpu(u.init_c->packet_alignment));
535
 
536
        /* Get designated host ethernet address */
537
        reply_len = ETH_ALEN;
538
        retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS,
539
                        48, (void **) &bp, &reply_len);
540
        if (unlikely(retval< 0)) {
541
                dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval);
542
                goto fail_and_release;
543
        }
544
        memcpy(net->dev_addr, bp, ETH_ALEN);
545
 
546
        /* set a nonzero filter to enable data transfers */
547
        memset(u.set, 0, sizeof *u.set);
548
        u.set->msg_type = RNDIS_MSG_SET;
549
        u.set->msg_len = ccpu2(4 + sizeof *u.set);
550
        u.set->oid = OID_GEN_CURRENT_PACKET_FILTER;
551
        u.set->len = ccpu2(4);
552
        u.set->offset = ccpu2((sizeof *u.set) - 8);
553
        *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER);
554
 
555
        retval = rndis_command(dev, u.header);
556
        if (unlikely(retval < 0)) {
557
                dev_err(&intf->dev, "rndis set packet filter, %d\n", retval);
558
                goto fail_and_release;
559
        }
560
 
561
        retval = 0;
562
 
563
        kfree(u.buf);
564
        return retval;
565
 
566
fail_and_release:
567
        usb_set_intfdata(info->data, NULL);
568
        usb_driver_release_interface(driver_of(intf), info->data);
569
        info->data = NULL;
570
fail:
571
        kfree(u.buf);
572
        return retval;
573
}
574
 
575
static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
576
{
577
        struct rndis_halt       *halt;
578
 
579
        /* try to clear any rndis state/activity (no i/o from stack!) */
580
        halt = kzalloc(sizeof *halt, GFP_KERNEL);
581
        if (halt) {
582
                halt->msg_type = RNDIS_MSG_HALT;
583
                halt->msg_len = ccpu2(sizeof *halt);
584
                (void) rndis_command(dev, (void *)halt);
585
                kfree(halt);
586
        }
587
 
588
        return usbnet_cdc_unbind(dev, intf);
589
}
590
 
591
/*
592
 * DATA -- host must not write zlps
593
 */
594
static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
595
{
596
        /* peripheral may have batched packets to us... */
597
        while (likely(skb->len)) {
598
                struct rndis_data_hdr   *hdr = (void *)skb->data;
599
                struct sk_buff          *skb2;
600
                u32                     msg_len, data_offset, data_len;
601
 
602
                msg_len = le32_to_cpu(hdr->msg_len);
603
                data_offset = le32_to_cpu(hdr->data_offset);
604
                data_len = le32_to_cpu(hdr->data_len);
605
 
606
                /* don't choke if we see oob, per-packet data, etc */
607
                if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
608
                                || skb->len < msg_len
609
                                || (data_offset + data_len + 8) > msg_len)) {
610
                        dev->stats.rx_frame_errors++;
611
                        devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
612
                                le32_to_cpu(hdr->msg_type),
613
                                msg_len, data_offset, data_len, skb->len);
614
                        return 0;
615
                }
616
                skb_pull(skb, 8 + data_offset);
617
 
618
                /* at most one packet left? */
619
                if (likely((data_len - skb->len) <= sizeof *hdr)) {
620
                        skb_trim(skb, data_len);
621
                        break;
622
                }
623
 
624
                /* try to return all the packets in the batch */
625
                skb2 = skb_clone(skb, GFP_ATOMIC);
626
                if (unlikely(!skb2))
627
                        break;
628
                skb_pull(skb, msg_len - sizeof *hdr);
629
                skb_trim(skb2, data_len);
630
                usbnet_skb_return(dev, skb2);
631
        }
632
 
633
        /* caller will usbnet_skb_return the remaining packet */
634
        return 1;
635
}
636
 
637
static struct sk_buff *
638
rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
639
{
640
        struct rndis_data_hdr   *hdr;
641
        struct sk_buff          *skb2;
642
        unsigned                len = skb->len;
643
 
644
        if (likely(!skb_cloned(skb))) {
645
                int     room = skb_headroom(skb);
646
 
647
                /* enough head room as-is? */
648
                if (unlikely((sizeof *hdr) <= room))
649
                        goto fill;
650
 
651
                /* enough room, but needs to be readjusted? */
652
                room += skb_tailroom(skb);
653
                if (likely((sizeof *hdr) <= room)) {
654
                        skb->data = memmove(skb->head + sizeof *hdr,
655
                                            skb->data, len);
656
                        skb_set_tail_pointer(skb, len);
657
                        goto fill;
658
                }
659
        }
660
 
661
        /* create a new skb, with the correct size (and tailpad) */
662
        skb2 = skb_copy_expand(skb, sizeof *hdr, 1, flags);
663
        dev_kfree_skb_any(skb);
664
        if (unlikely(!skb2))
665
                return skb2;
666
        skb = skb2;
667
 
668
        /* fill out the RNDIS header.  we won't bother trying to batch
669
         * packets; Linux minimizes wasted bandwidth through tx queues.
670
         */
671
fill:
672
        hdr = (void *) __skb_push(skb, sizeof *hdr);
673
        memset(hdr, 0, sizeof *hdr);
674
        hdr->msg_type = RNDIS_MSG_PACKET;
675
        hdr->msg_len = cpu_to_le32(skb->len);
676
        hdr->data_offset = ccpu2(sizeof(*hdr) - 8);
677
        hdr->data_len = cpu_to_le32(len);
678
 
679
        /* FIXME make the last packet always be short ... */
680
        return skb;
681
}
682
 
683
 
684
static const struct driver_info rndis_info = {
685
        .description =  "RNDIS device",
686
        .flags =        FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT,
687
        .bind =         rndis_bind,
688
        .unbind =       rndis_unbind,
689
        .status =       rndis_status,
690
        .rx_fixup =     rndis_rx_fixup,
691
        .tx_fixup =     rndis_tx_fixup,
692
};
693
 
694
#undef ccpu2
695
 
696
 
697
/*-------------------------------------------------------------------------*/
698
 
699
static const struct usb_device_id       products [] = {
700
{
701
        /* RNDIS is MSFT's un-official variant of CDC ACM */
702
        USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
703
        .driver_info = (unsigned long) &rndis_info,
704
}, {
705
        /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */
706
        USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1),
707
        .driver_info = (unsigned long) &rndis_info,
708
},
709
        { },            // END
710
};
711
MODULE_DEVICE_TABLE(usb, products);
712
 
713
static struct usb_driver rndis_driver = {
714
        .name =         "rndis_host",
715
        .id_table =     products,
716
        .probe =        usbnet_probe,
717
        .disconnect =   usbnet_disconnect,
718
        .suspend =      usbnet_suspend,
719
        .resume =       usbnet_resume,
720
};
721
 
722
static int __init rndis_init(void)
723
{
724
        return usb_register(&rndis_driver);
725
}
726
module_init(rndis_init);
727
 
728
static void __exit rndis_exit(void)
729
{
730
        usb_deregister(&rndis_driver);
731
}
732
module_exit(rndis_exit);
733
 
734
MODULE_AUTHOR("David Brownell");
735
MODULE_DESCRIPTION("USB Host side RNDIS driver");
736
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.