aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/rndis.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/gadget/rndis.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/usb/gadget/rndis.c')
-rw-r--r--drivers/usb/gadget/rndis.c1428
1 files changed, 1428 insertions, 0 deletions
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
new file mode 100644
index 000000000000..6c5197850edc
--- /dev/null
+++ b/drivers/usb/gadget/rndis.c
@@ -0,0 +1,1428 @@
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)
60static int rndis_debug = 0;
61
62module_param (rndis_debug, bool, 0);
63MODULE_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
74static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
75
76/* Driver Version */
77static const __le32 rndis_driver_version = __constant_cpu_to_le32 (1);
78
79/* Function Prototypes */
80static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
81static int rndis_query_response (int configNr, rndis_query_msg_type *buf);
82static int rndis_set_response (int configNr, rndis_set_msg_type *buf);
83static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);
84static int rndis_keepalive_response (int configNr,
85 rndis_keepalive_msg_type *buf);
86
87static rndis_resp_t *rndis_add_response (int configNr, u32 length);
88
89
90/* NDIS Functions */
91static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
92{
93 int retval = -ENOTSUPP;
94 u32 length = 0;
95 __le32 *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 = (__le32 *) ((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 receive high level protocols.
125 * BTW:
126 * reddite ergo quae sunt Caesaris Caesari
127 * et quae sunt Dei Deo!
128 */
129 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
158 rndis_per_dev_params [configNr].dev->mtu);
159 retval = 0;
160 } else {
161 *((__le32 *) 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 *((__le32 *) resp + 6) = __constant_cpu_to_le32 (0);
173 else
174 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
315 rndis_per_dev_params [configNr]
316 .stats->tx_errors);
317 retval = 0;
318 } else {
319 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
329 rndis_per_dev_params [configNr]
330 .stats->rx_errors);
331 retval = 0;
332 } else {
333 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
343 rndis_per_dev_params [configNr]
344 .stats->rx_dropped);
345 retval = 0;
346 } else {
347 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
401 rndis_per_dev_params [configNr]
402 .stats->multicast*1234);
403 retval = 0;
404 } else {
405 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
414 rndis_per_dev_params [configNr]
415 .stats->multicast);
416 retval = 0;
417 } else {
418 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
427 rndis_per_dev_params [configNr]
428 .stats->tx_packets/42*255);
429 retval = 0;
430 } else {
431 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
440 rndis_per_dev_params [configNr]
441 .stats->tx_packets/42);
442 retval = 0;
443 } else {
444 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
465 rndis_per_dev_params [configNr]
466 .stats->multicast * 1111);
467 retval = 0;
468 } else {
469 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
478 rndis_per_dev_params [configNr]
479 .stats->multicast);
480 retval = 0;
481 } else {
482 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
491 rndis_per_dev_params [configNr]
492 .stats->rx_packets/42*255);
493 retval = 0;
494 } else {
495 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
504 rndis_per_dev_params [configNr]
505 .stats->rx_packets/42);
506 retval = 0;
507 } else {
508 *((__le32 *) 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 *((__le32 *) resp + 6) = cpu_to_le32 (
517 rndis_per_dev_params [configNr]
518 .stats->rx_crc_errors);
519 retval = 0;
520 } else {
521 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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 *((__le32 *) 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
694static 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 == USB_CDC_PACKET_TYPE_x for x in:
734 * PROMISCUOUS, DIRECTED,
735 * MULTICAST, ALL_MULTICAST, BROADCAST
736 */
737 params->filter = le32_to_cpup((__le32 *)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
805static 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
846static 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 * oid_supported_list is the largest answer
857 */
858 r = rndis_add_response (configNr, sizeof (oid_supported_list));
859
860 if (!r) return -ENOMEM;
861 resp = (rndis_query_cmplt_type *) r->buf;
862
863 if (!resp) return -ENOMEM;
864
865 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
866 resp->MessageLength = __constant_cpu_to_le32 (24);
867 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
868
869 if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), r)) {
870 /* OID not supported */
871 resp->Status = __constant_cpu_to_le32 (
872 RNDIS_STATUS_NOT_SUPPORTED);
873 resp->InformationBufferLength = __constant_cpu_to_le32 (0);
874 resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
875 } else
876 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
877
878 if (rndis_per_dev_params [configNr].ack)
879 rndis_per_dev_params [configNr].ack (
880 rndis_per_dev_params [configNr].dev);
881 return 0;
882}
883
884static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
885{
886 u32 BufLength, BufOffset;
887 rndis_set_cmplt_type *resp;
888 rndis_resp_t *r;
889
890 r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
891
892 if (!r) return -ENOMEM;
893 resp = (rndis_set_cmplt_type *) r->buf;
894 if (!resp) return -ENOMEM;
895
896 BufLength = le32_to_cpu (buf->InformationBufferLength);
897 BufOffset = le32_to_cpu (buf->InformationBufferOffset);
898
899#ifdef VERBOSE
900 DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
901 DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
902 DEBUG("%s: InfoBuffer: ", __FUNCTION__);
903
904 for (i = 0; i < BufLength; i++) {
905 DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
906 }
907
908 DEBUG ("\n");
909#endif
910
911 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
912 resp->MessageLength = __constant_cpu_to_le32 (16);
913 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
914 if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
915 ((u8 *) buf) + 8 + BufOffset, BufLength, r))
916 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
917 else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
918
919 if (rndis_per_dev_params [configNr].ack)
920 rndis_per_dev_params [configNr].ack (
921 rndis_per_dev_params [configNr].dev);
922
923 return 0;
924}
925
926static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
927{
928 rndis_reset_cmplt_type *resp;
929 rndis_resp_t *r;
930
931 r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
932
933 if (!r) return -ENOMEM;
934 resp = (rndis_reset_cmplt_type *) r->buf;
935 if (!resp) return -ENOMEM;
936
937 resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
938 resp->MessageLength = __constant_cpu_to_le32 (16);
939 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
940 /* resent information */
941 resp->AddressingReset = __constant_cpu_to_le32 (1);
942
943 if (rndis_per_dev_params [configNr].ack)
944 rndis_per_dev_params [configNr].ack (
945 rndis_per_dev_params [configNr].dev);
946
947 return 0;
948}
949
950static int rndis_keepalive_response (int configNr,
951 rndis_keepalive_msg_type *buf)
952{
953 rndis_keepalive_cmplt_type *resp;
954 rndis_resp_t *r;
955
956 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
957
958 r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
959 resp = (rndis_keepalive_cmplt_type *) r->buf;
960 if (!resp) return -ENOMEM;
961
962 resp->MessageType = __constant_cpu_to_le32 (
963 REMOTE_NDIS_KEEPALIVE_CMPLT);
964 resp->MessageLength = __constant_cpu_to_le32 (16);
965 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
966 resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
967
968 if (rndis_per_dev_params [configNr].ack)
969 rndis_per_dev_params [configNr].ack (
970 rndis_per_dev_params [configNr].dev);
971
972 return 0;
973}
974
975
976/*
977 * Device to Host Comunication
978 */
979static int rndis_indicate_status_msg (int configNr, u32 status)
980{
981 rndis_indicate_status_msg_type *resp;
982 rndis_resp_t *r;
983
984 if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
985 return -ENOTSUPP;
986
987 r = rndis_add_response (configNr,
988 sizeof (rndis_indicate_status_msg_type));
989 if (!r) return -ENOMEM;
990
991 resp = (rndis_indicate_status_msg_type *) r->buf;
992 if (!resp) return -ENOMEM;
993
994 resp->MessageType = __constant_cpu_to_le32 (
995 REMOTE_NDIS_INDICATE_STATUS_MSG);
996 resp->MessageLength = __constant_cpu_to_le32 (20);
997 resp->Status = cpu_to_le32 (status);
998 resp->StatusBufferLength = __constant_cpu_to_le32 (0);
999 resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
1000
1001 if (rndis_per_dev_params [configNr].ack)
1002 rndis_per_dev_params [configNr].ack (
1003 rndis_per_dev_params [configNr].dev);
1004 return 0;
1005}
1006
1007int rndis_signal_connect (int configNr)
1008{
1009 rndis_per_dev_params [configNr].media_state
1010 = NDIS_MEDIA_STATE_CONNECTED;
1011 return rndis_indicate_status_msg (configNr,
1012 RNDIS_STATUS_MEDIA_CONNECT);
1013}
1014
1015int rndis_signal_disconnect (int configNr)
1016{
1017 rndis_per_dev_params [configNr].media_state
1018 = NDIS_MEDIA_STATE_DISCONNECTED;
1019 return rndis_indicate_status_msg (configNr,
1020 RNDIS_STATUS_MEDIA_DISCONNECT);
1021}
1022
1023void rndis_set_host_mac (int configNr, const u8 *addr)
1024{
1025 rndis_per_dev_params [configNr].host_mac = addr;
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 if (!buf)
1038 return -ENOMEM;
1039
1040 tmp = (__le32 *) buf;
1041 MsgType = le32_to_cpup(tmp++);
1042 MsgLength = le32_to_cpup(tmp++);
1043
1044 if (configNr >= RNDIS_MAX_CONFIGS)
1045 return -ENOTSUPP;
1046 params = &rndis_per_dev_params [configNr];
1047
1048 /* For USB: responses may take up to 10 seconds */
1049 switch (MsgType)
1050 {
1051 case REMOTE_NDIS_INITIALIZE_MSG:
1052 DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
1053 __FUNCTION__ );
1054 params->state = RNDIS_INITIALIZED;
1055 return rndis_init_response (configNr,
1056 (rndis_init_msg_type *) buf);
1057
1058 case REMOTE_NDIS_HALT_MSG:
1059 DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
1060 __FUNCTION__ );
1061 params->state = RNDIS_UNINITIALIZED;
1062 if (params->dev) {
1063 netif_carrier_off (params->dev);
1064 netif_stop_queue (params->dev);
1065 }
1066 return 0;
1067
1068 case REMOTE_NDIS_QUERY_MSG:
1069 return rndis_query_response (configNr,
1070 (rndis_query_msg_type *) buf);
1071
1072 case REMOTE_NDIS_SET_MSG:
1073 return rndis_set_response (configNr,
1074 (rndis_set_msg_type *) buf);
1075
1076 case REMOTE_NDIS_RESET_MSG:
1077 DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
1078 __FUNCTION__ );
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#ifdef VERBOSE
1085 DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
1086 __FUNCTION__ );
1087#endif
1088 return rndis_keepalive_response (configNr,
1089 (rndis_keepalive_msg_type *)
1090 buf);
1091
1092 default:
1093 /* At least Windows XP emits some undefined RNDIS messages.
1094 * In one case those messages seemed to relate to the host
1095 * suspending itself.
1096 */
1097 printk (KERN_WARNING
1098 "%s: unknown RNDIS message 0x%08X len %d\n",
1099 __FUNCTION__ , MsgType, MsgLength);
1100 {
1101 unsigned i;
1102 for (i = 0; i < MsgLength; i += 16) {
1103 DEBUG ("%03d: "
1104 " %02x %02x %02x %02x"
1105 " %02x %02x %02x %02x"
1106 " %02x %02x %02x %02x"
1107 " %02x %02x %02x %02x"
1108 "\n",
1109 i,
1110 buf[i], buf [i+1],
1111 buf[i+2], buf[i+3],
1112 buf[i+4], buf [i+5],
1113 buf[i+6], buf[i+7],
1114 buf[i+8], buf [i+9],
1115 buf[i+10], buf[i+11],
1116 buf[i+12], buf [i+13],
1117 buf[i+14], buf[i+15]);
1118 }
1119 }
1120 break;
1121 }
1122
1123 return -ENOTSUPP;
1124}
1125
1126int rndis_register (int (* rndis_control_ack) (struct net_device *))
1127{
1128 u8 i;
1129
1130 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1131 if (!rndis_per_dev_params [i].used) {
1132 rndis_per_dev_params [i].used = 1;
1133 rndis_per_dev_params [i].ack = rndis_control_ack;
1134 DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
1135 return i;
1136 }
1137 }
1138 DEBUG("failed\n");
1139
1140 return -1;
1141}
1142
1143void rndis_deregister (int configNr)
1144{
1145 DEBUG("%s: \n", __FUNCTION__ );
1146
1147 if (configNr >= RNDIS_MAX_CONFIGS) return;
1148 rndis_per_dev_params [configNr].used = 0;
1149
1150 return;
1151}
1152
1153int rndis_set_param_dev (u8 configNr, struct net_device *dev,
1154 struct net_device_stats *stats)
1155{
1156 DEBUG("%s:\n", __FUNCTION__ );
1157 if (!dev || !stats) return -1;
1158 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1159
1160 rndis_per_dev_params [configNr].dev = dev;
1161 rndis_per_dev_params [configNr].stats = stats;
1162
1163 return 0;
1164}
1165
1166int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
1167{
1168 DEBUG("%s:\n", __FUNCTION__ );
1169 if (!vendorDescr) return -1;
1170 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1171
1172 rndis_per_dev_params [configNr].vendorID = vendorID;
1173 rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
1174
1175 return 0;
1176}
1177
1178int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
1179{
1180 DEBUG("%s:\n", __FUNCTION__ );
1181 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1182
1183 rndis_per_dev_params [configNr].medium = medium;
1184 rndis_per_dev_params [configNr].speed = speed;
1185
1186 return 0;
1187}
1188
1189void rndis_add_hdr (struct sk_buff *skb)
1190{
1191 struct rndis_packet_msg_type *header;
1192
1193 if (!skb)
1194 return;
1195 header = (void *) skb_push (skb, sizeof *header);
1196 memset (header, 0, sizeof *header);
1197 header->MessageType = __constant_cpu_to_le32 (1);
1198 header->MessageLength = cpu_to_le32(skb->len);
1199 header->DataOffset = __constant_cpu_to_le32 (36);
1200 header->OOBDataOffset = cpu_to_le32(skb->len - 44);
1201}
1202
1203void rndis_free_response (int configNr, u8 *buf)
1204{
1205 rndis_resp_t *r;
1206 struct list_head *act, *tmp;
1207
1208 list_for_each_safe (act, tmp,
1209 &(rndis_per_dev_params [configNr].resp_queue))
1210 {
1211 r = list_entry (act, rndis_resp_t, list);
1212 if (r && r->buf == buf) {
1213 list_del (&r->list);
1214 kfree (r);
1215 }
1216 }
1217}
1218
1219u8 *rndis_get_next_response (int configNr, u32 *length)
1220{
1221 rndis_resp_t *r;
1222 struct list_head *act, *tmp;
1223
1224 if (!length) return NULL;
1225
1226 list_for_each_safe (act, tmp,
1227 &(rndis_per_dev_params [configNr].resp_queue))
1228 {
1229 r = list_entry (act, rndis_resp_t, list);
1230 if (!r->send) {
1231 r->send = 1;
1232 *length = r->length;
1233 return r->buf;
1234 }
1235 }
1236
1237 return NULL;
1238}
1239
1240static rndis_resp_t *rndis_add_response (int configNr, u32 length)
1241{
1242 rndis_resp_t *r;
1243
1244 r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
1245 if (!r) return NULL;
1246
1247 r->buf = (u8 *) (r + 1);
1248 r->length = length;
1249 r->send = 0;
1250
1251 list_add_tail (&r->list,
1252 &(rndis_per_dev_params [configNr].resp_queue));
1253 return r;
1254}
1255
1256int rndis_rm_hdr (u8 *buf, u32 *length)
1257{
1258 u32 i, messageLen, dataOffset;
1259 __le32 *tmp;
1260
1261 tmp = (__le32 *) buf;
1262
1263 if (!buf || !length) return -1;
1264 if (le32_to_cpup(tmp++) != 1) return -1;
1265
1266 messageLen = le32_to_cpup(tmp++);
1267 dataOffset = le32_to_cpup(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#ifdef CONFIG_USB_GADGET_DEBUG_FILES
1280
1281static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
1282 void *data)
1283{
1284 char *out = page;
1285 int len;
1286 rndis_params *param = (rndis_params *) data;
1287
1288 out += snprintf (out, count,
1289 "Config Nr. %d\n"
1290 "used : %s\n"
1291 "state : %s\n"
1292 "medium : 0x%08X\n"
1293 "speed : %d\n"
1294 "cable : %s\n"
1295 "vendor ID : 0x%08X\n"
1296 "vendor : %s\n",
1297 param->confignr, (param->used) ? "y" : "n",
1298 ({ char *s = "?";
1299 switch (param->state) {
1300 case RNDIS_UNINITIALIZED:
1301 s = "RNDIS_UNINITIALIZED"; break;
1302 case RNDIS_INITIALIZED:
1303 s = "RNDIS_INITIALIZED"; break;
1304 case RNDIS_DATA_INITIALIZED:
1305 s = "RNDIS_DATA_INITIALIZED"; break;
1306 }; s; }),
1307 param->medium,
1308 (param->media_state) ? 0 : param->speed*100,
1309 (param->media_state) ? "disconnected" : "connected",
1310 param->vendorID, param->vendorDescr);
1311
1312 len = out - page;
1313 len -= off;
1314
1315 if (len < count) {
1316 *eof = 1;
1317 if (len <= 0)
1318 return 0;
1319 } else
1320 len = count;
1321
1322 *start = page + off;
1323 return len;
1324}
1325
1326static int rndis_proc_write (struct file *file, const char __user *buffer,
1327 unsigned long count, void *data)
1328{
1329 rndis_params *p = data;
1330 u32 speed = 0;
1331 int i, fl_speed = 0;
1332
1333 for (i = 0; i < count; i++) {
1334 char c;
1335 if (get_user(c, buffer))
1336 return -EFAULT;
1337 switch (c) {
1338 case '0':
1339 case '1':
1340 case '2':
1341 case '3':
1342 case '4':
1343 case '5':
1344 case '6':
1345 case '7':
1346 case '8':
1347 case '9':
1348 fl_speed = 1;
1349 speed = speed*10 + c - '0';
1350 break;
1351 case 'C':
1352 case 'c':
1353 rndis_signal_connect (p->confignr);
1354 break;
1355 case 'D':
1356 case 'd':
1357 rndis_signal_disconnect(p->confignr);
1358 break;
1359 default:
1360 if (fl_speed) p->speed = speed;
1361 else DEBUG ("%c is not valid\n", c);
1362 break;
1363 }
1364
1365 buffer++;
1366 }
1367
1368 return count;
1369}
1370
1371#define NAME_TEMPLATE "driver/rndis-%03d"
1372
1373static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
1374
1375#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
1376
1377
1378int __init rndis_init (void)
1379{
1380 u8 i;
1381
1382 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1383#ifdef CONFIG_USB_GADGET_DEBUG_FILES
1384 char name [20];
1385
1386 sprintf (name, NAME_TEMPLATE, i);
1387 if (!(rndis_connect_state [i]
1388 = create_proc_entry (name, 0660, NULL)))
1389 {
1390 DEBUG ("%s :remove entries", __FUNCTION__);
1391 while (i) {
1392 sprintf (name, NAME_TEMPLATE, --i);
1393 remove_proc_entry (name, NULL);
1394 }
1395 DEBUG ("\n");
1396 return -EIO;
1397 }
1398
1399 rndis_connect_state [i]->nlink = 1;
1400 rndis_connect_state [i]->write_proc = rndis_proc_write;
1401 rndis_connect_state [i]->read_proc = rndis_proc_read;
1402 rndis_connect_state [i]->data = (void *)
1403 (rndis_per_dev_params + i);
1404#endif
1405 rndis_per_dev_params [i].confignr = i;
1406 rndis_per_dev_params [i].used = 0;
1407 rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
1408 rndis_per_dev_params [i].media_state
1409 = NDIS_MEDIA_STATE_DISCONNECTED;
1410 INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
1411 }
1412
1413 return 0;
1414}
1415
1416void rndis_exit (void)
1417{
1418#ifdef CONFIG_USB_GADGET_DEBUG_FILES
1419 u8 i;
1420 char name [20];
1421
1422 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1423 sprintf (name, NAME_TEMPLATE, i);
1424 remove_proc_entry (name, NULL);
1425 }
1426#endif
1427}
1428