4 * Version: $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
6 * Authors: Benedikt Spranger, Pengutronix
7 * Robert Schwebel, Pengutronix
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.
13 * This software was originally developed in conformance with
14 * Microsoft's Remote NDIS Specification License Agreement.
16 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
17 * Fixed message length bug in init_response
19 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
20 * Fixed rndis_rm_hdr length bug.
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>
35 #include <asm/byteorder.h>
36 #include <asm/system.h>
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.
44 * Windows hosts need an INF file like Documentation/usb/linux.inf
47 #ifndef __LITTLE_ENDIAN
48 #warning this code is missing all cpu_to_leXX() calls ...
52 #define DEBUG if (rndis_debug) printk
53 static int rndis_debug = 0;
55 module_param (rndis_debug, bool, 0);
56 MODULE_PARM_DESC (rndis_debug, "enable debugging");
59 #define DEBUG(str,args...) do{}while(0)
62 #define RNDIS_MAX_CONFIGS 1
64 static struct proc_dir_entry *rndis_connect_dir;
65 static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
67 static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
70 static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
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);
80 static rndis_resp_t *rndis_add_response (int configNr, u32 length);
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, ...)
88 static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
90 int retval = -ENOTSUPP;
92 rndis_query_cmplt_type *resp;
94 if (!r) return -ENOMEM;
95 resp = (rndis_query_cmplt_type *) r->buf;
97 if (!resp) return -ENOMEM;
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);
109 case OID_GEN_HARDWARE_STATUS:
110 DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
113 * Hardware must be ready to recieve high level protocols.
115 * reddite ergo quae sunt Caesaris Caesari
116 * et quae sunt Dei Deo!
118 *((u32 *) resp + 6) = 0;
123 case OID_GEN_MEDIA_SUPPORTED:
124 DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
126 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
131 case OID_GEN_MEDIA_IN_USE:
132 DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
134 /* one medium, one transport... (maybe you do it better) */
135 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].medium;
139 case OID_GEN_MAXIMUM_LOOKAHEAD:
140 DEBUG("%s: OID_GEN_MAXIMUM_LOOKAHEAD\n", __FUNCTION__);
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) {
148 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
152 *((u32 *) resp + 6) = 0;
158 case OID_GEN_LINK_SPEED:
159 DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
161 if (rndis_per_dev_params [configNr].media_state
162 == NDIS_MEDIA_STATE_DISCONNECTED)
163 *((u32 *) resp + 6) = 0;
165 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].speed;
169 case OID_GEN_TRANSMIT_BUFFER_SPACE:
170 DEBUG("%s: OID_GEN_TRANSMIT_BUFFER_SPACE\n", __FUNCTION__);
172 *((u32 *) resp + 6) = 0;
176 case OID_GEN_RECEIVE_BUFFER_SPACE:
177 DEBUG("%s: OID_GEN_RECEIVE_BUFFER_SPACE\n", __FUNCTION__);
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) {
185 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
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) {
196 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
203 case OID_GEN_VENDOR_ID:
204 DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
206 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].vendorID;
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);
220 case OID_GEN_CURRENT_PACKET_FILTER:
221 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
223 *((u32 *) resp + 6) = rndis_per_dev_params[configNr].filter;
227 case OID_GEN_CURRENT_LOOKAHEAD:
228 DEBUG("%s: OID_GEN_CURRENT_LOOKAHEAD\n", __FUNCTION__);
231 case OID_GEN_DRIVER_VERSION:
232 DEBUG("%s: OID_GEN_DRIVER_VERSION\n", __FUNCTION__);
236 case OID_GEN_MAXIMUM_TOTAL_SIZE:
237 DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
239 *((u32 *) resp + 6) = RNDIS_MAX_TOTAL_SIZE;
243 case OID_GEN_PROTOCOL_OPTIONS:
244 DEBUG("%s: OID_GEN_PROTOCOL_OPTIONS\n", __FUNCTION__);
247 case OID_GEN_MAC_OPTIONS:
248 DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
250 *((u32 *) resp + 6) = NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
251 NDIS_MAC_OPTION_FULL_DUPLEX;
256 case OID_GEN_MEDIA_CONNECT_STATUS:
257 DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
259 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
264 case OID_GEN_MAXIMUM_SEND_PACKETS:
265 DEBUG("%s: OID_GEN_MAXIMUM_SEND_PACKETS\n", __FUNCTION__);
269 case OID_GEN_VENDOR_DRIVER_VERSION:
270 DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
272 *((u32 *) resp + 6) = rndis_driver_version;
276 case OID_GEN_SUPPORTED_GUIDS:
277 DEBUG("%s: OID_GEN_SUPPORTED_GUIDS\n", __FUNCTION__);
280 case OID_GEN_NETWORK_LAYER_ADDRESSES:
281 DEBUG("%s: OID_GEN_NETWORK_LAYER_ADDRESSES\n", __FUNCTION__);
284 case OID_GEN_TRANSPORT_HEADER_OFFSET:
285 DEBUG("%s: OID_GEN_TRANSPORT_HEADER_OFFSET\n", __FUNCTION__);
288 case OID_GEN_MACHINE_NAME:
289 DEBUG("%s: OID_GEN_MACHINE_NAME\n", __FUNCTION__);
292 case OID_GEN_RNDIS_CONFIG_PARAMETER:
293 DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
295 *((u32 *) resp + 6) = 0;
299 case OID_GEN_VLAN_ID:
300 DEBUG("%s: OID_GEN_VLAN_ID\n", __FUNCTION__);
303 case OID_GEN_MEDIA_CAPABILITIES:
304 DEBUG("%s: OID_GEN_MEDIA_CAPABILITIES\n", __FUNCTION__);
307 case OID_GEN_PHYSICAL_MEDIUM:
308 DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
310 *((u32 *) resp + 6) = 0;
315 case OID_GEN_XMIT_OK:
316 DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
317 if (rndis_per_dev_params [configNr].stats) {
319 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
321 rndis_per_dev_params [configNr].stats->tx_errors -
322 rndis_per_dev_params [configNr].stats->tx_dropped;
325 *((u32 *) resp + 6) = 0;
332 DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
333 if (rndis_per_dev_params [configNr].stats) {
335 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
337 rndis_per_dev_params [configNr].stats->rx_errors -
338 rndis_per_dev_params [configNr].stats->rx_dropped;
341 *((u32 *) resp + 6) = 0;
347 case OID_GEN_XMIT_ERROR:
348 DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
349 if (rndis_per_dev_params [configNr].stats) {
351 *((u32 *) resp + 6) = rndis_per_dev_params [configNr].
355 *((u32 *) resp + 6) = 0;
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].
368 *((u32 *) resp + 6) = 0;
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].
381 *((u32 *) resp + 6) = 0;
386 case OID_GEN_DIRECTED_BYTES_XMIT:
387 DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
389 * Aunt Tilly's size of shoes
390 * minus antarctica count of penguins
391 * divided by weight of Alpha Centauri
393 if (rndis_per_dev_params [configNr].stats) {
395 *((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
397 rndis_per_dev_params [configNr].stats->tx_errors -
398 rndis_per_dev_params [configNr].stats->tx_dropped)
402 *((u32 *) resp + 6) = 0;
407 case OID_GEN_DIRECTED_FRAMES_XMIT:
408 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
410 if (rndis_per_dev_params [configNr].stats) {
412 *((u32 *) resp + 6) = (rndis_per_dev_params [configNr].
414 rndis_per_dev_params [configNr].stats->tx_errors -
415 rndis_per_dev_params [configNr].stats->tx_dropped)
419 *((u32 *) resp + 6) = 0;
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;
431 *((u32 *) resp + 6) = 0;
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].
443 *((u32 *) resp + 6) = 0;
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;
455 *((u32 *) resp + 6) = 0;
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;
467 *((u32 *) resp + 6) = 0;
472 case OID_GEN_DIRECTED_BYTES_RCV:
473 DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
474 *((u32 *) resp + 6) = 0;
478 case OID_GEN_DIRECTED_FRAMES_RCV:
479 DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
480 *((u32 *) resp + 6) = 0;
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;
491 *((u32 *) resp + 6) = 0;
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].
503 *((u32 *) resp + 6) = 0;
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;
515 *((u32 *) resp + 6) = 0;
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;
527 *((u32 *) resp + 6) = 0;
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;
539 *((u32 *) resp + 6) = 0;
544 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
545 DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
546 *((u32 *) resp + 6) = 0;
550 case OID_GEN_GET_TIME_CAPS:
551 DEBUG("%s: OID_GEN_GET_TIME_CAPS\n", __FUNCTION__);
554 case OID_GEN_GET_NETCARD_TIME:
555 DEBUG("%s: OID_GEN_GET_NETCARD_TIME\n", __FUNCTION__);
558 case OID_GEN_NETCARD_LOAD:
559 DEBUG("%s: OID_GEN_NETCARD_LOAD\n", __FUNCTION__);
562 case OID_GEN_DEVICE_PROFILE:
563 DEBUG("%s: OID_GEN_DEVICE_PROFILE\n", __FUNCTION__);
566 case OID_GEN_INIT_TIME_MS:
567 DEBUG("%s: OID_GEN_INIT_TIME_MS\n", __FUNCTION__);
570 case OID_GEN_RESET_COUNTS:
571 DEBUG("%s: OID_GEN_RESET_COUNTS\n", __FUNCTION__);
574 case OID_GEN_MEDIA_SENSE_COUNTS:
575 DEBUG("%s: OID_GEN_MEDIA_SENSE_COUNTS\n", __FUNCTION__);
578 case OID_GEN_FRIENDLY_NAME:
579 DEBUG("%s: OID_GEN_FRIENDLY_NAME\n", __FUNCTION__);
582 case OID_GEN_MINIPORT_INFO:
583 DEBUG("%s: OID_GEN_MINIPORT_INFO\n", __FUNCTION__);
586 case OID_GEN_RESET_VERIFY_PARAMETERS:
587 DEBUG("%s: OID_GEN_RESET_VERIFY_PARAMETERS\n", __FUNCTION__);
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) {
595 memcpy ((u8 *) resp + 24,
596 rndis_per_dev_params [configNr].host_mac,
600 *((u32 *) resp + 6) = 0;
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) {
610 memcpy ((u8 *) resp + 24,
611 rndis_per_dev_params [configNr].host_mac,
618 case OID_802_3_MULTICAST_LIST:
619 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
621 /* Multicast base address only */
622 *((u32 *) resp + 6) = 0xE0000000;
627 case OID_802_3_MAXIMUM_LIST_SIZE:
628 DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
630 /* Multicast base address only */
631 *((u32 *) resp + 6) = 1;
635 case OID_802_3_MAC_OPTIONS:
636 DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
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)
645 *((u32 *) resp + 6) = rndis_per_dev_params [configNr]
646 .stats->rx_frame_errors;
652 case OID_802_3_XMIT_ONE_COLLISION:
653 DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
655 *((u32 *) resp + 6) = 0;
660 case OID_802_3_XMIT_MORE_COLLISIONS:
661 DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
663 *((u32 *) resp + 6) = 0;
667 case OID_802_3_XMIT_DEFERRED:
668 DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
672 case OID_802_3_XMIT_MAX_COLLISIONS:
673 DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
677 case OID_802_3_RCV_OVERRUN:
678 DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
682 case OID_802_3_XMIT_UNDERRUN:
683 DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
687 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
688 DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
692 case OID_802_3_XMIT_TIMES_CRS_LOST:
693 DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
697 case OID_802_3_XMIT_LATE_COLLISIONS:
698 DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
702 default: printk (KERN_ERR "%s: unknown OID 0x%08X\n",
706 resp->InformationBufferOffset = 16;
707 resp->InformationBufferLength = length;
708 resp->MessageLength = 24 + length;
709 r->length = 24 + length;
713 static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
716 rndis_set_cmplt_type *resp;
717 int i, retval = -ENOTSUPP;
718 struct rndis_config_parameter *param;
719 struct rndis_params *params;
724 resp = (rndis_set_cmplt_type *) r->buf;
731 case OID_GEN_CURRENT_PACKET_FILTER:
732 params = &rndis_per_dev_params [configNr];
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
741 params->filter = *(u32 *)buf;
742 DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
743 __FUNCTION__, params->filter);
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.
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);
755 params->state = RNDIS_INITIALIZED;
756 netif_carrier_off (params->dev);
757 netif_stop_queue (params->dev);
761 case OID_802_3_MULTICAST_LIST:
762 /* I think we can ignore this */
763 DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
767 case OID_GEN_RNDIS_CONFIG_PARAMETER:
768 DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER\n", __FUNCTION__);
769 param = (struct rndis_config_parameter *) buf;
771 for (i = 0; i < param->ParameterNameLength; i++) {
773 *(buf + param->ParameterNameOffset + i));
781 default: printk (KERN_ERR "%s: unknown OID 0x%08X\n",
792 static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
794 rndis_init_cmplt_type *resp;
797 if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
799 r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
801 if (!r) return -ENOMEM;
803 resp = (rndis_init_cmplt_type *) r->buf;
805 if (!resp) return -ENOMEM;
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)
820 resp->PacketAlignmentFactor = 0;
821 resp->AFListOffset = 0;
822 resp->AFListSize = 0;
824 if (rndis_per_dev_params [configNr].ack)
825 rndis_per_dev_params [configNr].ack (
826 rndis_per_dev_params [configNr].dev);
831 static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
833 rndis_query_cmplt_type *resp;
836 DEBUG("%s: OID = %08X\n", __FUNCTION__, buf->OID);
837 if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
840 * we need more memory:
841 * oid_supported_list is the largest answer
843 r = rndis_add_response (configNr, sizeof (oid_supported_list));
845 if (!r) return -ENOMEM;
846 resp = (rndis_query_cmplt_type *) r->buf;
848 if (!resp) return -ENOMEM;
850 resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
851 resp->MessageLength = 24;
852 resp->RequestID = buf->RequestID;
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;
860 resp->Status = RNDIS_STATUS_SUCCESS;
862 if (rndis_per_dev_params [configNr].ack)
863 rndis_per_dev_params [configNr].ack (
864 rndis_per_dev_params [configNr].dev);
868 static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
870 rndis_set_cmplt_type *resp;
874 r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
876 if (!r) return -ENOMEM;
877 resp = (rndis_set_cmplt_type *) r->buf;
878 if (!resp) return -ENOMEM;
880 DEBUG("%s: Length: %d\n", __FUNCTION__, buf->InformationBufferLength);
881 DEBUG("%s: Offset: %d\n", __FUNCTION__, buf->InformationBufferOffset);
882 DEBUG("%s: InfoBuffer: ", __FUNCTION__);
884 for (i = 0; i < buf->InformationBufferLength; i++) {
885 DEBUG ("%02x ", *(((u8 *) buf) + i + 12 +
886 buf->InformationBufferOffset));
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,
896 buf->InformationBufferLength, r))
897 resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
898 else resp->Status = RNDIS_STATUS_SUCCESS;
900 if (rndis_per_dev_params [configNr].ack)
901 rndis_per_dev_params [configNr].ack (rndis_per_dev_params [configNr].dev);
906 static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
908 rndis_reset_cmplt_type *resp;
911 r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
913 if (!r) return -ENOMEM;
914 resp = (rndis_reset_cmplt_type *) r->buf;
915 if (!resp) return -ENOMEM;
917 resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
918 resp->MessageLength = 16;
919 resp->Status = RNDIS_STATUS_SUCCESS;
920 resp->AddressingReset = 1; /* resent information */
922 if (rndis_per_dev_params [configNr].ack)
923 rndis_per_dev_params [configNr].ack (
924 rndis_per_dev_params [configNr].dev);
929 static int rndis_keepalive_response (int configNr,
930 rndis_keepalive_msg_type *buf)
932 rndis_keepalive_cmplt_type *resp;
935 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
937 r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
938 resp = (rndis_keepalive_cmplt_type *) r->buf;
939 if (!resp) return -ENOMEM;
941 resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
942 resp->MessageLength = 16;
943 resp->RequestID = buf->RequestID;
944 resp->Status = RNDIS_STATUS_SUCCESS;
946 if (rndis_per_dev_params [configNr].ack)
947 rndis_per_dev_params [configNr].ack (
948 rndis_per_dev_params [configNr].dev);
955 * Device to Host Comunication
957 static int rndis_indicate_status_msg (int configNr, u32 status)
959 rndis_indicate_status_msg_type *resp;
962 if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
965 r = rndis_add_response (configNr,
966 sizeof (rndis_indicate_status_msg_type));
967 if (!r) return -ENOMEM;
969 resp = (rndis_indicate_status_msg_type *) r->buf;
970 if (!resp) return -ENOMEM;
972 resp->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
973 resp->MessageLength = 20;
974 resp->Status = status;
975 resp->StatusBufferLength = 0;
976 resp->StatusBufferOffset = 0;
978 if (rndis_per_dev_params [configNr].ack)
979 rndis_per_dev_params [configNr].ack (
980 rndis_per_dev_params [configNr].dev);
984 int rndis_signal_connect (int configNr)
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);
992 int rndis_signal_disconnect (int configNr)
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);
1000 void rndis_set_host_mac (int configNr, const u8 *addr)
1002 rndis_per_dev_params [configNr].host_mac = addr;
1008 int rndis_msg_parser (u8 configNr, u8 *buf)
1010 u32 MsgType, MsgLength, *tmp;
1011 struct rndis_params *params;
1018 MsgLength = *(tmp + 1);
1020 if (configNr >= RNDIS_MAX_CONFIGS)
1022 params = &rndis_per_dev_params [configNr];
1024 /* For USB: responses may take up to 10 seconds */
1027 case REMOTE_NDIS_INITIALIZE_MSG:
1028 DEBUG(KERN_INFO "%s: REMOTE_NDIS_INITIALIZE_MSG\n",
1030 params->state = RNDIS_INITIALIZED;
1031 return rndis_init_response (configNr,
1032 (rndis_init_msg_type *) buf);
1034 case REMOTE_NDIS_HALT_MSG:
1035 DEBUG(KERN_INFO "%s: REMOTE_NDIS_HALT_MSG\n",
1037 params->state = RNDIS_UNINITIALIZED;
1039 netif_carrier_off (params->dev);
1040 netif_stop_queue (params->dev);
1044 case REMOTE_NDIS_QUERY_MSG:
1045 DEBUG(KERN_INFO "%s: REMOTE_NDIS_QUERY_MSG\n",
1047 return rndis_query_response (configNr,
1048 (rndis_query_msg_type *) buf);
1050 case REMOTE_NDIS_SET_MSG:
1051 DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n",
1053 return rndis_set_response (configNr,
1054 (rndis_set_msg_type *) buf);
1056 case REMOTE_NDIS_RESET_MSG:
1057 DEBUG(KERN_INFO "%s: REMOTE_NDIS_RESET_MSG\n",
1059 return rndis_reset_response (configNr,
1060 (rndis_reset_msg_type *) buf);
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",
1066 return rndis_keepalive_response (configNr,
1067 (rndis_keepalive_msg_type *)
1071 printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n",
1072 __FUNCTION__ , MsgType);
1079 int rndis_register (int (* rndis_control_ack) (struct net_device *))
1082 DEBUG("%s: ", __FUNCTION__ );
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);
1097 void rndis_deregister (int configNr)
1099 DEBUG("%s: \n", __FUNCTION__ );
1101 if (configNr >= RNDIS_MAX_CONFIGS) return;
1102 rndis_per_dev_params [configNr].used = 0;
1107 int rndis_set_param_dev (u8 configNr, struct net_device *dev,
1108 struct net_device_stats *stats)
1110 DEBUG("%s:\n", __FUNCTION__ );
1111 if (!dev || !stats) return -1;
1112 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1114 rndis_per_dev_params [configNr].dev = dev;
1115 rndis_per_dev_params [configNr].stats = stats;
1120 int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
1122 DEBUG("%s:\n", __FUNCTION__ );
1123 if (!vendorDescr) return -1;
1124 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1126 rndis_per_dev_params [configNr].vendorID = vendorID;
1127 rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
1132 int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
1134 DEBUG("%s:\n", __FUNCTION__ );
1135 if (configNr >= RNDIS_MAX_CONFIGS) return -1;
1137 rndis_per_dev_params [configNr].medium = medium;
1138 rndis_per_dev_params [configNr].speed = speed;
1143 void rndis_add_hdr (struct sk_buff *skb)
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;
1156 void rndis_free_response (int configNr, u8 *buf)
1159 struct list_head *act, *tmp;
1161 list_for_each_safe (act, tmp,
1162 &(rndis_per_dev_params [configNr].resp_queue))
1164 r = list_entry (act, rndis_resp_t, list);
1165 if (r && r->buf == buf) {
1166 list_del (&r->list);
1172 u8 *rndis_get_next_response (int configNr, u32 *length)
1175 struct list_head *act, *tmp;
1177 if (!length) return NULL;
1179 list_for_each_safe (act, tmp,
1180 &(rndis_per_dev_params [configNr].resp_queue))
1182 r = list_entry (act, rndis_resp_t, list);
1185 *length = r->length;
1193 static rndis_resp_t *rndis_add_response (int configNr, u32 length)
1197 r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
1198 if (!r) return NULL;
1200 r->buf = (u8 *) (r + 1);
1204 list_add_tail (&r->list,
1205 &(rndis_per_dev_params [configNr].resp_queue));
1209 int rndis_rm_hdr (u8 *buf, u32 *length)
1211 u32 i, messageLen, dataOffset;
1213 if (!buf || !length) return -1;
1214 if (*((u32 *) buf) != 1) return -1;
1216 messageLen = *((u32 *) buf + 1);
1218 dataOffset = *((u32 *) buf + 2) + 8;
1219 if (messageLen < dataOffset || messageLen > *length) return -1;
1221 for (i = dataOffset; i < messageLen; i++)
1222 buf [i - dataOffset] = buf [i];
1224 *length = messageLen - dataOffset;
1229 int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
1234 rndis_params *param = (rndis_params *) data;
1236 out += snprintf (out, count,
1243 "vendor ID : 0x%08X\n"
1245 param->confignr, (param->used) ? "y" : "n",
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;
1256 (param->media_state) ? 0 : param->speed*100,
1257 (param->media_state) ? "disconnected" : "connected",
1258 param->vendorID, param->vendorDescr);
1270 *start = page + off;
1274 int rndis_proc_write (struct file *file, const char *buffer,
1275 unsigned long count, void *data)
1278 int i, fl_speed = 0;
1280 for (i = 0; i < count; i++) {
1293 speed = speed*10 + *buffer - '0';
1297 rndis_signal_connect (((rndis_params *) data)
1302 rndis_signal_disconnect (((rndis_params *) data)
1306 if (fl_speed) ((rndis_params *) data)->speed = speed;
1307 else DEBUG ("%c is not valid\n", *buffer);
1317 int __init rndis_init (void)
1322 /* FIXME this should probably be /proc/driver/rndis,
1323 * and only if debugging is enabled
1326 if (!(rndis_connect_dir = proc_mkdir ("rndis", NULL))) {
1327 printk (KERN_ERR "%s: couldn't create /proc/rndis entry",
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)))
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);
1345 remove_proc_entry ("000", rndis_connect_dir);
1346 remove_proc_entry ("rndis", NULL);
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));
1365 void rndis_exit (void)
1370 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1371 sprintf (name, "%03d", i);
1372 remove_proc_entry (name, rndis_connect_dir);
1374 remove_proc_entry ("rndis", NULL);