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