patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / usb / gadget / rndis.c
1 /* 
2  * RNDIS MSG parser
3  * 
4  * Version:     $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
5  * 
6  * Authors:     Benedikt Spranger, Pengutronix
7  *              Robert Schwebel, Pengutronix
8  * 
9  *              This program is free software; you can redistribute it and/or
10  *              modify it under the terms of the GNU General Public License
11  *              version 2, as published by the Free Software Foundation. 
12  * 
13  *              This software was originally developed in conformance with
14  *              Microsoft's Remote NDIS Specification License Agreement.
15  *              
16  * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
17  *              Fixed message length bug in init_response
18  * 
19  * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
20  *              Fixed rndis_rm_hdr length bug.
21  */
22
23 #include <linux/config.h>
24 #include <linux/module.h>
25 #include <linux/moduleparam.h>
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/version.h>
29 #include <linux/init.h>
30 #include <linux/list.h>
31 #include <linux/proc_fs.h>
32 #include <linux/netdevice.h>
33
34 #include <asm/io.h>
35 #include <asm/byteorder.h>
36 #include <asm/system.h>
37
38 #include "rndis.h"
39
40
41 /* The driver for your USB chip needs to support ep0 OUT to work with
42  * RNDIS, plus the same three descriptors as CDC Ethernet.
43  *
44  * Windows hosts need an INF file like Documentation/usb/linux.inf
45  */
46
47 #ifndef __LITTLE_ENDIAN
48 #warning this code is missing all cpu_to_leXX() calls ...
49 #endif
50
51 #if 0
52 #define DEBUG if (rndis_debug) printk 
53 static int rndis_debug = 0;
54
55 module_param (rndis_debug, bool, 0);
56 MODULE_PARM_DESC (rndis_debug, "enable debugging");
57
58 #else
59 #define DEBUG(str,args...) do{}while(0)
60 #endif
61
62 #define RNDIS_MAX_CONFIGS       1
63
64 static struct proc_dir_entry *rndis_connect_dir;
65 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
66
67 static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
68
69 /* Driver Version */
70 static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
71
72 /* Function Prototypes */
73 static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
74 static int rndis_query_response (int configNr, rndis_query_msg_type *buf);
75 static int rndis_set_response (int configNr, rndis_set_msg_type *buf);
76 static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);
77 static int rndis_keepalive_response (int configNr, 
78                                      rndis_keepalive_msg_type *buf);
79
80 static rndis_resp_t *rndis_add_response (int configNr, u32 length);
81
82 /* FIXME OMITTED OIDs, that RNDIS-on-USB "must" support, include
83  *  - power management (OID_PNP_CAPABILITIES, ...)
84  *  - network wakeup (OID_PNP_ENABLE_WAKE_UP, ...)
85  */
86
87 /* NDIS Functions */
88 static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
89 {
90         int                     retval = -ENOTSUPP;
91         u32                     length = 0;
92         rndis_query_cmplt_type  *resp;
93
94         if (!r) return -ENOMEM;
95         resp = (rndis_query_cmplt_type *) r->buf;
96
97         if (!resp) return -ENOMEM;
98         
99         switch (OID) {
100         /* mandatory */
101         case OID_GEN_SUPPORTED_LIST:
102                 DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
103                 length = sizeof (oid_supported_list);
104                 memcpy ((u8 *) resp + 24, oid_supported_list, length); 
105                 retval = 0;
106                 break;
107                 
108         /* mandatory */
109         case OID_GEN_HARDWARE_STATUS:
110                 DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
111                 length = 4;
112                 /* Bogus question! 
113                  * Hardware must be ready to recieve high level protocols.
114                  * BTW: 
115                  * reddite ergo quae sunt Caesaris Caesari
116                  * et quae sunt Dei Deo!
117                  */
118                 *((u32 *) resp + 6) = 0;
119                 retval = 0;
120                 break;
121                 
122         /* mandatory */
123         case OID_GEN_MEDIA_SUPPORTED:
124                 DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
125                 length = 4;
126                 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
127                 retval = 0;
128                 break;
129                 
130         /* mandatory */
131         case OID_GEN_MEDIA_IN_USE:
132                 DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
133                 length = 4;
134                 /* one medium, one transport... (maybe you do it better) */
135                 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
136                 retval = 0;
137                 break;
138                 
139         case OID_GEN_MAXIMUM_LOOKAHEAD:
140                 DEBUG("%s: OID_GEN_MAXIMUM_LOOKAHEAD\n", __FUNCTION__);
141                 break;
142                 
143         /* mandatory */
144         case OID_GEN_MAXIMUM_FRAME_SIZE:
145                 DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
146                 if (rndis_per_dev_params [configNr].dev) {
147                         length = 4;
148                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
149                                                 .dev->mtu;
150                         retval = 0;
151                 } else {
152                         *((u32 *) resp + 6) = 0;
153                         retval = 0;
154                 }
155                 break;
156                 
157         /* mandatory */
158         case OID_GEN_LINK_SPEED:
159                 DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
160                 length = 4;
161                 if (rndis_per_dev_params [configNr].media_state
162                         == NDIS_MEDIA_STATE_DISCONNECTED)
163                     *((u32 *) resp + 6) = 0;
164                 else
165                     *((u32 *) resp + 6) = rndis_per_dev_params [configNr].speed;
166                 retval = 0;
167                 break;
168                 
169         case OID_GEN_TRANSMIT_BUFFER_SPACE:
170                 DEBUG("%s: OID_GEN_TRANSMIT_BUFFER_SPACE\n", __FUNCTION__);
171                 length = 4;
172                 *((u32 *) resp + 6) = 0;
173                 retval = 0;
174                 break;
175                 
176         case OID_GEN_RECEIVE_BUFFER_SPACE:
177                 DEBUG("%s: OID_GEN_RECEIVE_BUFFER_SPACE\n", __FUNCTION__);
178                 break;
179                 
180         /* mandatory */
181         case OID_GEN_TRANSMIT_BLOCK_SIZE:
182                 DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
183                 if (rndis_per_dev_params [configNr].dev) {
184                         length = 4;
185                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
186                                                 .dev->mtu;
187                         retval = 0;
188                 }
189                 break;
190                 
191         /* mandatory */
192         case OID_GEN_RECEIVE_BLOCK_SIZE:
193                 DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
194                 if (rndis_per_dev_params [configNr].dev) {
195                         length = 4;
196                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
197                                                 .dev->mtu;
198                         retval = 0;
199                 }
200                 break;
201                 
202         /* mandatory */
203         case OID_GEN_VENDOR_ID:
204                 DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
205                 length = 4;
206                 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].vendorID;
207                 retval = 0;
208                 break;
209                 
210         /* mandatory */
211         case OID_GEN_VENDOR_DESCRIPTION:
212                 DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
213                 length = strlen (rndis_per_dev_params [configNr].vendorDescr);
214                 memcpy ((u8 *) resp + 24, 
215                         rndis_per_dev_params [configNr].vendorDescr, length);
216                 retval = 0;
217                 break;
218
219         /* mandatory */
220         case OID_GEN_CURRENT_PACKET_FILTER:
221                 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
222                 length = 4;
223                 *((u32 *) resp + 6) = rndis_per_dev_params[configNr].filter;
224                 retval = 0;
225                 break;
226                 
227         case OID_GEN_CURRENT_LOOKAHEAD:
228                 DEBUG("%s: OID_GEN_CURRENT_LOOKAHEAD\n", __FUNCTION__);
229                 break;
230                 
231         case OID_GEN_DRIVER_VERSION:
232                 DEBUG("%s: OID_GEN_DRIVER_VERSION\n", __FUNCTION__);
233                 break;
234                 
235         /* mandatory */
236         case OID_GEN_MAXIMUM_TOTAL_SIZE:
237                 DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
238                 length = 4;
239                 *((u32 *) resp + 6) = RNDIS_MAX_TOTAL_SIZE;
240                 retval = 0;
241                 break;
242                 
243         case OID_GEN_PROTOCOL_OPTIONS:
244                 DEBUG("%s: OID_GEN_PROTOCOL_OPTIONS\n", __FUNCTION__);
245                 break;
246                 
247         case OID_GEN_MAC_OPTIONS:
248                 DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
249                 length = 4;
250                 *((u32 *) resp + 6) = NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 
251                     NDIS_MAC_OPTION_FULL_DUPLEX;
252                 retval = 0;
253                 break;
254                 
255         /* mandatory */
256         case OID_GEN_MEDIA_CONNECT_STATUS:
257                 DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
258                 length = 4;
259                 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
260                                                 .media_state;
261                 retval = 0;
262                 break;
263                 
264         case OID_GEN_MAXIMUM_SEND_PACKETS:
265                 DEBUG("%s: OID_GEN_MAXIMUM_SEND_PACKETS\n", __FUNCTION__);
266                 break;
267                 
268         /* mandatory */
269         case OID_GEN_VENDOR_DRIVER_VERSION:
270                 DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
271                 length = 4;
272                 *((u32 *) resp + 6) = rndis_driver_version;
273                 retval = 0;
274                 break;
275                 
276         case OID_GEN_SUPPORTED_GUIDS:
277                 DEBUG("%s: OID_GEN_SUPPORTED_GUIDS\n", __FUNCTION__);
278                 break;
279                 
280         case OID_GEN_NETWORK_LAYER_ADDRESSES:
281                 DEBUG("%s: OID_GEN_NETWORK_LAYER_ADDRESSES\n", __FUNCTION__);
282                 break;
283                 
284         case OID_GEN_TRANSPORT_HEADER_OFFSET:
285                 DEBUG("%s: OID_GEN_TRANSPORT_HEADER_OFFSET\n", __FUNCTION__);
286                 break;
287                 
288         case OID_GEN_MACHINE_NAME:
289                 DEBUG("%s: OID_GEN_MACHINE_NAME\n", __FUNCTION__);
290                 break;
291                 
292         case OID_GEN_RNDIS_CONFIG_PARAMETER:
293                 DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
294                 length = 4;
295                 *((u32 *) resp + 6) = 0;
296                 retval = 0;
297                 break;
298                 
299         case OID_GEN_VLAN_ID:
300                 DEBUG("%s: OID_GEN_VLAN_ID\n", __FUNCTION__);
301                 break;
302                 
303         case OID_GEN_MEDIA_CAPABILITIES:
304                 DEBUG("%s: OID_GEN_MEDIA_CAPABILITIES\n", __FUNCTION__);
305                 break;
306                 
307         case OID_GEN_PHYSICAL_MEDIUM:
308                 DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
309                 length = 4;
310                 *((u32 *) resp + 6) = 0;
311                 retval = 0;
312                 break;
313                 
314         /* mandatory */
315         case OID_GEN_XMIT_OK:
316                 DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
317                 if (rndis_per_dev_params [configNr].stats) {
318                         length = 4;
319                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
320                                         .stats->tx_packets - 
321                             rndis_per_dev_params [configNr].stats->tx_errors -
322                             rndis_per_dev_params [configNr].stats->tx_dropped;
323                         retval = 0;
324                 } else {
325                         *((u32 *) resp + 6) = 0;
326                         retval = 0;
327                 }
328                 break;
329                 
330         /* mandatory */
331         case OID_GEN_RCV_OK:
332                 DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
333                 if (rndis_per_dev_params [configNr].stats) {
334                         length = 4;
335                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
336                                         stats->rx_packets - 
337                             rndis_per_dev_params [configNr].stats->rx_errors -
338                             rndis_per_dev_params [configNr].stats->rx_dropped;
339                         retval = 0;
340                 } else {
341                         *((u32 *) resp + 6) = 0;
342                         retval = 0;
343                 }
344                 break;
345                 
346         /* mandatory */
347         case OID_GEN_XMIT_ERROR:
348                 DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
349                 if (rndis_per_dev_params [configNr].stats) {
350                         length = 4;
351                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
352                                         stats->tx_errors;
353                         retval = 0;
354                 } else {
355                         *((u32 *) resp + 6) = 0;
356                         retval = 0;
357                 }
358                 break;
359                 
360         /* mandatory */
361         case OID_GEN_RCV_ERROR:
362                 DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
363                 if (rndis_per_dev_params [configNr].stats) {
364                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
365                                         stats->rx_errors;
366                         retval = 0;
367                 } else {
368                         *((u32 *) resp + 6) = 0;
369                         retval = 0;
370                 }
371                 break;
372                 
373         /* mandatory */
374         case OID_GEN_RCV_NO_BUFFER:
375                 DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
376                 if (rndis_per_dev_params [configNr].stats) {
377                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
378                                         stats->rx_dropped;
379                         retval = 0;
380                 } else {
381                         *((u32 *) resp + 6) = 0;
382                         retval = 0;
383                 }
384                 break;
385                 
386         case OID_GEN_DIRECTED_BYTES_XMIT:
387                 DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
388                 /* 
389                  * Aunt Tilly's size of shoes
390                  * minus antarctica count of penguins
391                  * divided by weight of Alpha Centauri
392                  */
393                 if (rndis_per_dev_params [configNr].stats) {
394                         length = 4;
395                         *((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
396                                         stats->tx_packets - 
397                             rndis_per_dev_params [configNr].stats->tx_errors -
398                             rndis_per_dev_params [configNr].stats->tx_dropped)
399                                         *123;
400                         retval = 0;
401                 } else {
402                         *((u32 *) resp + 6) = 0;
403                         retval = 0;
404                 }
405                 break;
406                 
407         case OID_GEN_DIRECTED_FRAMES_XMIT:
408                 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
409                 /* dito */
410                 if (rndis_per_dev_params [configNr].stats) {
411                         length = 4;
412                         *((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
413                                         stats->tx_packets - 
414                             rndis_per_dev_params [configNr].stats->tx_errors -
415                             rndis_per_dev_params [configNr].stats->tx_dropped)
416                                         /123;
417                         retval = 0;
418                 } else {
419                         *((u32 *) resp + 6) = 0;
420                         retval = 0;
421                 }
422                 break;
423                 
424         case OID_GEN_MULTICAST_BYTES_XMIT:
425                 DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
426                 if (rndis_per_dev_params [configNr].stats) {
427                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
428                                         stats->multicast*1234;
429                         retval = 0;
430                 } else {
431                         *((u32 *) resp + 6) = 0;
432                         retval = 0;
433                 }
434                 break;
435                 
436         case OID_GEN_MULTICAST_FRAMES_XMIT:
437                 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
438                 if (rndis_per_dev_params [configNr].stats) {
439                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
440                                         stats->multicast;
441                         retval = 0;
442                 } else {
443                         *((u32 *) resp + 6) = 0;
444                         retval = 0;
445                 }
446                 break;
447                 
448         case OID_GEN_BROADCAST_BYTES_XMIT:
449                 DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
450                 if (rndis_per_dev_params [configNr].stats) {
451                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
452                                         stats->tx_packets/42*255;
453                         retval = 0;
454                 } else {
455                         *((u32 *) resp + 6) = 0;
456                         retval = 0;
457                 }
458                 break;
459                 
460         case OID_GEN_BROADCAST_FRAMES_XMIT:
461                 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
462                 if (rndis_per_dev_params [configNr].stats) {
463                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
464                                         stats->tx_packets/42;
465                         retval = 0;
466                 } else {
467                         *((u32 *) resp + 6) = 0;
468                         retval = 0;
469                 }
470                 break;
471                 
472         case OID_GEN_DIRECTED_BYTES_RCV:
473                 DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
474                 *((u32 *) resp + 6) = 0;
475                 retval = 0;
476                 break;
477                 
478         case OID_GEN_DIRECTED_FRAMES_RCV:
479                 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
480                 *((u32 *) resp + 6) = 0;
481                 retval = 0;
482                 break;
483                 
484         case OID_GEN_MULTICAST_BYTES_RCV:
485                 DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
486                 if (rndis_per_dev_params [configNr].stats) {
487                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
488                                         stats->multicast*1111;
489                         retval = 0;
490                 } else {
491                         *((u32 *) resp + 6) = 0;
492                         retval = 0;
493                 }
494                 break;
495                 
496         case OID_GEN_MULTICAST_FRAMES_RCV:
497                 DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
498                 if (rndis_per_dev_params [configNr].stats) {
499                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
500                                         stats->multicast;
501                         retval = 0;
502                 } else {
503                         *((u32 *) resp + 6) = 0;
504                         retval = 0;
505                 }
506                 break;
507                 
508         case OID_GEN_BROADCAST_BYTES_RCV:
509                 DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
510                 if (rndis_per_dev_params [configNr].stats) {
511                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
512                                         stats->rx_packets/42*255;
513                         retval = 0;
514                 } else {
515                         *((u32 *) resp + 6) = 0;
516                         retval = 0;
517                 }
518                 break;
519                 
520         case OID_GEN_BROADCAST_FRAMES_RCV:
521                 DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
522                 if (rndis_per_dev_params [configNr].stats) {
523                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
524                                         stats->rx_packets/42;
525                         retval = 0;
526                 } else {
527                         *((u32 *) resp + 6) = 0;
528                         retval = 0;
529                 }
530                 break;
531                 
532         case OID_GEN_RCV_CRC_ERROR:
533                 DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
534                 if (rndis_per_dev_params [configNr].stats) {
535                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
536                                         stats->rx_crc_errors;
537                         retval = 0;
538                 } else {
539                         *((u32 *) resp + 6) = 0;
540                         retval = 0;
541                 }
542                 break;
543                 
544         case OID_GEN_TRANSMIT_QUEUE_LENGTH:
545                 DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
546                 *((u32 *) resp + 6) = 0;
547                 retval = 0;
548                 break;
549                 
550         case OID_GEN_GET_TIME_CAPS:
551                 DEBUG("%s: OID_GEN_GET_TIME_CAPS\n", __FUNCTION__);
552                 break;
553                 
554         case OID_GEN_GET_NETCARD_TIME:
555                 DEBUG("%s: OID_GEN_GET_NETCARD_TIME\n", __FUNCTION__);
556                 break;
557                 
558         case OID_GEN_NETCARD_LOAD:
559                 DEBUG("%s: OID_GEN_NETCARD_LOAD\n", __FUNCTION__);
560                 break;
561                 
562         case OID_GEN_DEVICE_PROFILE:
563                 DEBUG("%s: OID_GEN_DEVICE_PROFILE\n", __FUNCTION__);
564                 break;
565                 
566         case OID_GEN_INIT_TIME_MS:
567                 DEBUG("%s: OID_GEN_INIT_TIME_MS\n", __FUNCTION__);
568                 break;
569                 
570         case OID_GEN_RESET_COUNTS:
571                 DEBUG("%s: OID_GEN_RESET_COUNTS\n", __FUNCTION__);
572                 break;
573                 
574         case OID_GEN_MEDIA_SENSE_COUNTS:
575                 DEBUG("%s: OID_GEN_MEDIA_SENSE_COUNTS\n", __FUNCTION__);
576                 break;
577                 
578         case OID_GEN_FRIENDLY_NAME:
579                 DEBUG("%s: OID_GEN_FRIENDLY_NAME\n", __FUNCTION__);
580                 break;
581                 
582         case OID_GEN_MINIPORT_INFO:
583                 DEBUG("%s: OID_GEN_MINIPORT_INFO\n", __FUNCTION__);
584                 break;
585                 
586         case OID_GEN_RESET_VERIFY_PARAMETERS:
587                 DEBUG("%s: OID_GEN_RESET_VERIFY_PARAMETERS\n", __FUNCTION__);
588                 break;
589                 
590         /* mandatory */
591         case OID_802_3_PERMANENT_ADDRESS:
592                 DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
593                 if (rndis_per_dev_params [configNr].dev) {
594                         length = ETH_ALEN;
595                         memcpy ((u8 *) resp + 24,
596                                 rndis_per_dev_params [configNr].host_mac,
597                                 length);
598                         retval = 0;
599                 } else {
600                         *((u32 *) resp + 6) = 0;
601                         retval = 0;
602                 }
603                 break;
604                 
605         /* mandatory */
606         case OID_802_3_CURRENT_ADDRESS:
607                 DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
608                 if (rndis_per_dev_params [configNr].dev) {
609                         length = ETH_ALEN;
610                         memcpy ((u8 *) resp + 24,
611                                 rndis_per_dev_params [configNr].host_mac,
612                                 length);
613                         retval = 0;
614                 }
615                 break;
616                 
617         /* mandatory */
618         case OID_802_3_MULTICAST_LIST:
619                 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
620                 length = 4;
621                 /* Multicast base address only */
622                 *((u32 *) resp + 6) = 0xE0000000;
623                 retval = 0;
624                 break;
625                 
626         /* mandatory */
627         case OID_802_3_MAXIMUM_LIST_SIZE:
628                 DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
629                  length = 4;
630                 /* Multicast base address only */
631                 *((u32 *) resp + 6) = 1;
632                 retval = 0;
633                 break;
634                 
635         case OID_802_3_MAC_OPTIONS:
636                 DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
637                 break;
638                 
639         /* mandatory */
640         case OID_802_3_RCV_ERROR_ALIGNMENT:
641                 DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
642                 if (rndis_per_dev_params [configNr].stats)
643                 {
644                         length = 4;
645                         *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
646                                         .stats->rx_frame_errors;
647                         retval = 0;
648                 }
649                 break;
650                 
651         /* mandatory */
652         case OID_802_3_XMIT_ONE_COLLISION:
653                 DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
654                 length = 4;
655                 *((u32 *) resp + 6) = 0;
656                 retval = 0;
657                 break;
658                 
659         /* mandatory */
660         case OID_802_3_XMIT_MORE_COLLISIONS:
661                 DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
662                 length = 4;
663                 *((u32 *) resp + 6) = 0;
664                 retval = 0;
665                 break;
666                 
667         case OID_802_3_XMIT_DEFERRED:
668                 DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
669                 /* TODO */
670                 break;
671                 
672         case OID_802_3_XMIT_MAX_COLLISIONS:
673                 DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
674                 /* TODO */
675                 break;
676                 
677         case OID_802_3_RCV_OVERRUN:
678                 DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
679                 /* TODO */
680                 break;
681                 
682         case OID_802_3_XMIT_UNDERRUN:
683                 DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
684                 /* TODO */
685                 break;
686                 
687         case OID_802_3_XMIT_HEARTBEAT_FAILURE:
688                 DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
689                 /* TODO */
690                 break;
691                 
692         case OID_802_3_XMIT_TIMES_CRS_LOST:
693                 DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
694                 /* TODO */
695                 break;
696                 
697         case OID_802_3_XMIT_LATE_COLLISIONS:
698                 DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
699                 /* TODO */
700                 break;          
701                 
702         default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", 
703                          __FUNCTION__, OID);
704         }
705         
706         resp->InformationBufferOffset = 16;
707         resp->InformationBufferLength = length;
708         resp->MessageLength = 24 + length;
709         r->length = 24 + length;
710         return retval;
711 }
712
713 static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, 
714                               rndis_resp_t *r)
715 {
716         rndis_set_cmplt_type            *resp;
717         int                             i, retval = -ENOTSUPP;
718         struct rndis_config_parameter   *param;
719         struct rndis_params             *params;
720         u8 *cp;
721
722         if (!r)
723                 return -ENOMEM;
724         resp = (rndis_set_cmplt_type *) r->buf;
725         if (!resp)
726                 return -ENOMEM;
727
728         cp = (u8 *)resp;
729
730         switch (OID) {
731         case OID_GEN_CURRENT_PACKET_FILTER:
732                 params = &rndis_per_dev_params [configNr];
733                 retval = 0;
734
735                 /* FIXME use this NDIS_PACKET_TYPE_* bitflags to
736                  * filter packets in hard_start_xmit()
737                  * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in:
738                  *      PROMISCUOUS, DIRECTED,
739                  *      MULTICAST, ALL_MULTICAST, BROADCAST
740                  */
741                 params->filter = *(u32 *)buf;
742                 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
743                         __FUNCTION__, params->filter);
744
745                 /* this call has a significant side effect:  it's
746                  * what makes the packet flow start and stop, like
747                  * activating the CDC Ethernet altsetting.
748                  */
749                 if (params->filter) {
750                         params->state = RNDIS_DATA_INITIALIZED;
751                         netif_carrier_on(params->dev);
752                         if (netif_running(params->dev))
753                                 netif_wake_queue (params->dev);
754                 } else {
755                         params->state = RNDIS_INITIALIZED;
756                         netif_carrier_off (params->dev);
757                         netif_stop_queue (params->dev);
758                 }
759                 break;
760                 
761         case OID_802_3_MULTICAST_LIST:
762                 /* I think we can ignore this */                
763                 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
764                 retval = 0;
765                 break;
766                 
767         case OID_GEN_RNDIS_CONFIG_PARAMETER:
768                 DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
769                 param = (struct rndis_config_parameter *) buf;
770                 if (param) {
771                         for (i = 0; i < param->ParameterNameLength; i++) {
772                                 DEBUG ("%c", 
773                                        *(buf + param->ParameterNameOffset + i));
774                         }
775                         DEBUG ("\n");
776                 }
777                 
778                 retval = 0;
779                 break;
780                 
781         default: printk (KERN_ERR "%s: unknown OID 0x%08X\n", 
782                          __FUNCTION__, OID);
783         }
784         
785         return retval;
786 }
787
788 /* 
789  * Response Functions 
790  */
791
792 static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
793 {
794         rndis_init_cmplt_type   *resp; 
795         rndis_resp_t            *r;
796         
797         if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
798         
799         r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
800         
801         if (!r) return -ENOMEM;
802         
803         resp = (rndis_init_cmplt_type *) r->buf;
804         
805         if (!resp) return -ENOMEM;
806         
807         resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
808         resp->MessageLength = 52;
809         resp->RequestID = buf->RequestID;
810         resp->Status = RNDIS_STATUS_SUCCESS;
811         resp->MajorVersion = RNDIS_MAJOR_VERSION;
812         resp->MinorVersion = RNDIS_MINOR_VERSION;
813         resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
814         resp->Medium = RNDIS_MEDIUM_802_3;
815         resp->MaxPacketsPerTransfer = 1;
816         resp->MaxTransferSize = rndis_per_dev_params [configNr].dev->mtu
817                 + sizeof (struct ethhdr)
818                 + sizeof (struct rndis_packet_msg_type)
819                 + 22;
820         resp->PacketAlignmentFactor = 0;
821         resp->AFListOffset = 0;
822         resp->AFListSize = 0;
823         
824         if (rndis_per_dev_params [configNr].ack)
825             rndis_per_dev_params [configNr].ack (
826                         rndis_per_dev_params [configNr].dev);
827         
828         return 0;
829 }
830
831 static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
832 {
833         rndis_query_cmplt_type *resp;
834         rndis_resp_t            *r;
835         
836         DEBUG("%s: OID = %08X\n", __FUNCTION__, buf->OID);
837         if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
838         
839         /* 
840          * we need more memory: 
841          * oid_supported_list is the largest answer 
842          */
843         r = rndis_add_response (configNr, sizeof (oid_supported_list));
844         
845         if (!r) return -ENOMEM;
846         resp = (rndis_query_cmplt_type *) r->buf;
847         
848         if (!resp) return -ENOMEM;
849         
850         resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
851         resp->MessageLength = 24;
852         resp->RequestID = buf->RequestID;
853         
854         if (gen_ndis_query_resp (configNr, buf->OID, r)) {
855                 /* OID not supported */
856                 resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
857                 resp->InformationBufferLength = 0;
858                 resp->InformationBufferOffset = 0;
859         } else
860                 resp->Status = RNDIS_STATUS_SUCCESS;
861         
862         if (rndis_per_dev_params [configNr].ack)
863             rndis_per_dev_params [configNr].ack (
864                         rndis_per_dev_params [configNr].dev);
865         return 0;
866 }
867
868 static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
869 {
870         rndis_set_cmplt_type    *resp;
871         rndis_resp_t            *r;
872         int                     i;
873         
874         r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
875         
876         if (!r) return -ENOMEM;
877         resp = (rndis_set_cmplt_type *) r->buf;
878         if (!resp) return -ENOMEM;
879         
880         DEBUG("%s: Length: %d\n", __FUNCTION__, buf->InformationBufferLength);
881         DEBUG("%s: Offset: %d\n", __FUNCTION__, buf->InformationBufferOffset);
882         DEBUG("%s: InfoBuffer: ", __FUNCTION__);
883         
884         for (i = 0; i < buf->InformationBufferLength; i++) {
885                 DEBUG ("%02x ", *(((u8 *) buf) + i + 12 +
886                        buf->InformationBufferOffset));
887         }
888         
889         DEBUG ("\n");
890         
891         resp->MessageType = REMOTE_NDIS_SET_CMPLT;
892         resp->MessageLength = 16;
893         resp->RequestID = buf->RequestID;
894         if (gen_ndis_set_resp (configNr, buf->OID, 
895                                ((u8 *) buf) + 28, 
896                                buf->InformationBufferLength, r))
897             resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
898         else resp->Status = RNDIS_STATUS_SUCCESS;
899         
900         if (rndis_per_dev_params [configNr].ack)
901             rndis_per_dev_params [configNr].ack (rndis_per_dev_params [configNr].dev);
902         
903         return 0;
904 }
905
906 static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
907 {
908         rndis_reset_cmplt_type  *resp;
909         rndis_resp_t            *r;
910         
911         r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
912         
913         if (!r) return -ENOMEM;
914         resp = (rndis_reset_cmplt_type *) r->buf;
915         if (!resp) return -ENOMEM;
916         
917         resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
918         resp->MessageLength = 16;
919         resp->Status = RNDIS_STATUS_SUCCESS;
920         resp->AddressingReset = 1; /* resent information */
921         
922         if (rndis_per_dev_params [configNr].ack)
923             rndis_per_dev_params [configNr].ack (
924                         rndis_per_dev_params [configNr].dev);
925
926         return 0;
927 }
928
929 static int rndis_keepalive_response (int configNr,
930                                      rndis_keepalive_msg_type *buf)
931 {
932         rndis_keepalive_cmplt_type      *resp;
933         rndis_resp_t                    *r;
934
935         /* host "should" check only in RNDIS_DATA_INITIALIZED state */
936
937         r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
938         resp = (rndis_keepalive_cmplt_type *) r->buf;
939         if (!resp) return -ENOMEM;
940                 
941         resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
942         resp->MessageLength = 16;
943         resp->RequestID = buf->RequestID;
944         resp->Status = RNDIS_STATUS_SUCCESS;
945         
946         if (rndis_per_dev_params [configNr].ack)
947             rndis_per_dev_params [configNr].ack (
948                         rndis_per_dev_params [configNr].dev);
949         
950         return 0;
951 }
952
953
954 /* 
955  * Device to Host Comunication 
956  */
957 static int rndis_indicate_status_msg (int configNr, u32 status)
958 {
959         rndis_indicate_status_msg_type  *resp;  
960         rndis_resp_t                    *r;
961         
962         if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
963             return -ENOTSUPP;
964         
965         r = rndis_add_response (configNr, 
966                                 sizeof (rndis_indicate_status_msg_type));
967         if (!r) return -ENOMEM;
968         
969         resp = (rndis_indicate_status_msg_type *) r->buf;
970         if (!resp) return -ENOMEM;
971         
972         resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
973         resp->MessageLength = 20;
974         resp->Status = status;
975         resp->StatusBufferLength = 0;
976         resp->StatusBufferOffset = 0;
977         
978         if (rndis_per_dev_params [configNr].ack) 
979             rndis_per_dev_params [configNr].ack (
980                         rndis_per_dev_params [configNr].dev);
981         return 0;
982 }
983
984 int rndis_signal_connect (int configNr)
985 {
986         rndis_per_dev_params [configNr].media_state
987                         = NDIS_MEDIA_STATE_CONNECTED;
988         return rndis_indicate_status_msg (configNr, 
989                                           RNDIS_STATUS_MEDIA_CONNECT);
990 }
991
992 int rndis_signal_disconnect (int configNr)
993 {
994         rndis_per_dev_params [configNr].media_state
995                         = NDIS_MEDIA_STATE_DISCONNECTED;
996         return rndis_indicate_status_msg (configNr,
997                                           RNDIS_STATUS_MEDIA_DISCONNECT);
998 }
999
1000 void rndis_set_host_mac (int configNr, const u8 *addr)
1001 {
1002         rndis_per_dev_params [configNr].host_mac = addr;
1003 }
1004
1005 /* 
1006  * Message Parser 
1007  */
1008 int rndis_msg_parser (u8 configNr, u8 *buf)
1009 {
1010         u32 MsgType, MsgLength, *tmp;
1011         struct rndis_params             *params;
1012         
1013         if (!buf)
1014                 return -ENOMEM;
1015         
1016         tmp = (u32 *) buf; 
1017         MsgType = *tmp;
1018         MsgLength = *(tmp + 1);
1019         
1020         if (configNr >= RNDIS_MAX_CONFIGS)
1021                 return -ENOTSUPP;
1022         params = &rndis_per_dev_params [configNr];
1023         
1024         /* For USB: responses may take up to 10 seconds */
1025         switch (MsgType)
1026         {
1027         case REMOTE_NDIS_INITIALIZE_MSG:
1028                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
1029                         __FUNCTION__ );
1030                 params->state = RNDIS_INITIALIZED;
1031                 return  rndis_init_response (configNr,
1032                                              (rndis_init_msg_type *) buf);
1033                 
1034         case REMOTE_NDIS_HALT_MSG:
1035                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_HALT_MSG\n",
1036                         __FUNCTION__ );
1037                 params->state = RNDIS_UNINITIALIZED;
1038                 if (params->dev) {
1039                         netif_carrier_off (params->dev);
1040                         netif_stop_queue (params->dev);
1041                 }
1042                 return 0;
1043                 
1044         case REMOTE_NDIS_QUERY_MSG:
1045                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_QUERY_MSG\n", 
1046                         __FUNCTION__ );
1047                 return rndis_query_response (configNr, 
1048                                              (rndis_query_msg_type *) buf);
1049                 
1050         case REMOTE_NDIS_SET_MSG:
1051                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n", 
1052                         __FUNCTION__ );
1053                 return rndis_set_response (configNr, 
1054                                            (rndis_set_msg_type *) buf);
1055                 
1056         case REMOTE_NDIS_RESET_MSG:
1057                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_RESET_MSG\n", 
1058                         __FUNCTION__ );
1059                 return rndis_reset_response (configNr,
1060                                              (rndis_reset_msg_type *) buf);
1061
1062         case REMOTE_NDIS_KEEPALIVE_MSG:
1063                 /* For USB: host does this every 5 seconds */
1064                 DEBUG(KERN_INFO "%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
1065                         __FUNCTION__ );
1066                 return rndis_keepalive_response (configNr,
1067                                                  (rndis_keepalive_msg_type *) 
1068                                                  buf);
1069                 
1070         default: 
1071                 printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n", 
1072                         __FUNCTION__ , MsgType);
1073                 break;
1074         }
1075         
1076         return -ENOTSUPP;
1077 }
1078
1079 int rndis_register (int (* rndis_control_ack) (struct net_device *))
1080 {
1081         u8 i;
1082         DEBUG("%s: ", __FUNCTION__ );
1083         
1084         for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1085                 if (!rndis_per_dev_params [i].used) {
1086                         rndis_per_dev_params [i].used = 1;
1087                         rndis_per_dev_params [i].ack = rndis_control_ack;
1088                         DEBUG("configNr = %d\n", i);
1089                         return i;
1090                 }
1091         }
1092         DEBUG("failed\n");
1093         
1094         return -1;
1095 }
1096
1097 void rndis_deregister (int configNr)
1098 {
1099         DEBUG("%s: \n", __FUNCTION__ );
1100         
1101         if (configNr >= RNDIS_MAX_CONFIGS) return;
1102         rndis_per_dev_params [configNr].used = 0;
1103         
1104         return;
1105 }
1106
1107 int rndis_set_param_dev (u8 configNr, struct net_device *dev, 
1108                          struct net_device_stats *stats)
1109 {
1110         DEBUG("%s:\n", __FUNCTION__ );
1111         if (!dev || !stats) return -1;
1112         if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1113         
1114         rndis_per_dev_params [configNr].dev = dev;
1115         rndis_per_dev_params [configNr].stats = stats;
1116         
1117         return 0;
1118 }
1119
1120 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
1121 {
1122         DEBUG("%s:\n", __FUNCTION__ );
1123         if (!vendorDescr) return -1;
1124         if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1125         
1126         rndis_per_dev_params [configNr].vendorID = vendorID;
1127         rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
1128         
1129         return 0;
1130 }
1131
1132 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
1133 {
1134         DEBUG("%s:\n", __FUNCTION__ );
1135         if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1136         
1137         rndis_per_dev_params [configNr].medium = medium;
1138         rndis_per_dev_params [configNr].speed = speed;
1139         
1140         return 0;
1141 }
1142
1143 void rndis_add_hdr (struct sk_buff *skb)
1144 {
1145         if (!skb) return;
1146         skb_push (skb, sizeof (struct rndis_packet_msg_type));
1147         memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
1148         *((u32 *) skb->data) = 1;
1149         *((u32 *) skb->data + 1) = skb->len;
1150         *((u32 *) skb->data + 2) = 36;
1151         *((u32 *) skb->data + 3) = skb->len - 44;
1152         
1153         return;
1154 }
1155
1156 void rndis_free_response (int configNr, u8 *buf)
1157 {
1158         rndis_resp_t            *r;
1159         struct list_head        *act, *tmp;
1160         
1161         list_for_each_safe (act, tmp, 
1162                             &(rndis_per_dev_params [configNr].resp_queue))
1163         {
1164                 r = list_entry (act, rndis_resp_t, list);
1165                 if (r && r->buf == buf) {
1166                         list_del (&r->list);
1167                         kfree (r);
1168                 }
1169         }
1170 }
1171
1172 u8 *rndis_get_next_response (int configNr, u32 *length)
1173 {
1174         rndis_resp_t            *r;
1175         struct list_head        *act, *tmp;
1176         
1177         if (!length) return NULL;
1178         
1179         list_for_each_safe (act, tmp, 
1180                             &(rndis_per_dev_params [configNr].resp_queue))
1181         {
1182                 r = list_entry (act, rndis_resp_t, list);
1183                 if (!r->send) {
1184                         r->send = 1;
1185                         *length = r->length;
1186                         return r->buf;
1187                 }
1188         }
1189         
1190         return NULL;
1191 }
1192
1193 static rndis_resp_t *rndis_add_response (int configNr, u32 length)
1194 {
1195         rndis_resp_t    *r;
1196         
1197         r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
1198         if (!r) return NULL;
1199         
1200         r->buf = (u8 *) (r + 1);
1201         r->length = length;
1202         r->send = 0;
1203         
1204         list_add_tail (&r->list, 
1205                        &(rndis_per_dev_params [configNr].resp_queue));
1206         return r;
1207 }
1208
1209 int rndis_rm_hdr (u8 *buf, u32 *length)
1210 {
1211         u32 i, messageLen, dataOffset;
1212         
1213         if (!buf || !length) return -1;
1214         if (*((u32 *) buf) != 1) return -1;
1215         
1216         messageLen = *((u32 *) buf + 1);
1217         
1218         dataOffset = *((u32 *) buf + 2) + 8;
1219         if (messageLen < dataOffset || messageLen > *length) return -1;
1220         
1221         for (i = dataOffset; i < messageLen; i++)
1222                 buf [i - dataOffset] = buf [i];
1223                 
1224         *length = messageLen - dataOffset;
1225         
1226         return 0;
1227 }
1228
1229 int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, 
1230                      void *data)
1231 {
1232         char *out = page;
1233         int len;
1234         rndis_params *param = (rndis_params *) data;
1235         
1236         out += snprintf (out, count, 
1237                          "Config Nr. %d\n"
1238                          "used      : %s\n"
1239                          "state     : %s\n"
1240                          "medium    : 0x%08X\n"
1241                          "speed     : %d\n"
1242                          "cable     : %s\n"
1243                          "vendor ID : 0x%08X\n"
1244                          "vendor    : %s\n", 
1245                          param->confignr, (param->used) ? "y" : "n", 
1246                          ({ char *s = "?";
1247                          switch (param->state) {
1248                          case RNDIS_UNINITIALIZED:
1249                                 s = "RNDIS_UNINITIALIZED"; break;
1250                          case RNDIS_INITIALIZED:
1251                                 s = "RNDIS_INITIALIZED"; break;
1252                          case RNDIS_DATA_INITIALIZED:
1253                                 s = "RNDIS_DATA_INITIALIZED"; break;
1254                         }; s; }),
1255                          param->medium, 
1256                          (param->media_state) ? 0 : param->speed*100, 
1257                          (param->media_state) ? "disconnected" : "connected",
1258                          param->vendorID, param->vendorDescr);      
1259         
1260         len = out - page;
1261         len -= off;
1262         
1263         if (len < count) {
1264                 *eof = 1;
1265                 if (len <= 0)
1266                         return 0;
1267         } else
1268                 len = count;
1269         
1270         *start = page + off;
1271         return len;
1272 }
1273
1274 int rndis_proc_write (struct file *file, const char *buffer, 
1275                       unsigned long count, void *data)
1276 {
1277         u32 speed = 0;
1278         int i, fl_speed = 0;
1279         
1280         for (i = 0; i < count; i++) {
1281                 switch (*buffer) {
1282                 case '0':
1283                 case '1':
1284                 case '2':
1285                 case '3':
1286                 case '4':
1287                 case '5':
1288                 case '6':
1289                 case '7':
1290                 case '8':
1291                 case '9':
1292                         fl_speed = 1;
1293                         speed = speed*10 + *buffer - '0';
1294                         break;
1295                 case 'C':
1296                 case 'c':
1297                         rndis_signal_connect (((rndis_params *) data)
1298                                 ->confignr);
1299                         break;
1300                 case 'D':
1301                 case 'd':
1302                         rndis_signal_disconnect (((rndis_params *) data)
1303                                 ->confignr);
1304                         break;
1305                 default: 
1306                         if (fl_speed) ((rndis_params *) data)->speed = speed;
1307                         else DEBUG ("%c is not valid\n", *buffer);
1308                         break;
1309                 }
1310                 
1311                 buffer++;
1312         }
1313         
1314         return count;
1315 }
1316
1317 int __init rndis_init (void)
1318 {
1319         u8 i;
1320         char name [4];
1321
1322         /* FIXME this should probably be /proc/driver/rndis,
1323          * and only if debugging is enabled
1324          */
1325         
1326         if (!(rndis_connect_dir =  proc_mkdir ("rndis", NULL))) {
1327                 printk (KERN_ERR "%s: couldn't create /proc/rndis entry", 
1328                         __FUNCTION__);
1329                 return -EIO;
1330         }
1331         
1332         for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1333                 sprintf (name, "%03d", i);
1334                 if (!(rndis_connect_state [i]
1335                                 = create_proc_entry (name, 0660,
1336                                                 rndis_connect_dir))) 
1337                 {
1338                         DEBUG ("%s :remove entries", __FUNCTION__);
1339                         for (i--; i > 0; i--) {
1340                                 sprintf (name, "%03d", i);
1341                                 remove_proc_entry (name, rndis_connect_dir);
1342                         }
1343                         DEBUG ("\n");
1344                         
1345                         remove_proc_entry ("000", rndis_connect_dir);
1346                         remove_proc_entry ("rndis", NULL);
1347                         return -EIO;
1348                 }
1349                 rndis_connect_state [i]->nlink = 1;
1350                 rndis_connect_state [i]->write_proc = rndis_proc_write;
1351                 rndis_connect_state [i]->read_proc = rndis_proc_read;
1352                 rndis_connect_state [i]->data = (void *)
1353                                 (rndis_per_dev_params + i);
1354                 rndis_per_dev_params [i].confignr = i;
1355                 rndis_per_dev_params [i].used = 0;
1356                 rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
1357                 rndis_per_dev_params [i].media_state
1358                                 = NDIS_MEDIA_STATE_DISCONNECTED;
1359                 INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
1360         }
1361         
1362         return 0;
1363 }
1364
1365 void rndis_exit (void)
1366 {
1367         u8 i;
1368         char name [4];
1369         
1370         for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1371                 sprintf (name, "%03d", i);
1372                 remove_proc_entry (name, rndis_connect_dir);
1373         }
1374         remove_proc_entry ("rndis", NULL);
1375         return;
1376 }
1377