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
53static int rndis_debug = 0;
54module_param (rndis_debug, int, 0);
55MODULE_PARM_DESC (rndis_debug, "enable debugging");
56#else
57#define rndis_debug		0
58#endif
59
60#define RNDIS_MAX_CONFIGS	1
61
62int rndis_ul_max_pkt_per_xfer_rcvd;
63module_param(rndis_ul_max_pkt_per_xfer_rcvd, int, S_IRUGO);
64MODULE_PARM_DESC(rndis_ul_max_pkt_per_xfer_rcvd,
65		"Max num of REMOTE_NDIS_PACKET_MSGs received in a single transfer");
66
67int rndis_ul_max_xfer_size_rcvd;
68module_param(rndis_ul_max_xfer_size_rcvd, int, S_IRUGO);
69MODULE_PARM_DESC(rndis_ul_max_xfer_size_rcvd,
70		"Max size of bus transfer received");
71
72
73static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
74
75/* Driver Version */
76static const __le32 rndis_driver_version = cpu_to_le32(1);
77
78/* Function Prototypes */
79static rndis_resp_t *rndis_add_response(int configNr, u32 length);
80
81
82/* supported OIDs */
83static 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 */
173static 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
503static 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
576static 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
612static 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
654static 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
694static 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
721static 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 */
748static 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
773int 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}
780EXPORT_SYMBOL_GPL(rndis_signal_connect);
781
782int 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}
789EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
790
791void 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}
804EXPORT_SYMBOL_GPL(rndis_uninit);
805
806void rndis_set_host_mac(int configNr, const u8 *addr)
807{
808	rndis_per_dev_params[configNr].host_mac = addr;
809}
810EXPORT_SYMBOL_GPL(rndis_set_host_mac);
811
812/*
813 * Message Parser
814 */
815int 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}
893EXPORT_SYMBOL_GPL(rndis_msg_parser);
894
895int 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}
915EXPORT_SYMBOL_GPL(rndis_register);
916
917void 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}
924EXPORT_SYMBOL_GPL(rndis_deregister);
925
926int 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}
940EXPORT_SYMBOL_GPL(rndis_set_param_dev);
941
942int 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}
953EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
954
955int 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}
965EXPORT_SYMBOL_GPL(rndis_set_param_medium);
966
967void 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
974void 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}
987EXPORT_SYMBOL_GPL(rndis_add_hdr);
988
989void 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}
1004EXPORT_SYMBOL_GPL(rndis_free_response);
1005
1006u8 *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}
1026EXPORT_SYMBOL_GPL(rndis_get_next_response);
1027
1028static 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
1045int 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:%u",
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}
1120EXPORT_SYMBOL_GPL(rndis_rm_hdr);
1121
1122#ifdef CONFIG_USB_GADGET_DEBUG_FILES
1123
1124static 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
1154static 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
1199static int rndis_proc_open(struct inode *inode, struct file *file)
1200{
1201	return single_open(file, rndis_proc_show, PDE_DATA(inode));
1202}
1203
1204static 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
1215static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
1216
1217#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
1218
1219
1220int 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
1253void 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