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