1 /*
2 * RNDIS MSG parser
3 *
4 * Authors: Benedikt Spranger, Pengutronix
5 * Robert Schwebel, Pengutronix
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This software was originally developed in conformance with
12 * Microsoft's Remote NDIS Specification License Agreement.
13 *
14 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
15 * Fixed message length bug in init_response
16 *
17 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
18 * Fixed rndis_rm_hdr length bug.
19 *
20 * Copyright (C) 2004 by David Brownell
21 * updates to merge with Linux 2.6, better match RNDIS spec
22 */
23
24 #include <linux/module.h>
25 #include <linux/moduleparam.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/list.h>
29 #include <linux/proc_fs.h>
30 #include <linux/slab.h>
31 #include <linux/seq_file.h>
32 #include <linux/netdevice.h>
33
34 #include <asm/io.h>
35 #include <asm/byteorder.h>
36 #include <asm/unaligned.h>
37
38 #include "u_rndis.h"
39
40 #undef VERBOSE_DEBUG
41
42 #include "rndis.h"
43
44
45 /* The driver for your USB chip needs to support ep0 OUT to work with
46 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
47 *
48 * Windows hosts need an INF file like Documentation/usb/linux.inf
49 * and will be happier if you provide the host_addr module parameter.
50 */
51
52 #if 0
53 static int rndis_debug = 0;
54 module_param (rndis_debug, int, 0);
55 MODULE_PARM_DESC (rndis_debug, "enable debugging");
56 #else
57 #define rndis_debug 0
58 #endif
59
60 #define RNDIS_MAX_CONFIGS 1
61
62 int rndis_ul_max_pkt_per_xfer_rcvd;
63 module_param(rndis_ul_max_pkt_per_xfer_rcvd, int, S_IRUGO);
64 MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer_rcvd,
65 "Max num of REMOTE_NDIS_PACKET_MSGs received in a single transfer");
66
67 int rndis_ul_max_xfer_size_rcvd;
68 module_param(rndis_ul_max_xfer_size_rcvd, int, S_IRUGO);
69 MODULE_PARM_DESC(rndis_ul_max_xfer_size_rcvd,
70 "Max size of bus transfer received");
71
72
73 static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
74
75 /* Driver Version */
76 static const __le32 rndis_driver_version = cpu_to_le32(1);
77
78 /* Function Prototypes */
79 static rndis_resp_t *rndis_add_response(int configNr, u32 length);
80
81
82 /* supported OIDs */
83 static const u32 oid_supported_list[] =
84 {
85 /* the general stuff */
86 RNDIS_OID_GEN_SUPPORTED_LIST,
87 RNDIS_OID_GEN_HARDWARE_STATUS,
88 RNDIS_OID_GEN_MEDIA_SUPPORTED,
89 RNDIS_OID_GEN_MEDIA_IN_USE,
90 RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
91 RNDIS_OID_GEN_LINK_SPEED,
92 RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE,
93 RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE,
94 RNDIS_OID_GEN_VENDOR_ID,
95 RNDIS_OID_GEN_VENDOR_DESCRIPTION,
96 RNDIS_OID_GEN_VENDOR_DRIVER_VERSION,
97 RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
98 RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE,
99 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
100 RNDIS_OID_GEN_PHYSICAL_MEDIUM,
101
102 /* the statistical stuff */
103 RNDIS_OID_GEN_XMIT_OK,
104 RNDIS_OID_GEN_RCV_OK,
105 RNDIS_OID_GEN_XMIT_ERROR,
106 RNDIS_OID_GEN_RCV_ERROR,
107 RNDIS_OID_GEN_RCV_NO_BUFFER,
108 #ifdef RNDIS_OPTIONAL_STATS
109 RNDIS_OID_GEN_DIRECTED_BYTES_XMIT,
110 RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT,
111 RNDIS_OID_GEN_MULTICAST_BYTES_XMIT,
112 RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT,
113 RNDIS_OID_GEN_BROADCAST_BYTES_XMIT,
114 RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT,
115 RNDIS_OID_GEN_DIRECTED_BYTES_RCV,
116 RNDIS_OID_GEN_DIRECTED_FRAMES_RCV,
117 RNDIS_OID_GEN_MULTICAST_BYTES_RCV,
118 RNDIS_OID_GEN_MULTICAST_FRAMES_RCV,
119 RNDIS_OID_GEN_BROADCAST_BYTES_RCV,
120 RNDIS_OID_GEN_BROADCAST_FRAMES_RCV,
121 RNDIS_OID_GEN_RCV_CRC_ERROR,
122 RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH,
123 #endif /* RNDIS_OPTIONAL_STATS */
124
125 /* mandatory 802.3 */
126 /* the general stuff */
127 RNDIS_OID_802_3_PERMANENT_ADDRESS,
128 RNDIS_OID_802_3_CURRENT_ADDRESS,
129 RNDIS_OID_802_3_MULTICAST_LIST,
130 RNDIS_OID_802_3_MAC_OPTIONS,
131 RNDIS_OID_802_3_MAXIMUM_LIST_SIZE,
132
133 /* the statistical stuff */
134 RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT,
135 RNDIS_OID_802_3_XMIT_ONE_COLLISION,
136 RNDIS_OID_802_3_XMIT_MORE_COLLISIONS,
137 #ifdef RNDIS_OPTIONAL_STATS
138 RNDIS_OID_802_3_XMIT_DEFERRED,
139 RNDIS_OID_802_3_XMIT_MAX_COLLISIONS,
140 RNDIS_OID_802_3_RCV_OVERRUN,
141 RNDIS_OID_802_3_XMIT_UNDERRUN,
142 RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE,
143 RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST,
144 RNDIS_OID_802_3_XMIT_LATE_COLLISIONS,
145 #endif /* RNDIS_OPTIONAL_STATS */
146
147 #ifdef RNDIS_PM
148 /* PM and wakeup are "mandatory" for USB, but the RNDIS specs
149 * don't say what they mean ... and the NDIS specs are often
150 * confusing and/or ambiguous in this context. (That is, more
151 * so than their specs for the other OIDs.)
152 *
153 * FIXME someone who knows what these should do, please
154 * implement them!
155 */
156
157 /* power management */
158 OID_PNP_CAPABILITIES,
159 OID_PNP_QUERY_POWER,
160 OID_PNP_SET_POWER,
161
162 #ifdef RNDIS_WAKEUP
163 /* wake up host */
164 OID_PNP_ENABLE_WAKE_UP,
165 OID_PNP_ADD_WAKE_UP_PATTERN,
166 OID_PNP_REMOVE_WAKE_UP_PATTERN,
167 #endif /* RNDIS_WAKEUP */
168 #endif /* RNDIS_PM */
169 };
170
171
172 /* NDIS Functions */
gen_ndis_query_resp(int configNr,u32 OID,u8 * buf,unsigned buf_len,rndis_resp_t * r)173 static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
174 unsigned buf_len, rndis_resp_t *r)
175 {
176 int retval = -ENOTSUPP;
177 u32 length = 4; /* usually */
178 __le32 *outbuf;
179 int i, count;
180 rndis_query_cmplt_type *resp;
181 struct net_device *net;
182 struct rtnl_link_stats64 temp;
183 const struct rtnl_link_stats64 *stats;
184
185 if (!r) return -ENOMEM;
186 resp = (rndis_query_cmplt_type *)r->buf;
187
188 if (!resp) return -ENOMEM;
189
190 if (buf_len && rndis_debug > 1) {
191 pr_debug("query OID %08x value, len %d:\n", OID, buf_len);
192 for (i = 0; i < buf_len; i += 16) {
193 pr_debug("%03d: %08x %08x %08x %08x\n", i,
194 get_unaligned_le32(&buf[i]),
195 get_unaligned_le32(&buf[i + 4]),
196 get_unaligned_le32(&buf[i + 8]),
197 get_unaligned_le32(&buf[i + 12]));
198 }
199 }
200
201 /* response goes here, right after the header */
202 outbuf = (__le32 *)&resp[1];
203 resp->InformationBufferOffset = cpu_to_le32(16);
204
205 net = rndis_per_dev_params[configNr].dev;
206 stats = dev_get_stats(net, &temp);
207
208 switch (OID) {
209
210 /* general oids (table 4-1) */
211
212 /* mandatory */
213 case RNDIS_OID_GEN_SUPPORTED_LIST:
214 pr_debug("%s: RNDIS_OID_GEN_SUPPORTED_LIST\n", __func__);
215 length = sizeof(oid_supported_list);
216 count = length / sizeof(u32);
217 for (i = 0; i < count; i++)
218 outbuf[i] = cpu_to_le32(oid_supported_list[i]);
219 retval = 0;
220 break;
221
222 /* mandatory */
223 case RNDIS_OID_GEN_HARDWARE_STATUS:
224 pr_debug("%s: RNDIS_OID_GEN_HARDWARE_STATUS\n", __func__);
225 /* Bogus question!
226 * Hardware must be ready to receive high level protocols.
227 * BTW:
228 * reddite ergo quae sunt Caesaris Caesari
229 * et quae sunt Dei Deo!
230 */
231 *outbuf = cpu_to_le32(0);
232 retval = 0;
233 break;
234
235 /* mandatory */
236 case RNDIS_OID_GEN_MEDIA_SUPPORTED:
237 pr_debug("%s: RNDIS_OID_GEN_MEDIA_SUPPORTED\n", __func__);
238 *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
239 retval = 0;
240 break;
241
242 /* mandatory */
243 case RNDIS_OID_GEN_MEDIA_IN_USE:
244 pr_debug("%s: RNDIS_OID_GEN_MEDIA_IN_USE\n", __func__);
245 /* one medium, one transport... (maybe you do it better) */
246 *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium);
247 retval = 0;
248 break;
249
250 /* mandatory */
251 case RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE:
252 pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
253 if (rndis_per_dev_params[configNr].dev) {
254 *outbuf = cpu_to_le32(
255 rndis_per_dev_params[configNr].dev->mtu);
256 retval = 0;
257 }
258 break;
259
260 /* mandatory */
261 case RNDIS_OID_GEN_LINK_SPEED:
262 if (rndis_debug > 1)
263 pr_debug("%s: RNDIS_OID_GEN_LINK_SPEED\n", __func__);
264 if (rndis_per_dev_params[configNr].media_state
265 == RNDIS_MEDIA_STATE_DISCONNECTED)
266 *outbuf = cpu_to_le32(0);
267 else
268 *outbuf = cpu_to_le32(
269 rndis_per_dev_params[configNr].speed);
270 retval = 0;
271 break;
272
273 /* mandatory */
274 case RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE:
275 pr_debug("%s: RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
276 if (rndis_per_dev_params[configNr].dev) {
277 *outbuf = cpu_to_le32(
278 rndis_per_dev_params[configNr].dev->mtu);
279 retval = 0;
280 }
281 break;
282
283 /* mandatory */
284 case RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE:
285 pr_debug("%s: RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
286 if (rndis_per_dev_params[configNr].dev) {
287 *outbuf = cpu_to_le32(
288 rndis_per_dev_params[configNr].dev->mtu);
289 retval = 0;
290 }
291 break;
292
293 /* mandatory */
294 case RNDIS_OID_GEN_VENDOR_ID:
295 pr_debug("%s: RNDIS_OID_GEN_VENDOR_ID\n", __func__);
296 *outbuf = cpu_to_le32(
297 rndis_per_dev_params[configNr].vendorID);
298 retval = 0;
299 break;
300
301 /* mandatory */
302 case RNDIS_OID_GEN_VENDOR_DESCRIPTION:
303 pr_debug("%s: RNDIS_OID_GEN_VENDOR_DESCRIPTION\n", __func__);
304 if (rndis_per_dev_params[configNr].vendorDescr) {
305 length = strlen(rndis_per_dev_params[configNr].
306 vendorDescr);
307 memcpy(outbuf,
308 rndis_per_dev_params[configNr].vendorDescr,
309 length);
310 } else {
311 outbuf[0] = 0;
312 }
313 retval = 0;
314 break;
315
316 case RNDIS_OID_GEN_VENDOR_DRIVER_VERSION:
317 pr_debug("%s: RNDIS_OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
318 /* Created as LE */
319 *outbuf = rndis_driver_version;
320 retval = 0;
321 break;
322
323 /* mandatory */
324 case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
325 pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
326 *outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter);
327 retval = 0;
328 break;
329
330 /* mandatory */
331 case RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE:
332 pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
333 *outbuf = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
334 retval = 0;
335 break;
336
337 /* mandatory */
338 case RNDIS_OID_GEN_MEDIA_CONNECT_STATUS:
339 if (rndis_debug > 1)
340 pr_debug("%s: RNDIS_OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
341 *outbuf = cpu_to_le32(rndis_per_dev_params[configNr]
342 .media_state);
343 retval = 0;
344 break;
345
346 case RNDIS_OID_GEN_PHYSICAL_MEDIUM:
347 pr_debug("%s: RNDIS_OID_GEN_PHYSICAL_MEDIUM\n", __func__);
348 *outbuf = cpu_to_le32(0);
349 retval = 0;
350 break;
351
352 /* The RNDIS specification is incomplete/wrong. Some versions
353 * of MS-Windows expect OIDs that aren't specified there. Other
354 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
355 */
356 case RNDIS_OID_GEN_MAC_OPTIONS: /* from WinME */
357 pr_debug("%s: RNDIS_OID_GEN_MAC_OPTIONS\n", __func__);
358 *outbuf = cpu_to_le32(
359 RNDIS_MAC_OPTION_RECEIVE_SERIALIZED
360 | RNDIS_MAC_OPTION_FULL_DUPLEX);
361 retval = 0;
362 break;
363
364 /* statistics OIDs (table 4-2) */
365
366 /* mandatory */
367 case RNDIS_OID_GEN_XMIT_OK:
368 if (rndis_debug > 1)
369 pr_debug("%s: RNDIS_OID_GEN_XMIT_OK\n", __func__);
370 if (stats) {
371 *outbuf = cpu_to_le32(stats->tx_packets
372 - stats->tx_errors - stats->tx_dropped);
373 retval = 0;
374 }
375 break;
376
377 /* mandatory */
378 case RNDIS_OID_GEN_RCV_OK:
379 if (rndis_debug > 1)
380 pr_debug("%s: RNDIS_OID_GEN_RCV_OK\n", __func__);
381 if (stats) {
382 *outbuf = cpu_to_le32(stats->rx_packets
383 - stats->rx_errors - stats->rx_dropped);
384 retval = 0;
385 }
386 break;
387
388 /* mandatory */
389 case RNDIS_OID_GEN_XMIT_ERROR:
390 if (rndis_debug > 1)
391 pr_debug("%s: RNDIS_OID_GEN_XMIT_ERROR\n", __func__);
392 if (stats) {
393 *outbuf = cpu_to_le32(stats->tx_errors);
394 retval = 0;
395 }
396 break;
397
398 /* mandatory */
399 case RNDIS_OID_GEN_RCV_ERROR:
400 if (rndis_debug > 1)
401 pr_debug("%s: RNDIS_OID_GEN_RCV_ERROR\n", __func__);
402 if (stats) {
403 *outbuf = cpu_to_le32(stats->rx_errors);
404 retval = 0;
405 }
406 break;
407
408 /* mandatory */
409 case RNDIS_OID_GEN_RCV_NO_BUFFER:
410 pr_debug("%s: RNDIS_OID_GEN_RCV_NO_BUFFER\n", __func__);
411 if (stats) {
412 *outbuf = cpu_to_le32(stats->rx_dropped);
413 retval = 0;
414 }
415 break;
416
417 /* ieee802.3 OIDs (table 4-3) */
418
419 /* mandatory */
420 case RNDIS_OID_802_3_PERMANENT_ADDRESS:
421 pr_debug("%s: RNDIS_OID_802_3_PERMANENT_ADDRESS\n", __func__);
422 if (rndis_per_dev_params[configNr].dev) {
423 length = ETH_ALEN;
424 memcpy(outbuf,
425 rndis_per_dev_params[configNr].host_mac,
426 length);
427 retval = 0;
428 }
429 break;
430
431 /* mandatory */
432 case RNDIS_OID_802_3_CURRENT_ADDRESS:
433 pr_debug("%s: RNDIS_OID_802_3_CURRENT_ADDRESS\n", __func__);
434 if (rndis_per_dev_params[configNr].dev) {
435 length = ETH_ALEN;
436 memcpy(outbuf,
437 rndis_per_dev_params [configNr].host_mac,
438 length);
439 retval = 0;
440 }
441 break;
442
443 /* mandatory */
444 case RNDIS_OID_802_3_MULTICAST_LIST:
445 pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__);
446 /* Multicast base address only */
447 *outbuf = cpu_to_le32(0xE0000000);
448 retval = 0;
449 break;
450
451 /* mandatory */
452 case RNDIS_OID_802_3_MAXIMUM_LIST_SIZE:
453 pr_debug("%s: RNDIS_OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
454 /* Multicast base address only */
455 *outbuf = cpu_to_le32(1);
456 retval = 0;
457 break;
458
459 case RNDIS_OID_802_3_MAC_OPTIONS:
460 pr_debug("%s: RNDIS_OID_802_3_MAC_OPTIONS\n", __func__);
461 *outbuf = cpu_to_le32(0);
462 retval = 0;
463 break;
464
465 /* ieee802.3 statistics OIDs (table 4-4) */
466
467 /* mandatory */
468 case RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT:
469 pr_debug("%s: RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
470 if (stats) {
471 *outbuf = cpu_to_le32(stats->rx_frame_errors);
472 retval = 0;
473 }
474 break;
475
476 /* mandatory */
477 case RNDIS_OID_802_3_XMIT_ONE_COLLISION:
478 pr_debug("%s: RNDIS_OID_802_3_XMIT_ONE_COLLISION\n", __func__);
479 *outbuf = cpu_to_le32(0);
480 retval = 0;
481 break;
482
483 /* mandatory */
484 case RNDIS_OID_802_3_XMIT_MORE_COLLISIONS:
485 pr_debug("%s: RNDIS_OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
486 *outbuf = cpu_to_le32(0);
487 retval = 0;
488 break;
489
490 default:
491 pr_warning("%s: query unknown OID 0x%08X\n",
492 __func__, OID);
493 }
494 if (retval < 0)
495 length = 0;
496
497 resp->InformationBufferLength = cpu_to_le32(length);
498 r->length = length + sizeof(*resp);
499 resp->MessageLength = cpu_to_le32(r->length);
500 return retval;
501 }
502
gen_ndis_set_resp(u8 configNr,u32 OID,u8 * buf,u32 buf_len,rndis_resp_t * r)503 static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
504 rndis_resp_t *r)
505 {
506 rndis_set_cmplt_type *resp;
507 int i, retval = -ENOTSUPP;
508 struct rndis_params *params;
509
510 if (!r)
511 return -ENOMEM;
512 resp = (rndis_set_cmplt_type *)r->buf;
513 if (!resp)
514 return -ENOMEM;
515
516 if (buf_len && rndis_debug > 1) {
517 pr_debug("set OID %08x value, len %d:\n", OID, buf_len);
518 for (i = 0; i < buf_len; i += 16) {
519 pr_debug("%03d: %08x %08x %08x %08x\n", i,
520 get_unaligned_le32(&buf[i]),
521 get_unaligned_le32(&buf[i + 4]),
522 get_unaligned_le32(&buf[i + 8]),
523 get_unaligned_le32(&buf[i + 12]));
524 }
525 }
526
527 params = &rndis_per_dev_params[configNr];
528 switch (OID) {
529 case RNDIS_OID_GEN_CURRENT_PACKET_FILTER:
530
531 /* these NDIS_PACKET_TYPE_* bitflags are shared with
532 * cdc_filter; it's not RNDIS-specific
533 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
534 * PROMISCUOUS, DIRECTED,
535 * MULTICAST, ALL_MULTICAST, BROADCAST
536 */
537 *params->filter = (u16)get_unaligned_le32(buf);
538 pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER %08x\n",
539 __func__, *params->filter);
540
541 /* this call has a significant side effect: it's
542 * what makes the packet flow start and stop, like
543 * activating the CDC Ethernet altsetting.
544 */
545 retval = 0;
546 if (*params->filter) {
547 params->state = RNDIS_DATA_INITIALIZED;
548 netif_carrier_on(params->dev);
549 if (netif_running(params->dev))
550 netif_wake_queue(params->dev);
551 } else {
552 params->state = RNDIS_INITIALIZED;
553 netif_carrier_off(params->dev);
554 netif_stop_queue(params->dev);
555 }
556 break;
557
558 case RNDIS_OID_802_3_MULTICAST_LIST:
559 /* I think we can ignore this */
560 pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__);
561 retval = 0;
562 break;
563
564 default:
565 pr_warning("%s: set unknown OID 0x%08X, size %d\n",
566 __func__, OID, buf_len);
567 }
568
569 return retval;
570 }
571
572 /*
573 * Response Functions
574 */
575
rndis_init_response(int configNr,rndis_init_msg_type * buf)576 static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
577 {
578 rndis_init_cmplt_type *resp;
579 rndis_resp_t *r;
580 struct rndis_params *params = rndis_per_dev_params + configNr;
581
582 if (!params->dev)
583 return -ENOTSUPP;
584
585 r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
586 if (!r)
587 return -ENOMEM;
588 resp = (rndis_init_cmplt_type *)r->buf;
589
590 resp->MessageType = cpu_to_le32(RNDIS_MSG_INIT_C);
591 resp->MessageLength = cpu_to_le32(52);
592 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
593 resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
594 resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
595 resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
596 resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
597 resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
598 resp->MaxPacketsPerTransfer = cpu_to_le32(params->max_pkt_per_xfer);
599 resp->MaxTransferSize = cpu_to_le32(params->max_pkt_per_xfer *
600 (params->dev->mtu
601 + sizeof(struct ethhdr)
602 + sizeof(struct rndis_packet_msg_type)
603 + 22));
604 resp->PacketAlignmentFactor = cpu_to_le32(0);
605 resp->AFListOffset = cpu_to_le32(0);
606 resp->AFListSize = cpu_to_le32(0);
607
608 params->resp_avail(params->v);
609 return 0;
610 }
611
rndis_query_response(int configNr,rndis_query_msg_type * buf)612 static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
613 {
614 rndis_query_cmplt_type *resp;
615 rndis_resp_t *r;
616 struct rndis_params *params = rndis_per_dev_params + configNr;
617
618 /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */
619 if (!params->dev)
620 return -ENOTSUPP;
621
622 /*
623 * we need more memory:
624 * gen_ndis_query_resp expects enough space for
625 * rndis_query_cmplt_type followed by data.
626 * oid_supported_list is the largest data reply
627 */
628 r = rndis_add_response(configNr,
629 sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
630 if (!r)
631 return -ENOMEM;
632 resp = (rndis_query_cmplt_type *)r->buf;
633
634 resp->MessageType = cpu_to_le32(RNDIS_MSG_QUERY_C);
635 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
636
637 if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID),
638 le32_to_cpu(buf->InformationBufferOffset)
639 + 8 + (u8 *)buf,
640 le32_to_cpu(buf->InformationBufferLength),
641 r)) {
642 /* OID not supported */
643 resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
644 resp->MessageLength = cpu_to_le32(sizeof *resp);
645 resp->InformationBufferLength = cpu_to_le32(0);
646 resp->InformationBufferOffset = cpu_to_le32(0);
647 } else
648 resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
649
650 params->resp_avail(params->v);
651 return 0;
652 }
653
rndis_set_response(int configNr,rndis_set_msg_type * buf)654 static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
655 {
656 u32 BufLength, BufOffset;
657 rndis_set_cmplt_type *resp;
658 rndis_resp_t *r;
659 struct rndis_params *params = rndis_per_dev_params + configNr;
660
661 r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
662 if (!r)
663 return -ENOMEM;
664 resp = (rndis_set_cmplt_type *)r->buf;
665
666 BufLength = le32_to_cpu(buf->InformationBufferLength);
667 BufOffset = le32_to_cpu(buf->InformationBufferOffset);
668
669 #ifdef VERBOSE_DEBUG
670 pr_debug("%s: Length: %d\n", __func__, BufLength);
671 pr_debug("%s: Offset: %d\n", __func__, BufOffset);
672 pr_debug("%s: InfoBuffer: ", __func__);
673
674 for (i = 0; i < BufLength; i++) {
675 pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
676 }
677
678 pr_debug("\n");
679 #endif
680
681 resp->MessageType = cpu_to_le32(RNDIS_MSG_SET_C);
682 resp->MessageLength = cpu_to_le32(16);
683 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
684 if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID),
685 ((u8 *)buf) + 8 + BufOffset, BufLength, r))
686 resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
687 else
688 resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
689
690 params->resp_avail(params->v);
691 return 0;
692 }
693
rndis_reset_response(int configNr,rndis_reset_msg_type * buf)694 static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
695 {
696 rndis_reset_cmplt_type *resp;
697 rndis_resp_t *r;
698 struct rndis_params *params = rndis_per_dev_params + configNr;
699 u32 length;
700 u8 *xbuf;
701
702 /* drain the response queue */
703 while ((xbuf = rndis_get_next_response(configNr, &length)))
704 rndis_free_response(configNr, xbuf);
705
706 r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
707 if (!r)
708 return -ENOMEM;
709 resp = (rndis_reset_cmplt_type *)r->buf;
710
711 resp->MessageType = cpu_to_le32(RNDIS_MSG_RESET_C);
712 resp->MessageLength = cpu_to_le32(16);
713 resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
714 /* resent information */
715 resp->AddressingReset = cpu_to_le32(1);
716
717 params->resp_avail(params->v);
718 return 0;
719 }
720
rndis_keepalive_response(int configNr,rndis_keepalive_msg_type * buf)721 static int rndis_keepalive_response(int configNr,
722 rndis_keepalive_msg_type *buf)
723 {
724 rndis_keepalive_cmplt_type *resp;
725 rndis_resp_t *r;
726 struct rndis_params *params = rndis_per_dev_params + configNr;
727
728 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
729
730 r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
731 if (!r)
732 return -ENOMEM;
733 resp = (rndis_keepalive_cmplt_type *)r->buf;
734
735 resp->MessageType = cpu_to_le32(RNDIS_MSG_KEEPALIVE_C);
736 resp->MessageLength = cpu_to_le32(16);
737 resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
738 resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
739
740 params->resp_avail(params->v);
741 return 0;
742 }
743
744
745 /*
746 * Device to Host Comunication
747 */
rndis_indicate_status_msg(int configNr,u32 status)748 static int rndis_indicate_status_msg(int configNr, u32 status)
749 {
750 rndis_indicate_status_msg_type *resp;
751 rndis_resp_t *r;
752 struct rndis_params *params = rndis_per_dev_params + configNr;
753
754 if (params->state == RNDIS_UNINITIALIZED)
755 return -ENOTSUPP;
756
757 r = rndis_add_response(configNr,
758 sizeof(rndis_indicate_status_msg_type));
759 if (!r)
760 return -ENOMEM;
761 resp = (rndis_indicate_status_msg_type *)r->buf;
762
763 resp->MessageType = cpu_to_le32(RNDIS_MSG_INDICATE);
764 resp->MessageLength = cpu_to_le32(20);
765 resp->Status = cpu_to_le32(status);
766 resp->StatusBufferLength = cpu_to_le32(0);
767 resp->StatusBufferOffset = cpu_to_le32(0);
768
769 params->resp_avail(params->v);
770 return 0;
771 }
772
rndis_signal_connect(int configNr)773 int rndis_signal_connect(int configNr)
774 {
775 rndis_per_dev_params[configNr].media_state
776 = RNDIS_MEDIA_STATE_CONNECTED;
777 return rndis_indicate_status_msg(configNr,
778 RNDIS_STATUS_MEDIA_CONNECT);
779 }
780 EXPORT_SYMBOL_GPL(rndis_signal_connect);
781
rndis_signal_disconnect(int configNr)782 int rndis_signal_disconnect(int configNr)
783 {
784 rndis_per_dev_params[configNr].media_state
785 = RNDIS_MEDIA_STATE_DISCONNECTED;
786 return rndis_indicate_status_msg(configNr,
787 RNDIS_STATUS_MEDIA_DISCONNECT);
788 }
789 EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
790
rndis_uninit(int configNr)791 void rndis_uninit(int configNr)
792 {
793 u8 *buf;
794 u32 length;
795
796 if (configNr >= RNDIS_MAX_CONFIGS)
797 return;
798 rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
799
800 /* drain the response queue */
801 while ((buf = rndis_get_next_response(configNr, &length)))
802 rndis_free_response(configNr, buf);
803 }
804 EXPORT_SYMBOL_GPL(rndis_uninit);
805
rndis_set_host_mac(int configNr,const u8 * addr)806 void rndis_set_host_mac(int configNr, const u8 *addr)
807 {
808 rndis_per_dev_params[configNr].host_mac = addr;
809 }
810 EXPORT_SYMBOL_GPL(rndis_set_host_mac);
811
812 /*
813 * Message Parser
814 */
rndis_msg_parser(u8 configNr,u8 * buf)815 int rndis_msg_parser(u8 configNr, u8 *buf)
816 {
817 u32 MsgType, MsgLength;
818 __le32 *tmp;
819 struct rndis_params *params;
820
821 if (!buf)
822 return -ENOMEM;
823
824 tmp = (__le32 *)buf;
825 MsgType = get_unaligned_le32(tmp++);
826 MsgLength = get_unaligned_le32(tmp++);
827
828 if (configNr >= RNDIS_MAX_CONFIGS)
829 return -ENOTSUPP;
830 params = &rndis_per_dev_params[configNr];
831
832 /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
833 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
834 * and normal HC level polling to see if there's any IN traffic.
835 */
836
837 /* For USB: responses may take up to 10 seconds */
838 switch (MsgType) {
839 case RNDIS_MSG_INIT:
840 pr_debug("%s: RNDIS_MSG_INIT\n",
841 __func__);
842 params->state = RNDIS_INITIALIZED;
843 return rndis_init_response(configNr,
844 (rndis_init_msg_type *)buf);
845
846 case RNDIS_MSG_HALT:
847 pr_debug("%s: RNDIS_MSG_HALT\n",
848 __func__);
849 params->state = RNDIS_UNINITIALIZED;
850 if (params->dev) {
851 netif_carrier_off(params->dev);
852 netif_stop_queue(params->dev);
853 }
854 return 0;
855
856 case RNDIS_MSG_QUERY:
857 return rndis_query_response(configNr,
858 (rndis_query_msg_type *)buf);
859
860 case RNDIS_MSG_SET:
861 return rndis_set_response(configNr,
862 (rndis_set_msg_type *)buf);
863
864 case RNDIS_MSG_RESET:
865 pr_debug("%s: RNDIS_MSG_RESET\n",
866 __func__);
867 return rndis_reset_response(configNr,
868 (rndis_reset_msg_type *)buf);
869
870 case RNDIS_MSG_KEEPALIVE:
871 /* For USB: host does this every 5 seconds */
872 if (rndis_debug > 1)
873 pr_debug("%s: RNDIS_MSG_KEEPALIVE\n",
874 __func__);
875 return rndis_keepalive_response(configNr,
876 (rndis_keepalive_msg_type *)
877 buf);
878
879 default:
880 /* At least Windows XP emits some undefined RNDIS messages.
881 * In one case those messages seemed to relate to the host
882 * suspending itself.
883 */
884 pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
885 __func__, MsgType, MsgLength);
886 print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET,
887 buf, MsgLength);
888 break;
889 }
890
891 return -ENOTSUPP;
892 }
893 EXPORT_SYMBOL_GPL(rndis_msg_parser);
894
rndis_register(void (* resp_avail)(void * v),void * v)895 int rndis_register(void (*resp_avail)(void *v), void *v)
896 {
897 u8 i;
898
899 if (!resp_avail)
900 return -EINVAL;
901
902 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
903 if (!rndis_per_dev_params[i].used) {
904 rndis_per_dev_params[i].used = 1;
905 rndis_per_dev_params[i].resp_avail = resp_avail;
906 rndis_per_dev_params[i].v = v;
907 pr_debug("%s: configNr = %d\n", __func__, i);
908 return i;
909 }
910 }
911 pr_debug("failed\n");
912
913 return -ENODEV;
914 }
915 EXPORT_SYMBOL_GPL(rndis_register);
916
rndis_deregister(int configNr)917 void rndis_deregister(int configNr)
918 {
919 pr_debug("%s:\n", __func__);
920
921 if (configNr >= RNDIS_MAX_CONFIGS) return;
922 rndis_per_dev_params[configNr].used = 0;
923 }
924 EXPORT_SYMBOL_GPL(rndis_deregister);
925
rndis_set_param_dev(u8 configNr,struct net_device * dev,u16 * cdc_filter)926 int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
927 {
928 pr_debug("%s:\n", __func__);
929 if (!dev)
930 return -EINVAL;
931 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
932
933 rndis_per_dev_params[configNr].dev = dev;
934 rndis_per_dev_params[configNr].filter = cdc_filter;
935
936 rndis_ul_max_xfer_size_rcvd = 0;
937 rndis_ul_max_pkt_per_xfer_rcvd = 0;
938 return 0;
939 }
940 EXPORT_SYMBOL_GPL(rndis_set_param_dev);
941
rndis_set_param_vendor(u8 configNr,u32 vendorID,const char * vendorDescr)942 int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
943 {
944 pr_debug("%s:\n", __func__);
945 if (!vendorDescr) return -1;
946 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
947
948 rndis_per_dev_params[configNr].vendorID = vendorID;
949 rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
950
951 return 0;
952 }
953 EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
954
rndis_set_param_medium(u8 configNr,u32 medium,u32 speed)955 int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
956 {
957 pr_debug("%s: %u %u\n", __func__, medium, speed);
958 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
959
960 rndis_per_dev_params[configNr].medium = medium;
961 rndis_per_dev_params[configNr].speed = speed;
962
963 return 0;
964 }
965 EXPORT_SYMBOL_GPL(rndis_set_param_medium);
966
rndis_set_max_pkt_xfer(u8 configNr,u8 max_pkt_per_xfer)967 void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer)
968 {
969 pr_debug("%s:\n", __func__);
970
971 rndis_per_dev_params[configNr].max_pkt_per_xfer = max_pkt_per_xfer;
972 }
973
rndis_add_hdr(struct sk_buff * skb)974 void rndis_add_hdr(struct sk_buff *skb)
975 {
976 struct rndis_packet_msg_type *header;
977
978 if (!skb)
979 return;
980 header = (void *)skb_push(skb, sizeof(*header));
981 memset(header, 0, sizeof *header);
982 header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET);
983 header->MessageLength = cpu_to_le32(skb->len);
984 header->DataOffset = cpu_to_le32(36);
985 header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
986 }
987 EXPORT_SYMBOL_GPL(rndis_add_hdr);
988
rndis_free_response(int configNr,u8 * buf)989 void rndis_free_response(int configNr, u8 *buf)
990 {
991 rndis_resp_t *r;
992 struct list_head *act, *tmp;
993
994 list_for_each_safe(act, tmp,
995 &(rndis_per_dev_params[configNr].resp_queue))
996 {
997 r = list_entry(act, rndis_resp_t, list);
998 if (r && r->buf == buf) {
999 list_del(&r->list);
1000 kfree(r);
1001 }
1002 }
1003 }
1004 EXPORT_SYMBOL_GPL(rndis_free_response);
1005
rndis_get_next_response(int configNr,u32 * length)1006 u8 *rndis_get_next_response(int configNr, u32 *length)
1007 {
1008 rndis_resp_t *r;
1009 struct list_head *act, *tmp;
1010
1011 if (!length) return NULL;
1012
1013 list_for_each_safe(act, tmp,
1014 &(rndis_per_dev_params[configNr].resp_queue))
1015 {
1016 r = list_entry(act, rndis_resp_t, list);
1017 if (!r->send) {
1018 r->send = 1;
1019 *length = r->length;
1020 return r->buf;
1021 }
1022 }
1023
1024 return NULL;
1025 }
1026 EXPORT_SYMBOL_GPL(rndis_get_next_response);
1027
rndis_add_response(int configNr,u32 length)1028 static rndis_resp_t *rndis_add_response(int configNr, u32 length)
1029 {
1030 rndis_resp_t *r;
1031
1032 /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
1033 r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
1034 if (!r) return NULL;
1035
1036 r->buf = (u8 *)(r + 1);
1037 r->length = length;
1038 r->send = 0;
1039
1040 list_add_tail(&r->list,
1041 &(rndis_per_dev_params[configNr].resp_queue));
1042 return r;
1043 }
1044
rndis_rm_hdr(struct gether * port,struct sk_buff * skb,struct sk_buff_head * list)1045 int rndis_rm_hdr(struct gether *port,
1046 struct sk_buff *skb,
1047 struct sk_buff_head *list)
1048 {
1049 int num_pkts = 1;
1050
1051 if (skb->len > rndis_ul_max_xfer_size_rcvd)
1052 rndis_ul_max_xfer_size_rcvd = skb->len;
1053
1054 while (skb->len) {
1055 struct rndis_packet_msg_type *hdr;
1056 struct sk_buff *skb2;
1057 u32 msg_len, data_offset, data_len;
1058
1059 /* some rndis hosts send extra byte to avoid zlp, ignore it */
1060 if (skb->len == 1) {
1061 dev_kfree_skb_any(skb);
1062 return 0;
1063 }
1064
1065 if (skb->len < sizeof *hdr) {
1066 pr_err("invalid rndis pkt: skblen:%u hdr_len:%zu",
1067 skb->len, sizeof *hdr);
1068 dev_kfree_skb_any(skb);
1069 return -EINVAL;
1070 }
1071
1072 hdr = (void *)skb->data;
1073 msg_len = le32_to_cpu(hdr->MessageLength);
1074 data_offset = le32_to_cpu(hdr->DataOffset);
1075 data_len = le32_to_cpu(hdr->DataLength);
1076
1077 if (skb->len < msg_len ||
1078 ((data_offset + data_len + 8) > msg_len)) {
1079 pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n",
1080 le32_to_cpu(hdr->MessageType),
1081 msg_len, data_offset, data_len, skb->len);
1082 dev_kfree_skb_any(skb);
1083 return -EOVERFLOW;
1084 }
1085 if (le32_to_cpu(hdr->MessageType) != RNDIS_MSG_PACKET) {
1086 pr_err("invalid rndis message: %d/%d/%d/%d, len:%d\n",
1087 le32_to_cpu(hdr->MessageType),
1088 msg_len, data_offset, data_len, skb->len);
1089 dev_kfree_skb_any(skb);
1090 return -EINVAL;
1091 }
1092
1093 skb_pull(skb, data_offset + 8);
1094
1095 if (msg_len == skb->len) {
1096 skb_trim(skb, data_len);
1097 break;
1098 }
1099
1100 skb2 = skb_clone(skb, GFP_ATOMIC);
1101 if (!skb2) {
1102 pr_err("%s:skb clone failed\n", __func__);
1103 dev_kfree_skb_any(skb);
1104 return -ENOMEM;
1105 }
1106
1107 skb_pull(skb, msg_len - sizeof *hdr);
1108 skb_trim(skb2, data_len);
1109 skb_queue_tail(list, skb2);
1110
1111 num_pkts++;
1112 }
1113
1114 if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
1115 rndis_ul_max_pkt_per_xfer_rcvd = num_pkts;
1116
1117 skb_queue_tail(list, skb);
1118 return 0;
1119 }
1120 EXPORT_SYMBOL_GPL(rndis_rm_hdr);
1121
1122 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
1123
rndis_proc_show(struct seq_file * m,void * v)1124 static int rndis_proc_show(struct seq_file *m, void *v)
1125 {
1126 rndis_params *param = m->private;
1127
1128 seq_printf(m,
1129 "Config Nr. %d\n"
1130 "used : %s\n"
1131 "state : %s\n"
1132 "medium : 0x%08X\n"
1133 "speed : %d\n"
1134 "cable : %s\n"
1135 "vendor ID : 0x%08X\n"
1136 "vendor : %s\n",
1137 param->confignr, (param->used) ? "y" : "n",
1138 ({ char *s = "?";
1139 switch (param->state) {
1140 case RNDIS_UNINITIALIZED:
1141 s = "RNDIS_UNINITIALIZED"; break;
1142 case RNDIS_INITIALIZED:
1143 s = "RNDIS_INITIALIZED"; break;
1144 case RNDIS_DATA_INITIALIZED:
1145 s = "RNDIS_DATA_INITIALIZED"; break;
1146 } s; }),
1147 param->medium,
1148 (param->media_state) ? 0 : param->speed*100,
1149 (param->media_state) ? "disconnected" : "connected",
1150 param->vendorID, param->vendorDescr);
1151 return 0;
1152 }
1153
rndis_proc_write(struct file * file,const char __user * buffer,size_t count,loff_t * ppos)1154 static ssize_t rndis_proc_write(struct file *file, const char __user *buffer,
1155 size_t count, loff_t *ppos)
1156 {
1157 rndis_params *p = PDE_DATA(file_inode(file));
1158 u32 speed = 0;
1159 int i, fl_speed = 0;
1160
1161 for (i = 0; i < count; i++) {
1162 char c;
1163 if (get_user(c, buffer))
1164 return -EFAULT;
1165 switch (c) {
1166 case '0':
1167 case '1':
1168 case '2':
1169 case '3':
1170 case '4':
1171 case '5':
1172 case '6':
1173 case '7':
1174 case '8':
1175 case '9':
1176 fl_speed = 1;
1177 speed = speed * 10 + c - '0';
1178 break;
1179 case 'C':
1180 case 'c':
1181 rndis_signal_connect(p->confignr);
1182 break;
1183 case 'D':
1184 case 'd':
1185 rndis_signal_disconnect(p->confignr);
1186 break;
1187 default:
1188 if (fl_speed) p->speed = speed;
1189 else pr_debug("%c is not valid\n", c);
1190 break;
1191 }
1192
1193 buffer++;
1194 }
1195
1196 return count;
1197 }
1198
rndis_proc_open(struct inode * inode,struct file * file)1199 static int rndis_proc_open(struct inode *inode, struct file *file)
1200 {
1201 return single_open(file, rndis_proc_show, PDE_DATA(inode));
1202 }
1203
1204 static const struct file_operations rndis_proc_fops = {
1205 .owner = THIS_MODULE,
1206 .open = rndis_proc_open,
1207 .read = seq_read,
1208 .llseek = seq_lseek,
1209 .release = single_release,
1210 .write = rndis_proc_write,
1211 };
1212
1213 #define NAME_TEMPLATE "driver/rndis-%03d"
1214
1215 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
1216
1217 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
1218
1219
rndis_init(void)1220 int rndis_init(void)
1221 {
1222 u8 i;
1223
1224 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1225 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
1226 char name [20];
1227
1228 sprintf(name, NAME_TEMPLATE, i);
1229 rndis_connect_state[i] = proc_create_data(name, 0660, NULL,
1230 &rndis_proc_fops,
1231 (void *)(rndis_per_dev_params + i));
1232 if (!rndis_connect_state[i]) {
1233 pr_debug("%s: remove entries", __func__);
1234 while (i) {
1235 sprintf(name, NAME_TEMPLATE, --i);
1236 remove_proc_entry(name, NULL);
1237 }
1238 pr_debug("\n");
1239 return -EIO;
1240 }
1241 #endif
1242 rndis_per_dev_params[i].confignr = i;
1243 rndis_per_dev_params[i].used = 0;
1244 rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
1245 rndis_per_dev_params[i].media_state
1246 = RNDIS_MEDIA_STATE_DISCONNECTED;
1247 INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
1248 }
1249
1250 return 0;
1251 }
1252
rndis_exit(void)1253 void rndis_exit(void)
1254 {
1255 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
1256 u8 i;
1257 char name[20];
1258
1259 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1260 sprintf(name, NAME_TEMPLATE, i);
1261 remove_proc_entry(name, NULL);
1262 }
1263 #endif
1264 }
1265
1266