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