• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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