blob: 48463db0b2f594c29fcfa53da43a2245a32bafe4 [file] [log] [blame]
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +03001/*
2 * RNDIS MSG parser
3 *
4 * Authors: Benedikt Spranger, Pengutronix
5 * Robert Schwebel, Pengutronix
6 *
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +03007 * This software was originally developed in conformance with
8 * Microsoft's Remote NDIS Specification License Agreement.
9 *
10 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
11 * Fixed message length bug in init_response
12 *
13 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
14 * Fixed rndis_rm_hdr length bug.
15 *
16 * Copyright (C) 2004 by David Brownell
17 * updates to merge with Linux 2.6, better match RNDIS spec
Tom Rini5b8031c2016-01-14 22:05:13 -050018 *
19 * SPDX-License-Identifier: GPL-2.0
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +030020 */
21
22#include <common.h>
23#include <net.h>
24#include <malloc.h>
25#include <linux/types.h>
26#include <linux/list.h>
27#include <linux/netdevice.h>
28
29#include <asm/byteorder.h>
30#include <asm/unaligned.h>
31#include <asm/errno.h>
32
33#undef RNDIS_PM
34#undef RNDIS_WAKEUP
35#undef VERBOSE
36
37#include "rndis.h"
38
39#define ETH_ALEN 6 /* Octets in one ethernet addr */
40#define ETH_HLEN 14 /* Total octets in header. */
41#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
42#define ETH_DATA_LEN 1500 /* Max. octets in payload */
43#define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +030044#define ENOTSUPP 524 /* Operation is not supported */
45
46
47/*
48 * The driver for your USB chip needs to support ep0 OUT to work with
49 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
50 *
51 * Windows hosts need an INF file like Documentation/usb/linux.inf
52 * and will be happier if you provide the host_addr module parameter.
53 */
54
55#define RNDIS_MAX_CONFIGS 1
56
57static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
58
59/* Driver Version */
60static const __le32 rndis_driver_version = __constant_cpu_to_le32(1);
61
62/* Function Prototypes */
63static rndis_resp_t *rndis_add_response(int configNr, u32 length);
64
65
66/* supported OIDs */
67static const u32 oid_supported_list[] = {
68 /* the general stuff */
69 OID_GEN_SUPPORTED_LIST,
70 OID_GEN_HARDWARE_STATUS,
71 OID_GEN_MEDIA_SUPPORTED,
72 OID_GEN_MEDIA_IN_USE,
73 OID_GEN_MAXIMUM_FRAME_SIZE,
74 OID_GEN_LINK_SPEED,
75 OID_GEN_TRANSMIT_BLOCK_SIZE,
76 OID_GEN_RECEIVE_BLOCK_SIZE,
77 OID_GEN_VENDOR_ID,
78 OID_GEN_VENDOR_DESCRIPTION,
79 OID_GEN_VENDOR_DRIVER_VERSION,
80 OID_GEN_CURRENT_PACKET_FILTER,
81 OID_GEN_MAXIMUM_TOTAL_SIZE,
82 OID_GEN_MEDIA_CONNECT_STATUS,
83 OID_GEN_PHYSICAL_MEDIUM,
84#if 0
85 OID_GEN_RNDIS_CONFIG_PARAMETER,
86#endif
87
88 /* the statistical stuff */
89 OID_GEN_XMIT_OK,
90 OID_GEN_RCV_OK,
91 OID_GEN_XMIT_ERROR,
92 OID_GEN_RCV_ERROR,
93 OID_GEN_RCV_NO_BUFFER,
94#ifdef RNDIS_OPTIONAL_STATS
95 OID_GEN_DIRECTED_BYTES_XMIT,
96 OID_GEN_DIRECTED_FRAMES_XMIT,
97 OID_GEN_MULTICAST_BYTES_XMIT,
98 OID_GEN_MULTICAST_FRAMES_XMIT,
99 OID_GEN_BROADCAST_BYTES_XMIT,
100 OID_GEN_BROADCAST_FRAMES_XMIT,
101 OID_GEN_DIRECTED_BYTES_RCV,
102 OID_GEN_DIRECTED_FRAMES_RCV,
103 OID_GEN_MULTICAST_BYTES_RCV,
104 OID_GEN_MULTICAST_FRAMES_RCV,
105 OID_GEN_BROADCAST_BYTES_RCV,
106 OID_GEN_BROADCAST_FRAMES_RCV,
107 OID_GEN_RCV_CRC_ERROR,
108 OID_GEN_TRANSMIT_QUEUE_LENGTH,
109#endif /* RNDIS_OPTIONAL_STATS */
110
111 /* mandatory 802.3 */
112 /* the general stuff */
113 OID_802_3_PERMANENT_ADDRESS,
114 OID_802_3_CURRENT_ADDRESS,
115 OID_802_3_MULTICAST_LIST,
116 OID_802_3_MAC_OPTIONS,
117 OID_802_3_MAXIMUM_LIST_SIZE,
118
119 /* the statistical stuff */
120 OID_802_3_RCV_ERROR_ALIGNMENT,
121 OID_802_3_XMIT_ONE_COLLISION,
122 OID_802_3_XMIT_MORE_COLLISIONS,
123#ifdef RNDIS_OPTIONAL_STATS
124 OID_802_3_XMIT_DEFERRED,
125 OID_802_3_XMIT_MAX_COLLISIONS,
126 OID_802_3_RCV_OVERRUN,
127 OID_802_3_XMIT_UNDERRUN,
128 OID_802_3_XMIT_HEARTBEAT_FAILURE,
129 OID_802_3_XMIT_TIMES_CRS_LOST,
130 OID_802_3_XMIT_LATE_COLLISIONS,
131#endif /* RNDIS_OPTIONAL_STATS */
132
133#ifdef RNDIS_PM
134 /* PM and wakeup are mandatory for USB: */
135
136 /* power management */
137 OID_PNP_CAPABILITIES,
138 OID_PNP_QUERY_POWER,
139 OID_PNP_SET_POWER,
140
141#ifdef RNDIS_WAKEUP
142 /* wake up host */
143 OID_PNP_ENABLE_WAKE_UP,
144 OID_PNP_ADD_WAKE_UP_PATTERN,
145 OID_PNP_REMOVE_WAKE_UP_PATTERN,
146#endif /* RNDIS_WAKEUP */
147#endif /* RNDIS_PM */
148};
149
150
151/* NDIS Functions */
152static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
153 unsigned buf_len, rndis_resp_t *r)
154{
155 int retval = -ENOTSUPP;
156 u32 length = 4; /* usually */
157 __le32 *outbuf;
158 int i, count;
159 rndis_query_cmplt_type *resp;
160 rndis_params *params;
161
162 if (!r)
163 return -ENOMEM;
164 resp = (rndis_query_cmplt_type *) r->buf;
165
166 if (!resp)
167 return -ENOMEM;
168
169#if defined(DEBUG) && defined(DEBUG_VERBOSE)
170 if (buf_len) {
171 debug("query OID %08x value, len %d:\n", OID, buf_len);
172 for (i = 0; i < buf_len; i += 16) {
173 debug("%03d: %08x %08x %08x %08x\n", i,
174 get_unaligned_le32(&buf[i]),
175 get_unaligned_le32(&buf[i + 4]),
176 get_unaligned_le32(&buf[i + 8]),
177 get_unaligned_le32(&buf[i + 12]));
178 }
179 }
180#endif
181
182 /* response goes here, right after the header */
183 outbuf = (__le32 *) &resp[1];
184 resp->InformationBufferOffset = __constant_cpu_to_le32(16);
185
186 params = &rndis_per_dev_params[configNr];
187 switch (OID) {
188
189 /* general oids (table 4-1) */
190
191 /* mandatory */
192 case OID_GEN_SUPPORTED_LIST:
193 debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
194 length = sizeof(oid_supported_list);
195 count = length / sizeof(u32);
196 for (i = 0; i < count; i++)
197 outbuf[i] = cpu_to_le32(oid_supported_list[i]);
198 retval = 0;
199 break;
200
201 /* mandatory */
202 case OID_GEN_HARDWARE_STATUS:
203 debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
204 /*
205 * Bogus question!
206 * Hardware must be ready to receive high level protocols.
207 * BTW:
208 * reddite ergo quae sunt Caesaris Caesari
209 * et quae sunt Dei Deo!
210 */
211 *outbuf = __constant_cpu_to_le32(0);
212 retval = 0;
213 break;
214
215 /* mandatory */
216 case OID_GEN_MEDIA_SUPPORTED:
217 debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
218 *outbuf = cpu_to_le32(params->medium);
219 retval = 0;
220 break;
221
222 /* mandatory */
223 case OID_GEN_MEDIA_IN_USE:
224 debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
225 /* one medium, one transport... (maybe you do it better) */
226 *outbuf = cpu_to_le32(params->medium);
227 retval = 0;
228 break;
229
230 /* mandatory */
231 case OID_GEN_MAXIMUM_FRAME_SIZE:
232 debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
233 if (params->dev) {
234 *outbuf = cpu_to_le32(params->mtu);
235 retval = 0;
236 }
237 break;
238
239 /* mandatory */
240 case OID_GEN_LINK_SPEED:
241#if defined(DEBUG) && defined(DEBUG_VERBOSE)
242 debug("%s: OID_GEN_LINK_SPEED\n", __func__);
243#endif
244 if (params->media_state == NDIS_MEDIA_STATE_DISCONNECTED)
245 *outbuf = __constant_cpu_to_le32(0);
246 else
247 *outbuf = cpu_to_le32(params->speed);
248 retval = 0;
249 break;
250
251 /* mandatory */
252 case OID_GEN_TRANSMIT_BLOCK_SIZE:
253 debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
254 if (params->dev) {
255 *outbuf = cpu_to_le32(params->mtu);
256 retval = 0;
257 }
258 break;
259
260 /* mandatory */
261 case OID_GEN_RECEIVE_BLOCK_SIZE:
262 debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
263 if (params->dev) {
264 *outbuf = cpu_to_le32(params->mtu);
265 retval = 0;
266 }
267 break;
268
269 /* mandatory */
270 case OID_GEN_VENDOR_ID:
271 debug("%s: OID_GEN_VENDOR_ID\n", __func__);
272 *outbuf = cpu_to_le32(params->vendorID);
273 retval = 0;
274 break;
275
276 /* mandatory */
277 case OID_GEN_VENDOR_DESCRIPTION:
278 debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
279 length = strlen(params->vendorDescr);
280 memcpy(outbuf, params->vendorDescr, length);
281 retval = 0;
282 break;
283
284 case OID_GEN_VENDOR_DRIVER_VERSION:
285 debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
286 /* Created as LE */
287 *outbuf = rndis_driver_version;
288 retval = 0;
289 break;
290
291 /* mandatory */
292 case OID_GEN_CURRENT_PACKET_FILTER:
293 debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
294 *outbuf = cpu_to_le32(*params->filter);
295 retval = 0;
296 break;
297
298 /* mandatory */
299 case OID_GEN_MAXIMUM_TOTAL_SIZE:
300 debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
301 *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
302 retval = 0;
303 break;
304
305 /* mandatory */
306 case OID_GEN_MEDIA_CONNECT_STATUS:
307#if defined(DEBUG) && defined(DEBUG_VERBOSE)
308 debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
309#endif
310 *outbuf = cpu_to_le32(params->media_state);
311 retval = 0;
312 break;
313
314 case OID_GEN_PHYSICAL_MEDIUM:
315 debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
316 *outbuf = __constant_cpu_to_le32(0);
317 retval = 0;
318 break;
319
320 /*
321 * The RNDIS specification is incomplete/wrong. Some versions
322 * of MS-Windows expect OIDs that aren't specified there. Other
323 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
324 */
325 case OID_GEN_MAC_OPTIONS: /* from WinME */
326 debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
327 *outbuf = __constant_cpu_to_le32(
328 NDIS_MAC_OPTION_RECEIVE_SERIALIZED
329 | NDIS_MAC_OPTION_FULL_DUPLEX);
330 retval = 0;
331 break;
332
333 /* statistics OIDs (table 4-2) */
334
335 /* mandatory */
336 case OID_GEN_XMIT_OK:
337#if defined(DEBUG) && defined(DEBUG_VERBOSE)
338 debug("%s: OID_GEN_XMIT_OK\n", __func__);
339#endif
340 if (params->stats) {
341 *outbuf = cpu_to_le32(
342 params->stats->tx_packets -
343 params->stats->tx_errors -
344 params->stats->tx_dropped);
345 retval = 0;
346 }
347 break;
348
349 /* mandatory */
350 case OID_GEN_RCV_OK:
351#if defined(DEBUG) && defined(DEBUG_VERBOSE)
352 debug("%s: OID_GEN_RCV_OK\n", __func__);
353#endif
354 if (params->stats) {
355 *outbuf = cpu_to_le32(
356 params->stats->rx_packets -
357 params->stats->rx_errors -
358 params->stats->rx_dropped);
359 retval = 0;
360 }
361 break;
362
363 /* mandatory */
364 case OID_GEN_XMIT_ERROR:
365#if defined(DEBUG) && defined(DEBUG_VERBOSE)
366 debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
367#endif
368 if (params->stats) {
369 *outbuf = cpu_to_le32(params->stats->tx_errors);
370 retval = 0;
371 }
372 break;
373
374 /* mandatory */
375 case OID_GEN_RCV_ERROR:
376#if defined(DEBUG) && defined(DEBUG_VERBOSE)
377 debug("%s: OID_GEN_RCV_ERROR\n", __func__);
378#endif
379 if (params->stats) {
380 *outbuf = cpu_to_le32(params->stats->rx_errors);
381 retval = 0;
382 }
383 break;
384
385 /* mandatory */
386 case OID_GEN_RCV_NO_BUFFER:
387 debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
388 if (params->stats) {
389 *outbuf = cpu_to_le32(params->stats->rx_dropped);
390 retval = 0;
391 }
392 break;
393
394#ifdef RNDIS_OPTIONAL_STATS
395 case OID_GEN_DIRECTED_BYTES_XMIT:
396 debug("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
397 /*
398 * Aunt Tilly's size of shoes
399 * minus antarctica count of penguins
400 * divided by weight of Alpha Centauri
401 */
402 if (params->stats) {
403 *outbuf = cpu_to_le32(
404 (params->stats->tx_packets -
405 params->stats->tx_errors -
406 params->stats->tx_dropped)
407 * 123);
408 retval = 0;
409 }
410 break;
411
412 case OID_GEN_DIRECTED_FRAMES_XMIT:
413 debug("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
414 /* dito */
415 if (params->stats) {
416 *outbuf = cpu_to_le32(
417 (params->stats->tx_packets -
418 params->stats->tx_errors -
419 params->stats->tx_dropped)
420 / 123);
421 retval = 0;
422 }
423 break;
424
425 case OID_GEN_MULTICAST_BYTES_XMIT:
426 debug("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
427 if (params->stats) {
428 *outbuf = cpu_to_le32(params->stats->multicast * 1234);
429 retval = 0;
430 }
431 break;
432
433 case OID_GEN_MULTICAST_FRAMES_XMIT:
434 debug("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
435 if (params->stats) {
436 *outbuf = cpu_to_le32(params->stats->multicast);
437 retval = 0;
438 }
439 break;
440
441 case OID_GEN_BROADCAST_BYTES_XMIT:
442 debug("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
443 if (params->stats) {
444 *outbuf = cpu_to_le32(params->stats->tx_packets/42*255);
445 retval = 0;
446 }
447 break;
448
449 case OID_GEN_BROADCAST_FRAMES_XMIT:
450 debug("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
451 if (params->stats) {
452 *outbuf = cpu_to_le32(params->stats->tx_packets / 42);
453 retval = 0;
454 }
455 break;
456
457 case OID_GEN_DIRECTED_BYTES_RCV:
458 debug("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
459 *outbuf = __constant_cpu_to_le32(0);
460 retval = 0;
461 break;
462
463 case OID_GEN_DIRECTED_FRAMES_RCV:
464 debug("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
465 *outbuf = __constant_cpu_to_le32(0);
466 retval = 0;
467 break;
468
469 case OID_GEN_MULTICAST_BYTES_RCV:
470 debug("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
471 if (params->stats) {
472 *outbuf = cpu_to_le32(params->stats->multicast * 1111);
473 retval = 0;
474 }
475 break;
476
477 case OID_GEN_MULTICAST_FRAMES_RCV:
478 debug("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
479 if (params->stats) {
480 *outbuf = cpu_to_le32(params->stats->multicast);
481 retval = 0;
482 }
483 break;
484
485 case OID_GEN_BROADCAST_BYTES_RCV:
486 debug("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
487 if (params->stats) {
488 *outbuf = cpu_to_le32(params->stats->rx_packets/42*255);
489 retval = 0;
490 }
491 break;
492
493 case OID_GEN_BROADCAST_FRAMES_RCV:
494 debug("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
495 if (params->stats) {
496 *outbuf = cpu_to_le32(params->stats->rx_packets / 42);
497 retval = 0;
498 }
499 break;
500
501 case OID_GEN_RCV_CRC_ERROR:
502 debug("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
503 if (params->stats) {
504 *outbuf = cpu_to_le32(params->stats->rx_crc_errors);
505 retval = 0;
506 }
507 break;
508
509 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
510 debug("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
511 *outbuf = __constant_cpu_to_le32(0);
512 retval = 0;
513 break;
514#endif /* RNDIS_OPTIONAL_STATS */
515
516 /* ieee802.3 OIDs (table 4-3) */
517
518 /* mandatory */
519 case OID_802_3_PERMANENT_ADDRESS:
520 debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
521 if (params->dev) {
522 length = ETH_ALEN;
523 memcpy(outbuf, params->host_mac, length);
524 retval = 0;
525 }
526 break;
527
528 /* mandatory */
529 case OID_802_3_CURRENT_ADDRESS:
530 debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
531 if (params->dev) {
532 length = ETH_ALEN;
533 memcpy(outbuf, params->host_mac, length);
534 retval = 0;
535 }
536 break;
537
538 /* mandatory */
539 case OID_802_3_MULTICAST_LIST:
540 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
541 /* Multicast base address only */
542 *outbuf = __constant_cpu_to_le32(0xE0000000);
543 retval = 0;
544 break;
545
546 /* mandatory */
547 case OID_802_3_MAXIMUM_LIST_SIZE:
548 debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
549 /* Multicast base address only */
550 *outbuf = __constant_cpu_to_le32(1);
551 retval = 0;
552 break;
553
554 case OID_802_3_MAC_OPTIONS:
555 debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
556 break;
557
558 /* ieee802.3 statistics OIDs (table 4-4) */
559
560 /* mandatory */
561 case OID_802_3_RCV_ERROR_ALIGNMENT:
562 debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
563 if (params->stats) {
564 *outbuf = cpu_to_le32(params->stats->rx_frame_errors);
565 retval = 0;
566 }
567 break;
568
569 /* mandatory */
570 case OID_802_3_XMIT_ONE_COLLISION:
571 debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
572 *outbuf = __constant_cpu_to_le32(0);
573 retval = 0;
574 break;
575
576 /* mandatory */
577 case OID_802_3_XMIT_MORE_COLLISIONS:
578 debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
579 *outbuf = __constant_cpu_to_le32(0);
580 retval = 0;
581 break;
582
583#ifdef RNDIS_OPTIONAL_STATS
584 case OID_802_3_XMIT_DEFERRED:
585 debug("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
586 /* TODO */
587 break;
588
589 case OID_802_3_XMIT_MAX_COLLISIONS:
590 debug("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
591 /* TODO */
592 break;
593
594 case OID_802_3_RCV_OVERRUN:
595 debug("%s: OID_802_3_RCV_OVERRUN\n", __func__);
596 /* TODO */
597 break;
598
599 case OID_802_3_XMIT_UNDERRUN:
600 debug("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
601 /* TODO */
602 break;
603
604 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
605 debug("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
606 /* TODO */
607 break;
608
609 case OID_802_3_XMIT_TIMES_CRS_LOST:
610 debug("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
611 /* TODO */
612 break;
613
614 case OID_802_3_XMIT_LATE_COLLISIONS:
615 debug("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
616 /* TODO */
617 break;
618#endif /* RNDIS_OPTIONAL_STATS */
619
620#ifdef RNDIS_PM
621 /* power management OIDs (table 4-5) */
622 case OID_PNP_CAPABILITIES:
623 debug("%s: OID_PNP_CAPABILITIES\n", __func__);
624
625 /* for now, no wakeup capabilities */
626 length = sizeof(struct NDIS_PNP_CAPABILITIES);
627 memset(outbuf, 0, length);
628 retval = 0;
629 break;
630 case OID_PNP_QUERY_POWER:
631 debug("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
632 get_unaligned_le32(buf) - 1);
633 /*
634 * only suspend is a real power state, and
635 * it can't be entered by OID_PNP_SET_POWER...
636 */
637 length = 0;
638 retval = 0;
639 break;
640#endif
641
642 default:
643 debug("%s: query unknown OID 0x%08X\n", __func__, OID);
644 }
645 if (retval < 0)
646 length = 0;
647
648 resp->InformationBufferLength = cpu_to_le32(length);
649 r->length = length + sizeof *resp;
650 resp->MessageLength = cpu_to_le32(r->length);
651 return retval;
652}
653
654static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
655 rndis_resp_t *r)
656{
657 rndis_set_cmplt_type *resp;
658 int retval = -ENOTSUPP;
659 struct rndis_params *params;
660#if (defined(DEBUG) && defined(DEBUG_VERBOSE)) || defined(RNDIS_PM)
661 int i;
662#endif
663
664 if (!r)
665 return -ENOMEM;
666 resp = (rndis_set_cmplt_type *) r->buf;
667 if (!resp)
668 return -ENOMEM;
669
670#if defined(DEBUG) && defined(DEBUG_VERBOSE)
671 if (buf_len) {
672 debug("set OID %08x value, len %d:\n", OID, buf_len);
673 for (i = 0; i < buf_len; i += 16) {
674 debug("%03d: %08x %08x %08x %08x\n", i,
675 get_unaligned_le32(&buf[i]),
676 get_unaligned_le32(&buf[i + 4]),
677 get_unaligned_le32(&buf[i + 8]),
678 get_unaligned_le32(&buf[i + 12]));
679 }
680 }
681#endif
682
683 params = &rndis_per_dev_params[configNr];
684 switch (OID) {
685 case OID_GEN_CURRENT_PACKET_FILTER:
686
687 /*
688 * these NDIS_PACKET_TYPE_* bitflags are shared with
689 * cdc_filter; it's not RNDIS-specific
690 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
691 * PROMISCUOUS, DIRECTED,
692 * MULTICAST, ALL_MULTICAST, BROADCAST
693 */
694 *params->filter = (u16) get_unaligned_le32(buf);
695 debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
696 __func__, *params->filter);
697
698 /*
699 * this call has a significant side effect: it's
700 * what makes the packet flow start and stop, like
701 * activating the CDC Ethernet altsetting.
702 */
703#ifdef RNDIS_PM
704update_linkstate:
705#endif
706 retval = 0;
707 if (*params->filter)
708 params->state = RNDIS_DATA_INITIALIZED;
709 else
710 params->state = RNDIS_INITIALIZED;
711 break;
712
713 case OID_802_3_MULTICAST_LIST:
714 /* I think we can ignore this */
715 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
716 retval = 0;
717 break;
718#if 0
719 case OID_GEN_RNDIS_CONFIG_PARAMETER:
720 {
721 struct rndis_config_parameter *param;
722 param = (struct rndis_config_parameter *) buf;
723 debug("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
724 __func__,
725 min(cpu_to_le32(param->ParameterNameLength), 80),
726 buf + param->ParameterNameOffset);
727 retval = 0;
728 }
729 break;
730#endif
731
732#ifdef RNDIS_PM
733 case OID_PNP_SET_POWER:
734 /*
735 * The only real power state is USB suspend, and RNDIS requests
736 * can't enter it; this one isn't really about power. After
737 * resuming, Windows forces a reset, and then SET_POWER D0.
738 * FIXME ... then things go batty; Windows wedges itself.
739 */
740 i = get_unaligned_le32(buf);
741 debug("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
742 switch (i) {
743 case NdisDeviceStateD0:
744 *params->filter = params->saved_filter;
745 goto update_linkstate;
746 case NdisDeviceStateD3:
747 case NdisDeviceStateD2:
748 case NdisDeviceStateD1:
749 params->saved_filter = *params->filter;
750 retval = 0;
751 break;
752 }
753 break;
754
755#ifdef RNDIS_WAKEUP
756 /*
757 * no wakeup support advertised, so wakeup OIDs always fail:
758 * - OID_PNP_ENABLE_WAKE_UP
759 * - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
760 */
761#endif
762
763#endif /* RNDIS_PM */
764
765 default:
766 debug("%s: set unknown OID 0x%08X, size %d\n",
767 __func__, OID, buf_len);
768 }
769
770 return retval;
771}
772
773/*
774 * Response Functions
775 */
776
777static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
778{
779 rndis_init_cmplt_type *resp;
780 rndis_resp_t *r;
781
782 if (!rndis_per_dev_params[configNr].dev)
783 return -ENOTSUPP;
784
785 r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
786 if (!r)
787 return -ENOMEM;
788 resp = (rndis_init_cmplt_type *) r->buf;
789
790 resp->MessageType = __constant_cpu_to_le32(
791 REMOTE_NDIS_INITIALIZE_CMPLT);
792 resp->MessageLength = __constant_cpu_to_le32(52);
793 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
794 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
795 resp->MajorVersion = __constant_cpu_to_le32(RNDIS_MAJOR_VERSION);
796 resp->MinorVersion = __constant_cpu_to_le32(RNDIS_MINOR_VERSION);
797 resp->DeviceFlags = __constant_cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
798 resp->Medium = __constant_cpu_to_le32(RNDIS_MEDIUM_802_3);
799 resp->MaxPacketsPerTransfer = __constant_cpu_to_le32(1);
800 resp->MaxTransferSize = cpu_to_le32(
801 rndis_per_dev_params[configNr].mtu
802 + ETHER_HDR_SIZE
803 + sizeof(struct rndis_packet_msg_type)
804 + 22);
805 resp->PacketAlignmentFactor = __constant_cpu_to_le32(0);
806 resp->AFListOffset = __constant_cpu_to_le32(0);
807 resp->AFListSize = __constant_cpu_to_le32(0);
808
809 if (rndis_per_dev_params[configNr].ack)
810 rndis_per_dev_params[configNr].ack(
811 rndis_per_dev_params[configNr].dev);
812
813 return 0;
814}
815
816static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
817{
818 rndis_query_cmplt_type *resp;
819 rndis_resp_t *r;
820
821 debug("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID));
822 if (!rndis_per_dev_params[configNr].dev)
823 return -ENOTSUPP;
824
825 /*
826 * we need more memory:
827 * gen_ndis_query_resp expects enough space for
828 * rndis_query_cmplt_type followed by data.
829 * oid_supported_list is the largest data reply
830 */
831 r = rndis_add_response(configNr,
832 sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
833 if (!r)
834 return -ENOMEM;
835 resp = (rndis_query_cmplt_type *) r->buf;
836
837 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
838 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
839
840 if (gen_ndis_query_resp(configNr, get_unaligned_le32(&buf->OID),
841 get_unaligned_le32(&buf->InformationBufferOffset)
842 + 8 + (u8 *) buf,
843 get_unaligned_le32(&buf->InformationBufferLength),
844 r)) {
845 /* OID not supported */
846 resp->Status = __constant_cpu_to_le32(
847 RNDIS_STATUS_NOT_SUPPORTED);
848 resp->MessageLength = __constant_cpu_to_le32(sizeof *resp);
849 resp->InformationBufferLength = __constant_cpu_to_le32(0);
850 resp->InformationBufferOffset = __constant_cpu_to_le32(0);
851 } else
852 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
853
854 if (rndis_per_dev_params[configNr].ack)
855 rndis_per_dev_params[configNr].ack(
856 rndis_per_dev_params[configNr].dev);
857 return 0;
858}
859
860static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
861{
862 u32 BufLength, BufOffset;
863 rndis_set_cmplt_type *resp;
864 rndis_resp_t *r;
865
866 r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
867 if (!r)
868 return -ENOMEM;
869 resp = (rndis_set_cmplt_type *) r->buf;
870
871 BufLength = get_unaligned_le32(&buf->InformationBufferLength);
872 BufOffset = get_unaligned_le32(&buf->InformationBufferOffset);
873
874#ifdef VERBOSE
875 debug("%s: Length: %d\n", __func__, BufLength);
876 debug("%s: Offset: %d\n", __func__, BufOffset);
877 debug("%s: InfoBuffer: ", __func__);
878
879 for (i = 0; i < BufLength; i++)
880 debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
881
882 debug("\n");
883#endif
884
885 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
886 resp->MessageLength = __constant_cpu_to_le32(16);
887 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
888 if (gen_ndis_set_resp(configNr, get_unaligned_le32(&buf->OID),
889 ((u8 *) buf) + 8 + BufOffset, BufLength, r))
890 resp->Status = __constant_cpu_to_le32(
891 RNDIS_STATUS_NOT_SUPPORTED);
892 else
893 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
894
895 if (rndis_per_dev_params[configNr].ack)
896 rndis_per_dev_params[configNr].ack(
897 rndis_per_dev_params[configNr].dev);
898
899 return 0;
900}
901
902static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
903{
904 rndis_reset_cmplt_type *resp;
905 rndis_resp_t *r;
906
907 r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
908 if (!r)
909 return -ENOMEM;
910 resp = (rndis_reset_cmplt_type *) r->buf;
911
912 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
913 resp->MessageLength = __constant_cpu_to_le32(16);
914 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
915 /* resent information */
916 resp->AddressingReset = __constant_cpu_to_le32(1);
917
918 if (rndis_per_dev_params[configNr].ack)
919 rndis_per_dev_params[configNr].ack(
920 rndis_per_dev_params[configNr].dev);
921
922 return 0;
923}
924
925static int rndis_keepalive_response(int configNr,
926 rndis_keepalive_msg_type *buf)
927{
928 rndis_keepalive_cmplt_type *resp;
929 rndis_resp_t *r;
930
931 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
932
933 r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
934 if (!r)
935 return -ENOMEM;
936 resp = (rndis_keepalive_cmplt_type *) r->buf;
937
938 resp->MessageType = __constant_cpu_to_le32(
939 REMOTE_NDIS_KEEPALIVE_CMPLT);
940 resp->MessageLength = __constant_cpu_to_le32(16);
941 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
942 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
943
944 if (rndis_per_dev_params[configNr].ack)
945 rndis_per_dev_params[configNr].ack(
946 rndis_per_dev_params[configNr].dev);
947
948 return 0;
949}
950
951
952/*
953 * Device to Host Comunication
954 */
955static int rndis_indicate_status_msg(int configNr, u32 status)
956{
957 rndis_indicate_status_msg_type *resp;
958 rndis_resp_t *r;
959
960 if (rndis_per_dev_params[configNr].state == RNDIS_UNINITIALIZED)
961 return -ENOTSUPP;
962
963 r = rndis_add_response(configNr,
964 sizeof(rndis_indicate_status_msg_type));
965 if (!r)
966 return -ENOMEM;
967 resp = (rndis_indicate_status_msg_type *) r->buf;
968
969 resp->MessageType = __constant_cpu_to_le32(
970 REMOTE_NDIS_INDICATE_STATUS_MSG);
971 resp->MessageLength = __constant_cpu_to_le32(20);
972 resp->Status = cpu_to_le32(status);
973 resp->StatusBufferLength = __constant_cpu_to_le32(0);
974 resp->StatusBufferOffset = __constant_cpu_to_le32(0);
975
976 if (rndis_per_dev_params[configNr].ack)
977 rndis_per_dev_params[configNr].ack(
978 rndis_per_dev_params[configNr].dev);
979 return 0;
980}
981
982int rndis_signal_connect(int configNr)
983{
984 rndis_per_dev_params[configNr].media_state
985 = NDIS_MEDIA_STATE_CONNECTED;
986 return rndis_indicate_status_msg(configNr,
987 RNDIS_STATUS_MEDIA_CONNECT);
988}
989
990int rndis_signal_disconnect(int configNr)
991{
992 rndis_per_dev_params[configNr].media_state
993 = NDIS_MEDIA_STATE_DISCONNECTED;
994
Vitaly Kuzmicheve4ae6662011-02-11 18:18:35 +0300995#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
996 return rndis_indicate_status_msg(configNr,
997 RNDIS_STATUS_MEDIA_DISCONNECT);
998#else
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +0300999 return 0;
Vitaly Kuzmicheve4ae6662011-02-11 18:18:35 +03001000#endif
Vitaly Kuzmichev7612a432011-02-11 18:18:34 +03001001}
1002
1003void rndis_uninit(int configNr)
1004{
1005 u8 *buf;
1006 u32 length;
1007
1008 if (configNr >= RNDIS_MAX_CONFIGS)
1009 return;
1010 rndis_per_dev_params[configNr].used = 0;
1011 rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
1012
1013 /* drain the response queue */
1014 while ((buf = rndis_get_next_response(configNr, &length)))
1015 rndis_free_response(configNr, buf);
1016}
1017
1018void rndis_set_host_mac(int configNr, const u8 *addr)
1019{
1020 rndis_per_dev_params[configNr].host_mac = addr;
1021}
1022
1023enum rndis_state rndis_get_state(int configNr)
1024{
1025 if (configNr >= RNDIS_MAX_CONFIGS || configNr < 0)
1026 return -ENOTSUPP;
1027 return rndis_per_dev_params[configNr].state;
1028}
1029
1030/*
1031 * Message Parser
1032 */
1033int rndis_msg_parser(u8 configNr, u8 *buf)
1034{
1035 u32 MsgType, MsgLength;
1036 __le32 *tmp;
1037 struct rndis_params *params;
1038
1039 debug("%s: configNr = %d, %p\n", __func__, configNr, buf);
1040
1041 if (!buf)
1042 return -ENOMEM;
1043
1044 tmp = (__le32 *) buf;
1045 MsgType = get_unaligned_le32(tmp++);
1046 MsgLength = get_unaligned_le32(tmp++);
1047
1048 if (configNr >= RNDIS_MAX_CONFIGS)
1049 return -ENOTSUPP;
1050 params = &rndis_per_dev_params[configNr];
1051
1052 /*
1053 * NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
1054 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
1055 * and normal HC level polling to see if there's any IN traffic.
1056 */
1057
1058 /* For USB: responses may take up to 10 seconds */
1059 switch (MsgType) {
1060 case REMOTE_NDIS_INITIALIZE_MSG:
1061 debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__);
1062 params->state = RNDIS_INITIALIZED;
1063 return rndis_init_response(configNr,
1064 (rndis_init_msg_type *) buf);
1065
1066 case REMOTE_NDIS_HALT_MSG:
1067 debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__);
1068 params->state = RNDIS_UNINITIALIZED;
1069 return 0;
1070
1071 case REMOTE_NDIS_QUERY_MSG:
1072 return rndis_query_response(configNr,
1073 (rndis_query_msg_type *) buf);
1074
1075 case REMOTE_NDIS_SET_MSG:
1076 return rndis_set_response(configNr,
1077 (rndis_set_msg_type *) buf);
1078
1079 case REMOTE_NDIS_RESET_MSG:
1080 debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__);
1081 return rndis_reset_response(configNr,
1082 (rndis_reset_msg_type *) buf);
1083
1084 case REMOTE_NDIS_KEEPALIVE_MSG:
1085 /* For USB: host does this every 5 seconds */
1086#if defined(DEBUG) && defined(DEBUG_VERBOSE)
1087 debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__);
1088#endif
1089 return rndis_keepalive_response(configNr,
1090 (rndis_keepalive_msg_type *) buf);
1091
1092 default:
1093 /*
1094 * At least Windows XP emits some undefined RNDIS messages.
1095 * In one case those messages seemed to relate to the host
1096 * suspending itself.
1097 */
1098 debug("%s: unknown RNDIS message 0x%08X len %d\n",
1099 __func__ , MsgType, MsgLength);
1100 {
1101 unsigned i;
1102 for (i = 0; i < MsgLength; i += 16) {
1103 debug("%03d: "
1104 " %02x %02x %02x %02x"
1105 " %02x %02x %02x %02x"
1106 " %02x %02x %02x %02x"
1107 " %02x %02x %02x %02x"
1108 "\n",
1109 i,
1110 buf[i], buf[i+1],
1111 buf[i+2], buf[i+3],
1112 buf[i+4], buf[i+5],
1113 buf[i+6], buf[i+7],
1114 buf[i+8], buf[i+9],
1115 buf[i+10], buf[i+11],
1116 buf[i+12], buf[i+13],
1117 buf[i+14], buf[i+15]);
1118 }
1119 }
1120 break;
1121 }
1122
1123 return -ENOTSUPP;
1124}
1125
1126int rndis_register(int (*rndis_control_ack)(struct eth_device *))
1127{
1128 u8 i;
1129
1130 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1131 if (!rndis_per_dev_params[i].used) {
1132 rndis_per_dev_params[i].used = 1;
1133 rndis_per_dev_params[i].ack = rndis_control_ack;
1134 debug("%s: configNr = %d\n", __func__, i);
1135 return i;
1136 }
1137 }
1138 debug("%s failed\n", __func__);
1139
1140 return -1;
1141}
1142
1143void rndis_deregister(int configNr)
1144{
1145 debug("%s: configNr = %d\n", __func__, configNr);
1146
1147 if (configNr >= RNDIS_MAX_CONFIGS)
1148 return;
1149 rndis_per_dev_params[configNr].used = 0;
1150
1151 return;
1152}
1153
1154int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu,
1155 struct net_device_stats *stats, u16 *cdc_filter)
1156{
1157 debug("%s: configNr = %d\n", __func__, configNr);
1158 if (!dev || !stats)
1159 return -1;
1160 if (configNr >= RNDIS_MAX_CONFIGS)
1161 return -1;
1162
1163 rndis_per_dev_params[configNr].dev = dev;
1164 rndis_per_dev_params[configNr].stats = stats;
1165 rndis_per_dev_params[configNr].mtu = mtu;
1166 rndis_per_dev_params[configNr].filter = cdc_filter;
1167
1168 return 0;
1169}
1170
1171int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
1172{
1173 debug("%s: configNr = %d\n", __func__, configNr);
1174 if (!vendorDescr)
1175 return -1;
1176 if (configNr >= RNDIS_MAX_CONFIGS)
1177 return -1;
1178
1179 rndis_per_dev_params[configNr].vendorID = vendorID;
1180 rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
1181
1182 return 0;
1183}
1184
1185int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
1186{
1187 debug("%s: configNr = %d, %u %u\n", __func__, configNr, medium, speed);
1188 if (configNr >= RNDIS_MAX_CONFIGS)
1189 return -1;
1190
1191 rndis_per_dev_params[configNr].medium = medium;
1192 rndis_per_dev_params[configNr].speed = speed;
1193
1194 return 0;
1195}
1196
1197void rndis_add_hdr(void *buf, int length)
1198{
1199 struct rndis_packet_msg_type *header;
1200
1201 header = buf;
1202 memset(header, 0, sizeof *header);
1203 header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
1204 header->MessageLength = cpu_to_le32(length + sizeof *header);
1205 header->DataOffset = __constant_cpu_to_le32(36);
1206 header->DataLength = cpu_to_le32(length);
1207}
1208
1209void rndis_free_response(int configNr, u8 *buf)
1210{
1211 rndis_resp_t *r;
1212 struct list_head *act, *tmp;
1213
1214 list_for_each_safe(act, tmp,
1215 &(rndis_per_dev_params[configNr].resp_queue))
1216 {
1217 r = list_entry(act, rndis_resp_t, list);
1218 if (r && r->buf == buf) {
1219 list_del(&r->list);
1220 free(r);
1221 }
1222 }
1223}
1224
1225u8 *rndis_get_next_response(int configNr, u32 *length)
1226{
1227 rndis_resp_t *r;
1228 struct list_head *act, *tmp;
1229
1230 if (!length)
1231 return NULL;
1232
1233 list_for_each_safe(act, tmp,
1234 &(rndis_per_dev_params[configNr].resp_queue))
1235 {
1236 r = list_entry(act, rndis_resp_t, list);
1237 if (!r->send) {
1238 r->send = 1;
1239 *length = r->length;
1240 return r->buf;
1241 }
1242 }
1243
1244 return NULL;
1245}
1246
1247static rndis_resp_t *rndis_add_response(int configNr, u32 length)
1248{
1249 rndis_resp_t *r;
1250
1251 /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
1252 r = malloc(sizeof(rndis_resp_t) + length);
1253 if (!r)
1254 return NULL;
1255
1256 r->buf = (u8 *) (r + 1);
1257 r->length = length;
1258 r->send = 0;
1259
1260 list_add_tail(&r->list,
1261 &(rndis_per_dev_params[configNr].resp_queue));
1262 return r;
1263}
1264
1265int rndis_rm_hdr(void *buf, int length)
1266{
1267 /* tmp points to a struct rndis_packet_msg_type */
1268 __le32 *tmp = buf;
1269 int offs, len;
1270
1271 /* MessageType, MessageLength */
1272 if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
1273 != get_unaligned(tmp++))
1274 return -EINVAL;
1275 tmp++;
1276
1277 /* DataOffset, DataLength */
1278 offs = get_unaligned_le32(tmp++) + 8 /* offset of DataOffset */;
1279 if (offs != sizeof(struct rndis_packet_msg_type))
1280 debug("%s: unexpected DataOffset: %d\n", __func__, offs);
1281 if (offs >= length)
1282 return -EOVERFLOW;
1283
1284 len = get_unaligned_le32(tmp++);
1285 if (len + sizeof(struct rndis_packet_msg_type) != length)
1286 debug("%s: unexpected DataLength: %d, packet length=%d\n",
1287 __func__, len, length);
1288
1289 memmove(buf, buf + offs, len);
1290
1291 return offs;
1292}
1293
1294int rndis_init(void)
1295{
1296 u8 i;
1297
1298 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1299 rndis_per_dev_params[i].confignr = i;
1300 rndis_per_dev_params[i].used = 0;
1301 rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
1302 rndis_per_dev_params[i].media_state
1303 = NDIS_MEDIA_STATE_DISCONNECTED;
1304 INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
1305 }
1306
1307 return 0;
1308}
1309
1310void rndis_exit(void)
1311{
1312 /* Nothing to do */
1313}