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