4 * Authors: Benedikt Spranger, Pengutronix
5 * Robert Schwebel, Pengutronix
7 * This software was originally developed in conformance with
8 * Microsoft's Remote NDIS Specification License Agreement.
10 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
11 * Fixed message length bug in init_response
13 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
14 * Fixed rndis_rm_hdr length bug.
16 * Copyright (C) 2004 by David Brownell
17 * updates to merge with Linux 2.6, better match RNDIS spec
19 * SPDX-License-Identifier: GPL-2.0
25 #include <linux/types.h>
26 #include <linux/list.h>
27 #include <linux/netdevice.h>
29 #include <asm/byteorder.h>
30 #include <asm/unaligned.h>
31 #include <linux/errno.h>
39 #define ETH_ALEN 6 /* Octets in one ethernet addr */
40 #define ETH_HLEN 14 /* Total octets in header. */
41 #define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
42 #define ETH_DATA_LEN 1500 /* Max. octets in payload */
43 #define ETH_FRAME_LEN PKTSIZE_ALIGN /* Max. octets in frame sans FCS */
46 * The driver for your USB chip needs to support ep0 OUT to work with
47 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
49 * Windows hosts need an INF file like Documentation/usb/linux.inf
50 * and will be happier if you provide the host_addr module parameter.
53 #define RNDIS_MAX_CONFIGS 1
55 static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
58 static const __le32 rndis_driver_version = __constant_cpu_to_le32(1);
60 /* Function Prototypes */
61 static rndis_resp_t *rndis_add_response(int configNr, u32 length);
65 static const u32 oid_supported_list[] = {
66 /* the general stuff */
67 OID_GEN_SUPPORTED_LIST,
68 OID_GEN_HARDWARE_STATUS,
69 OID_GEN_MEDIA_SUPPORTED,
71 OID_GEN_MAXIMUM_FRAME_SIZE,
73 OID_GEN_TRANSMIT_BLOCK_SIZE,
74 OID_GEN_RECEIVE_BLOCK_SIZE,
76 OID_GEN_VENDOR_DESCRIPTION,
77 OID_GEN_VENDOR_DRIVER_VERSION,
78 OID_GEN_CURRENT_PACKET_FILTER,
79 OID_GEN_MAXIMUM_TOTAL_SIZE,
80 OID_GEN_MEDIA_CONNECT_STATUS,
81 OID_GEN_PHYSICAL_MEDIUM,
83 OID_GEN_RNDIS_CONFIG_PARAMETER,
86 /* the statistical stuff */
91 OID_GEN_RCV_NO_BUFFER,
92 #ifdef RNDIS_OPTIONAL_STATS
93 OID_GEN_DIRECTED_BYTES_XMIT,
94 OID_GEN_DIRECTED_FRAMES_XMIT,
95 OID_GEN_MULTICAST_BYTES_XMIT,
96 OID_GEN_MULTICAST_FRAMES_XMIT,
97 OID_GEN_BROADCAST_BYTES_XMIT,
98 OID_GEN_BROADCAST_FRAMES_XMIT,
99 OID_GEN_DIRECTED_BYTES_RCV,
100 OID_GEN_DIRECTED_FRAMES_RCV,
101 OID_GEN_MULTICAST_BYTES_RCV,
102 OID_GEN_MULTICAST_FRAMES_RCV,
103 OID_GEN_BROADCAST_BYTES_RCV,
104 OID_GEN_BROADCAST_FRAMES_RCV,
105 OID_GEN_RCV_CRC_ERROR,
106 OID_GEN_TRANSMIT_QUEUE_LENGTH,
107 #endif /* RNDIS_OPTIONAL_STATS */
109 /* mandatory 802.3 */
110 /* the general stuff */
111 OID_802_3_PERMANENT_ADDRESS,
112 OID_802_3_CURRENT_ADDRESS,
113 OID_802_3_MULTICAST_LIST,
114 OID_802_3_MAC_OPTIONS,
115 OID_802_3_MAXIMUM_LIST_SIZE,
117 /* the statistical stuff */
118 OID_802_3_RCV_ERROR_ALIGNMENT,
119 OID_802_3_XMIT_ONE_COLLISION,
120 OID_802_3_XMIT_MORE_COLLISIONS,
121 #ifdef RNDIS_OPTIONAL_STATS
122 OID_802_3_XMIT_DEFERRED,
123 OID_802_3_XMIT_MAX_COLLISIONS,
124 OID_802_3_RCV_OVERRUN,
125 OID_802_3_XMIT_UNDERRUN,
126 OID_802_3_XMIT_HEARTBEAT_FAILURE,
127 OID_802_3_XMIT_TIMES_CRS_LOST,
128 OID_802_3_XMIT_LATE_COLLISIONS,
129 #endif /* RNDIS_OPTIONAL_STATS */
132 /* PM and wakeup are mandatory for USB: */
134 /* power management */
135 OID_PNP_CAPABILITIES,
141 OID_PNP_ENABLE_WAKE_UP,
142 OID_PNP_ADD_WAKE_UP_PATTERN,
143 OID_PNP_REMOVE_WAKE_UP_PATTERN,
144 #endif /* RNDIS_WAKEUP */
145 #endif /* RNDIS_PM */
150 static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
151 unsigned buf_len, rndis_resp_t *r)
153 int retval = -ENOTSUPP;
154 u32 length = 4; /* usually */
157 rndis_query_cmplt_type *resp;
158 rndis_params *params;
162 resp = (rndis_query_cmplt_type *) r->buf;
167 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
169 debug("query OID %08x value, len %d:\n", OID, buf_len);
170 for (i = 0; i < buf_len; i += 16) {
171 debug("%03d: %08x %08x %08x %08x\n", i,
172 get_unaligned_le32(&buf[i]),
173 get_unaligned_le32(&buf[i + 4]),
174 get_unaligned_le32(&buf[i + 8]),
175 get_unaligned_le32(&buf[i + 12]));
180 /* response goes here, right after the header */
181 outbuf = (__le32 *) &resp[1];
182 resp->InformationBufferOffset = __constant_cpu_to_le32(16);
184 params = &rndis_per_dev_params[configNr];
187 /* general oids (table 4-1) */
190 case OID_GEN_SUPPORTED_LIST:
191 debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
192 length = sizeof(oid_supported_list);
193 count = length / sizeof(u32);
194 for (i = 0; i < count; i++)
195 outbuf[i] = cpu_to_le32(oid_supported_list[i]);
200 case OID_GEN_HARDWARE_STATUS:
201 debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
204 * Hardware must be ready to receive high level protocols.
206 * reddite ergo quae sunt Caesaris Caesari
207 * et quae sunt Dei Deo!
209 *outbuf = __constant_cpu_to_le32(0);
214 case OID_GEN_MEDIA_SUPPORTED:
215 debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
216 *outbuf = cpu_to_le32(params->medium);
221 case OID_GEN_MEDIA_IN_USE:
222 debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
223 /* one medium, one transport... (maybe you do it better) */
224 *outbuf = cpu_to_le32(params->medium);
229 case OID_GEN_MAXIMUM_FRAME_SIZE:
230 debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
232 *outbuf = cpu_to_le32(params->mtu);
238 case OID_GEN_LINK_SPEED:
239 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
240 debug("%s: OID_GEN_LINK_SPEED\n", __func__);
242 if (params->media_state == NDIS_MEDIA_STATE_DISCONNECTED)
243 *outbuf = __constant_cpu_to_le32(0);
245 *outbuf = cpu_to_le32(params->speed);
250 case OID_GEN_TRANSMIT_BLOCK_SIZE:
251 debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
253 *outbuf = cpu_to_le32(params->mtu);
259 case OID_GEN_RECEIVE_BLOCK_SIZE:
260 debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
262 *outbuf = cpu_to_le32(params->mtu);
268 case OID_GEN_VENDOR_ID:
269 debug("%s: OID_GEN_VENDOR_ID\n", __func__);
270 *outbuf = cpu_to_le32(params->vendorID);
275 case OID_GEN_VENDOR_DESCRIPTION:
276 debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
277 length = strlen(params->vendorDescr);
278 memcpy(outbuf, params->vendorDescr, length);
282 case OID_GEN_VENDOR_DRIVER_VERSION:
283 debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
285 *outbuf = rndis_driver_version;
290 case OID_GEN_CURRENT_PACKET_FILTER:
291 debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
292 *outbuf = cpu_to_le32(*params->filter);
297 case OID_GEN_MAXIMUM_TOTAL_SIZE:
298 debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
299 *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
304 case OID_GEN_MEDIA_CONNECT_STATUS:
305 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
306 debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
308 *outbuf = cpu_to_le32(params->media_state);
312 case OID_GEN_PHYSICAL_MEDIUM:
313 debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
314 *outbuf = __constant_cpu_to_le32(0);
319 * The RNDIS specification is incomplete/wrong. Some versions
320 * of MS-Windows expect OIDs that aren't specified there. Other
321 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
323 case OID_GEN_MAC_OPTIONS: /* from WinME */
324 debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
325 *outbuf = __constant_cpu_to_le32(
326 NDIS_MAC_OPTION_RECEIVE_SERIALIZED
327 | NDIS_MAC_OPTION_FULL_DUPLEX);
331 /* statistics OIDs (table 4-2) */
334 case OID_GEN_XMIT_OK:
335 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
336 debug("%s: OID_GEN_XMIT_OK\n", __func__);
339 *outbuf = cpu_to_le32(
340 params->stats->tx_packets -
341 params->stats->tx_errors -
342 params->stats->tx_dropped);
349 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
350 debug("%s: OID_GEN_RCV_OK\n", __func__);
353 *outbuf = cpu_to_le32(
354 params->stats->rx_packets -
355 params->stats->rx_errors -
356 params->stats->rx_dropped);
362 case OID_GEN_XMIT_ERROR:
363 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
364 debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
367 *outbuf = cpu_to_le32(params->stats->tx_errors);
373 case OID_GEN_RCV_ERROR:
374 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
375 debug("%s: OID_GEN_RCV_ERROR\n", __func__);
378 *outbuf = cpu_to_le32(params->stats->rx_errors);
384 case OID_GEN_RCV_NO_BUFFER:
385 debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
387 *outbuf = cpu_to_le32(params->stats->rx_dropped);
392 #ifdef RNDIS_OPTIONAL_STATS
393 case OID_GEN_DIRECTED_BYTES_XMIT:
394 debug("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
396 * Aunt Tilly's size of shoes
397 * minus antarctica count of penguins
398 * divided by weight of Alpha Centauri
401 *outbuf = cpu_to_le32(
402 (params->stats->tx_packets -
403 params->stats->tx_errors -
404 params->stats->tx_dropped)
410 case OID_GEN_DIRECTED_FRAMES_XMIT:
411 debug("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
414 *outbuf = cpu_to_le32(
415 (params->stats->tx_packets -
416 params->stats->tx_errors -
417 params->stats->tx_dropped)
423 case OID_GEN_MULTICAST_BYTES_XMIT:
424 debug("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
426 *outbuf = cpu_to_le32(params->stats->multicast * 1234);
431 case OID_GEN_MULTICAST_FRAMES_XMIT:
432 debug("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
434 *outbuf = cpu_to_le32(params->stats->multicast);
439 case OID_GEN_BROADCAST_BYTES_XMIT:
440 debug("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
442 *outbuf = cpu_to_le32(params->stats->tx_packets/42*255);
447 case OID_GEN_BROADCAST_FRAMES_XMIT:
448 debug("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
450 *outbuf = cpu_to_le32(params->stats->tx_packets / 42);
455 case OID_GEN_DIRECTED_BYTES_RCV:
456 debug("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
457 *outbuf = __constant_cpu_to_le32(0);
461 case OID_GEN_DIRECTED_FRAMES_RCV:
462 debug("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
463 *outbuf = __constant_cpu_to_le32(0);
467 case OID_GEN_MULTICAST_BYTES_RCV:
468 debug("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
470 *outbuf = cpu_to_le32(params->stats->multicast * 1111);
475 case OID_GEN_MULTICAST_FRAMES_RCV:
476 debug("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
478 *outbuf = cpu_to_le32(params->stats->multicast);
483 case OID_GEN_BROADCAST_BYTES_RCV:
484 debug("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
486 *outbuf = cpu_to_le32(params->stats->rx_packets/42*255);
491 case OID_GEN_BROADCAST_FRAMES_RCV:
492 debug("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
494 *outbuf = cpu_to_le32(params->stats->rx_packets / 42);
499 case OID_GEN_RCV_CRC_ERROR:
500 debug("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
502 *outbuf = cpu_to_le32(params->stats->rx_crc_errors);
507 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
508 debug("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
509 *outbuf = __constant_cpu_to_le32(0);
512 #endif /* RNDIS_OPTIONAL_STATS */
514 /* ieee802.3 OIDs (table 4-3) */
517 case OID_802_3_PERMANENT_ADDRESS:
518 debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
521 memcpy(outbuf, params->host_mac, length);
527 case OID_802_3_CURRENT_ADDRESS:
528 debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
531 memcpy(outbuf, params->host_mac, length);
537 case OID_802_3_MULTICAST_LIST:
538 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
539 /* Multicast base address only */
540 *outbuf = __constant_cpu_to_le32(0xE0000000);
545 case OID_802_3_MAXIMUM_LIST_SIZE:
546 debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
547 /* Multicast base address only */
548 *outbuf = __constant_cpu_to_le32(1);
552 case OID_802_3_MAC_OPTIONS:
553 debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
556 /* ieee802.3 statistics OIDs (table 4-4) */
559 case OID_802_3_RCV_ERROR_ALIGNMENT:
560 debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
562 *outbuf = cpu_to_le32(params->stats->rx_frame_errors);
568 case OID_802_3_XMIT_ONE_COLLISION:
569 debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
570 *outbuf = __constant_cpu_to_le32(0);
575 case OID_802_3_XMIT_MORE_COLLISIONS:
576 debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
577 *outbuf = __constant_cpu_to_le32(0);
581 #ifdef RNDIS_OPTIONAL_STATS
582 case OID_802_3_XMIT_DEFERRED:
583 debug("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
587 case OID_802_3_XMIT_MAX_COLLISIONS:
588 debug("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
592 case OID_802_3_RCV_OVERRUN:
593 debug("%s: OID_802_3_RCV_OVERRUN\n", __func__);
597 case OID_802_3_XMIT_UNDERRUN:
598 debug("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
602 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
603 debug("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
607 case OID_802_3_XMIT_TIMES_CRS_LOST:
608 debug("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
612 case OID_802_3_XMIT_LATE_COLLISIONS:
613 debug("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
616 #endif /* RNDIS_OPTIONAL_STATS */
619 /* power management OIDs (table 4-5) */
620 case OID_PNP_CAPABILITIES:
621 debug("%s: OID_PNP_CAPABILITIES\n", __func__);
623 /* for now, no wakeup capabilities */
624 length = sizeof(struct NDIS_PNP_CAPABILITIES);
625 memset(outbuf, 0, length);
628 case OID_PNP_QUERY_POWER:
629 debug("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
630 get_unaligned_le32(buf) - 1);
632 * only suspend is a real power state, and
633 * it can't be entered by OID_PNP_SET_POWER...
641 debug("%s: query unknown OID 0x%08X\n", __func__, OID);
646 resp->InformationBufferLength = cpu_to_le32(length);
647 r->length = length + sizeof *resp;
648 resp->MessageLength = cpu_to_le32(r->length);
652 static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
655 rndis_set_cmplt_type *resp;
656 int retval = -ENOTSUPP;
657 struct rndis_params *params;
658 #if (defined(DEBUG) && defined(DEBUG_VERBOSE)) || defined(RNDIS_PM)
664 resp = (rndis_set_cmplt_type *) r->buf;
668 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
670 debug("set OID %08x value, len %d:\n", OID, buf_len);
671 for (i = 0; i < buf_len; i += 16) {
672 debug("%03d: %08x %08x %08x %08x\n", i,
673 get_unaligned_le32(&buf[i]),
674 get_unaligned_le32(&buf[i + 4]),
675 get_unaligned_le32(&buf[i + 8]),
676 get_unaligned_le32(&buf[i + 12]));
681 params = &rndis_per_dev_params[configNr];
683 case OID_GEN_CURRENT_PACKET_FILTER:
686 * these NDIS_PACKET_TYPE_* bitflags are shared with
687 * cdc_filter; it's not RNDIS-specific
688 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
689 * PROMISCUOUS, DIRECTED,
690 * MULTICAST, ALL_MULTICAST, BROADCAST
692 *params->filter = (u16) get_unaligned_le32(buf);
693 debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
694 __func__, *params->filter);
697 * this call has a significant side effect: it's
698 * what makes the packet flow start and stop, like
699 * activating the CDC Ethernet altsetting.
706 params->state = RNDIS_DATA_INITIALIZED;
708 params->state = RNDIS_INITIALIZED;
711 case OID_802_3_MULTICAST_LIST:
712 /* I think we can ignore this */
713 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
717 case OID_GEN_RNDIS_CONFIG_PARAMETER:
719 struct rndis_config_parameter *param;
720 param = (struct rndis_config_parameter *) buf;
721 debug("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
723 min(cpu_to_le32(param->ParameterNameLength), 80),
724 buf + param->ParameterNameOffset);
731 case OID_PNP_SET_POWER:
733 * The only real power state is USB suspend, and RNDIS requests
734 * can't enter it; this one isn't really about power. After
735 * resuming, Windows forces a reset, and then SET_POWER D0.
736 * FIXME ... then things go batty; Windows wedges itself.
738 i = get_unaligned_le32(buf);
739 debug("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
741 case NdisDeviceStateD0:
742 *params->filter = params->saved_filter;
743 goto update_linkstate;
744 case NdisDeviceStateD3:
745 case NdisDeviceStateD2:
746 case NdisDeviceStateD1:
747 params->saved_filter = *params->filter;
755 * no wakeup support advertised, so wakeup OIDs always fail:
756 * - OID_PNP_ENABLE_WAKE_UP
757 * - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
761 #endif /* RNDIS_PM */
764 debug("%s: set unknown OID 0x%08X, size %d\n",
765 __func__, OID, buf_len);
775 static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
777 rndis_init_cmplt_type *resp;
780 if (!rndis_per_dev_params[configNr].dev)
783 r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
786 resp = (rndis_init_cmplt_type *) r->buf;
788 resp->MessageType = __constant_cpu_to_le32(
789 REMOTE_NDIS_INITIALIZE_CMPLT);
790 resp->MessageLength = __constant_cpu_to_le32(52);
791 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
792 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
793 resp->MajorVersion = __constant_cpu_to_le32(RNDIS_MAJOR_VERSION);
794 resp->MinorVersion = __constant_cpu_to_le32(RNDIS_MINOR_VERSION);
795 resp->DeviceFlags = __constant_cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
796 resp->Medium = __constant_cpu_to_le32(RNDIS_MEDIUM_802_3);
797 resp->MaxPacketsPerTransfer = __constant_cpu_to_le32(1);
798 resp->MaxTransferSize = cpu_to_le32(
799 rndis_per_dev_params[configNr].mtu
801 + sizeof(struct rndis_packet_msg_type)
803 resp->PacketAlignmentFactor = __constant_cpu_to_le32(0);
804 resp->AFListOffset = __constant_cpu_to_le32(0);
805 resp->AFListSize = __constant_cpu_to_le32(0);
807 if (rndis_per_dev_params[configNr].ack)
808 rndis_per_dev_params[configNr].ack(
809 rndis_per_dev_params[configNr].dev);
814 static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
816 rndis_query_cmplt_type *resp;
819 debug("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID));
820 if (!rndis_per_dev_params[configNr].dev)
824 * we need more memory:
825 * gen_ndis_query_resp expects enough space for
826 * rndis_query_cmplt_type followed by data.
827 * oid_supported_list is the largest data reply
829 r = rndis_add_response(configNr,
830 sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
833 resp = (rndis_query_cmplt_type *) r->buf;
835 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
836 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
838 if (gen_ndis_query_resp(configNr, get_unaligned_le32(&buf->OID),
839 get_unaligned_le32(&buf->InformationBufferOffset)
841 get_unaligned_le32(&buf->InformationBufferLength),
843 /* OID not supported */
844 resp->Status = __constant_cpu_to_le32(
845 RNDIS_STATUS_NOT_SUPPORTED);
846 resp->MessageLength = __constant_cpu_to_le32(sizeof *resp);
847 resp->InformationBufferLength = __constant_cpu_to_le32(0);
848 resp->InformationBufferOffset = __constant_cpu_to_le32(0);
850 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
852 if (rndis_per_dev_params[configNr].ack)
853 rndis_per_dev_params[configNr].ack(
854 rndis_per_dev_params[configNr].dev);
858 static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
860 u32 BufLength, BufOffset;
861 rndis_set_cmplt_type *resp;
864 r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
867 resp = (rndis_set_cmplt_type *) r->buf;
869 BufLength = get_unaligned_le32(&buf->InformationBufferLength);
870 BufOffset = get_unaligned_le32(&buf->InformationBufferOffset);
873 debug("%s: Length: %d\n", __func__, BufLength);
874 debug("%s: Offset: %d\n", __func__, BufOffset);
875 debug("%s: InfoBuffer: ", __func__);
877 for (i = 0; i < BufLength; i++)
878 debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
883 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
884 resp->MessageLength = __constant_cpu_to_le32(16);
885 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
886 if (gen_ndis_set_resp(configNr, get_unaligned_le32(&buf->OID),
887 ((u8 *) buf) + 8 + BufOffset, BufLength, r))
888 resp->Status = __constant_cpu_to_le32(
889 RNDIS_STATUS_NOT_SUPPORTED);
891 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
893 if (rndis_per_dev_params[configNr].ack)
894 rndis_per_dev_params[configNr].ack(
895 rndis_per_dev_params[configNr].dev);
900 static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
902 rndis_reset_cmplt_type *resp;
905 r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
908 resp = (rndis_reset_cmplt_type *) r->buf;
910 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
911 resp->MessageLength = __constant_cpu_to_le32(16);
912 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
913 /* resent information */
914 resp->AddressingReset = __constant_cpu_to_le32(1);
916 if (rndis_per_dev_params[configNr].ack)
917 rndis_per_dev_params[configNr].ack(
918 rndis_per_dev_params[configNr].dev);
923 static int rndis_keepalive_response(int configNr,
924 rndis_keepalive_msg_type *buf)
926 rndis_keepalive_cmplt_type *resp;
929 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
931 r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
934 resp = (rndis_keepalive_cmplt_type *) r->buf;
936 resp->MessageType = __constant_cpu_to_le32(
937 REMOTE_NDIS_KEEPALIVE_CMPLT);
938 resp->MessageLength = __constant_cpu_to_le32(16);
939 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
940 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
942 if (rndis_per_dev_params[configNr].ack)
943 rndis_per_dev_params[configNr].ack(
944 rndis_per_dev_params[configNr].dev);
951 * Device to Host Comunication
953 static int rndis_indicate_status_msg(int configNr, u32 status)
955 rndis_indicate_status_msg_type *resp;
958 if (rndis_per_dev_params[configNr].state == RNDIS_UNINITIALIZED)
961 r = rndis_add_response(configNr,
962 sizeof(rndis_indicate_status_msg_type));
965 resp = (rndis_indicate_status_msg_type *) r->buf;
967 resp->MessageType = __constant_cpu_to_le32(
968 REMOTE_NDIS_INDICATE_STATUS_MSG);
969 resp->MessageLength = __constant_cpu_to_le32(20);
970 resp->Status = cpu_to_le32(status);
971 resp->StatusBufferLength = __constant_cpu_to_le32(0);
972 resp->StatusBufferOffset = __constant_cpu_to_le32(0);
974 if (rndis_per_dev_params[configNr].ack)
975 rndis_per_dev_params[configNr].ack(
976 rndis_per_dev_params[configNr].dev);
980 int rndis_signal_connect(int configNr)
982 rndis_per_dev_params[configNr].media_state
983 = NDIS_MEDIA_STATE_CONNECTED;
984 return rndis_indicate_status_msg(configNr,
985 RNDIS_STATUS_MEDIA_CONNECT);
988 int rndis_signal_disconnect(int configNr)
990 rndis_per_dev_params[configNr].media_state
991 = NDIS_MEDIA_STATE_DISCONNECTED;
993 #ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
994 return rndis_indicate_status_msg(configNr,
995 RNDIS_STATUS_MEDIA_DISCONNECT);
1001 void rndis_uninit(int configNr)
1006 if (configNr >= RNDIS_MAX_CONFIGS)
1008 rndis_per_dev_params[configNr].used = 0;
1009 rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
1011 /* drain the response queue */
1012 while ((buf = rndis_get_next_response(configNr, &length)))
1013 rndis_free_response(configNr, buf);
1016 void rndis_set_host_mac(int configNr, const u8 *addr)
1018 rndis_per_dev_params[configNr].host_mac = addr;
1021 enum rndis_state rndis_get_state(int configNr)
1023 if (configNr >= RNDIS_MAX_CONFIGS || configNr < 0)
1025 return rndis_per_dev_params[configNr].state;
1031 int rndis_msg_parser(u8 configNr, u8 *buf)
1033 u32 MsgType, MsgLength;
1035 struct rndis_params *params;
1037 debug("%s: configNr = %d, %p\n", __func__, configNr, buf);
1042 tmp = (__le32 *) buf;
1043 MsgType = get_unaligned_le32(tmp++);
1044 MsgLength = get_unaligned_le32(tmp++);
1046 if (configNr >= RNDIS_MAX_CONFIGS)
1048 params = &rndis_per_dev_params[configNr];
1051 * NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
1052 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
1053 * and normal HC level polling to see if there's any IN traffic.
1056 /* For USB: responses may take up to 10 seconds */
1058 case REMOTE_NDIS_INITIALIZE_MSG:
1059 debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__);
1060 params->state = RNDIS_INITIALIZED;
1061 return rndis_init_response(configNr,
1062 (rndis_init_msg_type *) buf);
1064 case REMOTE_NDIS_HALT_MSG:
1065 debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__);
1066 params->state = RNDIS_UNINITIALIZED;
1069 case REMOTE_NDIS_QUERY_MSG:
1070 return rndis_query_response(configNr,
1071 (rndis_query_msg_type *) buf);
1073 case REMOTE_NDIS_SET_MSG:
1074 return rndis_set_response(configNr,
1075 (rndis_set_msg_type *) buf);
1077 case REMOTE_NDIS_RESET_MSG:
1078 debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__);
1079 return rndis_reset_response(configNr,
1080 (rndis_reset_msg_type *) buf);
1082 case REMOTE_NDIS_KEEPALIVE_MSG:
1083 /* For USB: host does this every 5 seconds */
1084 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
1085 debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__);
1087 return rndis_keepalive_response(configNr,
1088 (rndis_keepalive_msg_type *) buf);
1092 * At least Windows XP emits some undefined RNDIS messages.
1093 * In one case those messages seemed to relate to the host
1094 * suspending itself.
1096 debug("%s: unknown RNDIS message 0x%08X len %d\n",
1097 __func__ , MsgType, MsgLength);
1100 for (i = 0; i < MsgLength; i += 16) {
1102 " %02x %02x %02x %02x"
1103 " %02x %02x %02x %02x"
1104 " %02x %02x %02x %02x"
1105 " %02x %02x %02x %02x"
1113 buf[i+10], buf[i+11],
1114 buf[i+12], buf[i+13],
1115 buf[i+14], buf[i+15]);
1124 int rndis_register(int (*rndis_control_ack)(struct eth_device *))
1128 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1129 if (!rndis_per_dev_params[i].used) {
1130 rndis_per_dev_params[i].used = 1;
1131 rndis_per_dev_params[i].ack = rndis_control_ack;
1132 debug("%s: configNr = %d\n", __func__, i);
1136 debug("%s failed\n", __func__);
1141 void rndis_deregister(int configNr)
1143 debug("%s: configNr = %d\n", __func__, configNr);
1145 if (configNr >= RNDIS_MAX_CONFIGS)
1147 rndis_per_dev_params[configNr].used = 0;
1152 int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu,
1153 struct net_device_stats *stats, u16 *cdc_filter)
1155 debug("%s: configNr = %d\n", __func__, configNr);
1158 if (configNr >= RNDIS_MAX_CONFIGS)
1161 rndis_per_dev_params[configNr].dev = dev;
1162 rndis_per_dev_params[configNr].stats = stats;
1163 rndis_per_dev_params[configNr].mtu = mtu;
1164 rndis_per_dev_params[configNr].filter = cdc_filter;
1169 int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
1171 debug("%s: configNr = %d\n", __func__, configNr);
1174 if (configNr >= RNDIS_MAX_CONFIGS)
1177 rndis_per_dev_params[configNr].vendorID = vendorID;
1178 rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
1183 int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
1185 debug("%s: configNr = %d, %u %u\n", __func__, configNr, medium, speed);
1186 if (configNr >= RNDIS_MAX_CONFIGS)
1189 rndis_per_dev_params[configNr].medium = medium;
1190 rndis_per_dev_params[configNr].speed = speed;
1195 void rndis_add_hdr(void *buf, int length)
1197 struct rndis_packet_msg_type *header;
1200 memset(header, 0, sizeof *header);
1201 header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
1202 header->MessageLength = cpu_to_le32(length + sizeof *header);
1203 header->DataOffset = __constant_cpu_to_le32(36);
1204 header->DataLength = cpu_to_le32(length);
1207 void rndis_free_response(int configNr, u8 *buf)
1210 struct list_head *act, *tmp;
1212 list_for_each_safe(act, tmp,
1213 &(rndis_per_dev_params[configNr].resp_queue))
1215 r = list_entry(act, rndis_resp_t, list);
1216 if (r && r->buf == buf) {
1223 u8 *rndis_get_next_response(int configNr, u32 *length)
1226 struct list_head *act, *tmp;
1231 list_for_each_safe(act, tmp,
1232 &(rndis_per_dev_params[configNr].resp_queue))
1234 r = list_entry(act, rndis_resp_t, list);
1237 *length = r->length;
1245 static rndis_resp_t *rndis_add_response(int configNr, u32 length)
1249 /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
1250 r = malloc(sizeof(rndis_resp_t) + length);
1254 r->buf = (u8 *) (r + 1);
1258 list_add_tail(&r->list,
1259 &(rndis_per_dev_params[configNr].resp_queue));
1263 int rndis_rm_hdr(void *buf, int length)
1265 /* tmp points to a struct rndis_packet_msg_type */
1269 /* MessageType, MessageLength */
1270 if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
1271 != get_unaligned(tmp++))
1275 /* DataOffset, DataLength */
1276 offs = get_unaligned_le32(tmp++) + 8 /* offset of DataOffset */;
1277 if (offs != sizeof(struct rndis_packet_msg_type))
1278 debug("%s: unexpected DataOffset: %d\n", __func__, offs);
1282 len = get_unaligned_le32(tmp++);
1283 if (len + sizeof(struct rndis_packet_msg_type) != length)
1284 debug("%s: unexpected DataLength: %d, packet length=%d\n",
1285 __func__, len, length);
1287 memmove(buf, buf + offs, len);
1292 int rndis_init(void)
1296 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1297 rndis_per_dev_params[i].confignr = i;
1298 rndis_per_dev_params[i].used = 0;
1299 rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
1300 rndis_per_dev_params[i].media_state
1301 = NDIS_MEDIA_STATE_DISCONNECTED;
1302 INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
1308 void rndis_exit(void)