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 <asm/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 */
44 #define ENOTSUPP 524 /* Operation is not supported */
48 * The driver for your USB chip needs to support ep0 OUT to work with
49 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
51 * Windows hosts need an INF file like Documentation/usb/linux.inf
52 * and will be happier if you provide the host_addr module parameter.
55 #define RNDIS_MAX_CONFIGS 1
57 static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
60 static const __le32 rndis_driver_version = __constant_cpu_to_le32(1);
62 /* Function Prototypes */
63 static rndis_resp_t *rndis_add_response(int configNr, u32 length);
67 static const u32 oid_supported_list[] = {
68 /* the general stuff */
69 OID_GEN_SUPPORTED_LIST,
70 OID_GEN_HARDWARE_STATUS,
71 OID_GEN_MEDIA_SUPPORTED,
73 OID_GEN_MAXIMUM_FRAME_SIZE,
75 OID_GEN_TRANSMIT_BLOCK_SIZE,
76 OID_GEN_RECEIVE_BLOCK_SIZE,
78 OID_GEN_VENDOR_DESCRIPTION,
79 OID_GEN_VENDOR_DRIVER_VERSION,
80 OID_GEN_CURRENT_PACKET_FILTER,
81 OID_GEN_MAXIMUM_TOTAL_SIZE,
82 OID_GEN_MEDIA_CONNECT_STATUS,
83 OID_GEN_PHYSICAL_MEDIUM,
85 OID_GEN_RNDIS_CONFIG_PARAMETER,
88 /* the statistical stuff */
93 OID_GEN_RCV_NO_BUFFER,
94 #ifdef RNDIS_OPTIONAL_STATS
95 OID_GEN_DIRECTED_BYTES_XMIT,
96 OID_GEN_DIRECTED_FRAMES_XMIT,
97 OID_GEN_MULTICAST_BYTES_XMIT,
98 OID_GEN_MULTICAST_FRAMES_XMIT,
99 OID_GEN_BROADCAST_BYTES_XMIT,
100 OID_GEN_BROADCAST_FRAMES_XMIT,
101 OID_GEN_DIRECTED_BYTES_RCV,
102 OID_GEN_DIRECTED_FRAMES_RCV,
103 OID_GEN_MULTICAST_BYTES_RCV,
104 OID_GEN_MULTICAST_FRAMES_RCV,
105 OID_GEN_BROADCAST_BYTES_RCV,
106 OID_GEN_BROADCAST_FRAMES_RCV,
107 OID_GEN_RCV_CRC_ERROR,
108 OID_GEN_TRANSMIT_QUEUE_LENGTH,
109 #endif /* RNDIS_OPTIONAL_STATS */
111 /* mandatory 802.3 */
112 /* the general stuff */
113 OID_802_3_PERMANENT_ADDRESS,
114 OID_802_3_CURRENT_ADDRESS,
115 OID_802_3_MULTICAST_LIST,
116 OID_802_3_MAC_OPTIONS,
117 OID_802_3_MAXIMUM_LIST_SIZE,
119 /* the statistical stuff */
120 OID_802_3_RCV_ERROR_ALIGNMENT,
121 OID_802_3_XMIT_ONE_COLLISION,
122 OID_802_3_XMIT_MORE_COLLISIONS,
123 #ifdef RNDIS_OPTIONAL_STATS
124 OID_802_3_XMIT_DEFERRED,
125 OID_802_3_XMIT_MAX_COLLISIONS,
126 OID_802_3_RCV_OVERRUN,
127 OID_802_3_XMIT_UNDERRUN,
128 OID_802_3_XMIT_HEARTBEAT_FAILURE,
129 OID_802_3_XMIT_TIMES_CRS_LOST,
130 OID_802_3_XMIT_LATE_COLLISIONS,
131 #endif /* RNDIS_OPTIONAL_STATS */
134 /* PM and wakeup are mandatory for USB: */
136 /* power management */
137 OID_PNP_CAPABILITIES,
143 OID_PNP_ENABLE_WAKE_UP,
144 OID_PNP_ADD_WAKE_UP_PATTERN,
145 OID_PNP_REMOVE_WAKE_UP_PATTERN,
146 #endif /* RNDIS_WAKEUP */
147 #endif /* RNDIS_PM */
152 static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
153 unsigned buf_len, rndis_resp_t *r)
155 int retval = -ENOTSUPP;
156 u32 length = 4; /* usually */
159 rndis_query_cmplt_type *resp;
160 rndis_params *params;
164 resp = (rndis_query_cmplt_type *) r->buf;
169 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
171 debug("query OID %08x value, len %d:\n", OID, buf_len);
172 for (i = 0; i < buf_len; i += 16) {
173 debug("%03d: %08x %08x %08x %08x\n", i,
174 get_unaligned_le32(&buf[i]),
175 get_unaligned_le32(&buf[i + 4]),
176 get_unaligned_le32(&buf[i + 8]),
177 get_unaligned_le32(&buf[i + 12]));
182 /* response goes here, right after the header */
183 outbuf = (__le32 *) &resp[1];
184 resp->InformationBufferOffset = __constant_cpu_to_le32(16);
186 params = &rndis_per_dev_params[configNr];
189 /* general oids (table 4-1) */
192 case OID_GEN_SUPPORTED_LIST:
193 debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
194 length = sizeof(oid_supported_list);
195 count = length / sizeof(u32);
196 for (i = 0; i < count; i++)
197 outbuf[i] = cpu_to_le32(oid_supported_list[i]);
202 case OID_GEN_HARDWARE_STATUS:
203 debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
206 * Hardware must be ready to receive high level protocols.
208 * reddite ergo quae sunt Caesaris Caesari
209 * et quae sunt Dei Deo!
211 *outbuf = __constant_cpu_to_le32(0);
216 case OID_GEN_MEDIA_SUPPORTED:
217 debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
218 *outbuf = cpu_to_le32(params->medium);
223 case OID_GEN_MEDIA_IN_USE:
224 debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
225 /* one medium, one transport... (maybe you do it better) */
226 *outbuf = cpu_to_le32(params->medium);
231 case OID_GEN_MAXIMUM_FRAME_SIZE:
232 debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
234 *outbuf = cpu_to_le32(params->mtu);
240 case OID_GEN_LINK_SPEED:
241 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
242 debug("%s: OID_GEN_LINK_SPEED\n", __func__);
244 if (params->media_state == NDIS_MEDIA_STATE_DISCONNECTED)
245 *outbuf = __constant_cpu_to_le32(0);
247 *outbuf = cpu_to_le32(params->speed);
252 case OID_GEN_TRANSMIT_BLOCK_SIZE:
253 debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
255 *outbuf = cpu_to_le32(params->mtu);
261 case OID_GEN_RECEIVE_BLOCK_SIZE:
262 debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
264 *outbuf = cpu_to_le32(params->mtu);
270 case OID_GEN_VENDOR_ID:
271 debug("%s: OID_GEN_VENDOR_ID\n", __func__);
272 *outbuf = cpu_to_le32(params->vendorID);
277 case OID_GEN_VENDOR_DESCRIPTION:
278 debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
279 length = strlen(params->vendorDescr);
280 memcpy(outbuf, params->vendorDescr, length);
284 case OID_GEN_VENDOR_DRIVER_VERSION:
285 debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
287 *outbuf = rndis_driver_version;
292 case OID_GEN_CURRENT_PACKET_FILTER:
293 debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
294 *outbuf = cpu_to_le32(*params->filter);
299 case OID_GEN_MAXIMUM_TOTAL_SIZE:
300 debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
301 *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
306 case OID_GEN_MEDIA_CONNECT_STATUS:
307 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
308 debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
310 *outbuf = cpu_to_le32(params->media_state);
314 case OID_GEN_PHYSICAL_MEDIUM:
315 debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
316 *outbuf = __constant_cpu_to_le32(0);
321 * The RNDIS specification is incomplete/wrong. Some versions
322 * of MS-Windows expect OIDs that aren't specified there. Other
323 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
325 case OID_GEN_MAC_OPTIONS: /* from WinME */
326 debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
327 *outbuf = __constant_cpu_to_le32(
328 NDIS_MAC_OPTION_RECEIVE_SERIALIZED
329 | NDIS_MAC_OPTION_FULL_DUPLEX);
333 /* statistics OIDs (table 4-2) */
336 case OID_GEN_XMIT_OK:
337 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
338 debug("%s: OID_GEN_XMIT_OK\n", __func__);
341 *outbuf = cpu_to_le32(
342 params->stats->tx_packets -
343 params->stats->tx_errors -
344 params->stats->tx_dropped);
351 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
352 debug("%s: OID_GEN_RCV_OK\n", __func__);
355 *outbuf = cpu_to_le32(
356 params->stats->rx_packets -
357 params->stats->rx_errors -
358 params->stats->rx_dropped);
364 case OID_GEN_XMIT_ERROR:
365 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
366 debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
369 *outbuf = cpu_to_le32(params->stats->tx_errors);
375 case OID_GEN_RCV_ERROR:
376 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
377 debug("%s: OID_GEN_RCV_ERROR\n", __func__);
380 *outbuf = cpu_to_le32(params->stats->rx_errors);
386 case OID_GEN_RCV_NO_BUFFER:
387 debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
389 *outbuf = cpu_to_le32(params->stats->rx_dropped);
394 #ifdef RNDIS_OPTIONAL_STATS
395 case OID_GEN_DIRECTED_BYTES_XMIT:
396 debug("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
398 * Aunt Tilly's size of shoes
399 * minus antarctica count of penguins
400 * divided by weight of Alpha Centauri
403 *outbuf = cpu_to_le32(
404 (params->stats->tx_packets -
405 params->stats->tx_errors -
406 params->stats->tx_dropped)
412 case OID_GEN_DIRECTED_FRAMES_XMIT:
413 debug("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
416 *outbuf = cpu_to_le32(
417 (params->stats->tx_packets -
418 params->stats->tx_errors -
419 params->stats->tx_dropped)
425 case OID_GEN_MULTICAST_BYTES_XMIT:
426 debug("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
428 *outbuf = cpu_to_le32(params->stats->multicast * 1234);
433 case OID_GEN_MULTICAST_FRAMES_XMIT:
434 debug("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
436 *outbuf = cpu_to_le32(params->stats->multicast);
441 case OID_GEN_BROADCAST_BYTES_XMIT:
442 debug("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
444 *outbuf = cpu_to_le32(params->stats->tx_packets/42*255);
449 case OID_GEN_BROADCAST_FRAMES_XMIT:
450 debug("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
452 *outbuf = cpu_to_le32(params->stats->tx_packets / 42);
457 case OID_GEN_DIRECTED_BYTES_RCV:
458 debug("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
459 *outbuf = __constant_cpu_to_le32(0);
463 case OID_GEN_DIRECTED_FRAMES_RCV:
464 debug("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
465 *outbuf = __constant_cpu_to_le32(0);
469 case OID_GEN_MULTICAST_BYTES_RCV:
470 debug("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
472 *outbuf = cpu_to_le32(params->stats->multicast * 1111);
477 case OID_GEN_MULTICAST_FRAMES_RCV:
478 debug("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
480 *outbuf = cpu_to_le32(params->stats->multicast);
485 case OID_GEN_BROADCAST_BYTES_RCV:
486 debug("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
488 *outbuf = cpu_to_le32(params->stats->rx_packets/42*255);
493 case OID_GEN_BROADCAST_FRAMES_RCV:
494 debug("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
496 *outbuf = cpu_to_le32(params->stats->rx_packets / 42);
501 case OID_GEN_RCV_CRC_ERROR:
502 debug("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
504 *outbuf = cpu_to_le32(params->stats->rx_crc_errors);
509 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
510 debug("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
511 *outbuf = __constant_cpu_to_le32(0);
514 #endif /* RNDIS_OPTIONAL_STATS */
516 /* ieee802.3 OIDs (table 4-3) */
519 case OID_802_3_PERMANENT_ADDRESS:
520 debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
523 memcpy(outbuf, params->host_mac, length);
529 case OID_802_3_CURRENT_ADDRESS:
530 debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
533 memcpy(outbuf, params->host_mac, length);
539 case OID_802_3_MULTICAST_LIST:
540 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
541 /* Multicast base address only */
542 *outbuf = __constant_cpu_to_le32(0xE0000000);
547 case OID_802_3_MAXIMUM_LIST_SIZE:
548 debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
549 /* Multicast base address only */
550 *outbuf = __constant_cpu_to_le32(1);
554 case OID_802_3_MAC_OPTIONS:
555 debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
558 /* ieee802.3 statistics OIDs (table 4-4) */
561 case OID_802_3_RCV_ERROR_ALIGNMENT:
562 debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
564 *outbuf = cpu_to_le32(params->stats->rx_frame_errors);
570 case OID_802_3_XMIT_ONE_COLLISION:
571 debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
572 *outbuf = __constant_cpu_to_le32(0);
577 case OID_802_3_XMIT_MORE_COLLISIONS:
578 debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
579 *outbuf = __constant_cpu_to_le32(0);
583 #ifdef RNDIS_OPTIONAL_STATS
584 case OID_802_3_XMIT_DEFERRED:
585 debug("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
589 case OID_802_3_XMIT_MAX_COLLISIONS:
590 debug("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
594 case OID_802_3_RCV_OVERRUN:
595 debug("%s: OID_802_3_RCV_OVERRUN\n", __func__);
599 case OID_802_3_XMIT_UNDERRUN:
600 debug("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
604 case OID_802_3_XMIT_HEARTBEAT_FAILURE:
605 debug("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
609 case OID_802_3_XMIT_TIMES_CRS_LOST:
610 debug("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
614 case OID_802_3_XMIT_LATE_COLLISIONS:
615 debug("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
618 #endif /* RNDIS_OPTIONAL_STATS */
621 /* power management OIDs (table 4-5) */
622 case OID_PNP_CAPABILITIES:
623 debug("%s: OID_PNP_CAPABILITIES\n", __func__);
625 /* for now, no wakeup capabilities */
626 length = sizeof(struct NDIS_PNP_CAPABILITIES);
627 memset(outbuf, 0, length);
630 case OID_PNP_QUERY_POWER:
631 debug("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
632 get_unaligned_le32(buf) - 1);
634 * only suspend is a real power state, and
635 * it can't be entered by OID_PNP_SET_POWER...
643 debug("%s: query unknown OID 0x%08X\n", __func__, OID);
648 resp->InformationBufferLength = cpu_to_le32(length);
649 r->length = length + sizeof *resp;
650 resp->MessageLength = cpu_to_le32(r->length);
654 static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
657 rndis_set_cmplt_type *resp;
658 int retval = -ENOTSUPP;
659 struct rndis_params *params;
660 #if (defined(DEBUG) && defined(DEBUG_VERBOSE)) || defined(RNDIS_PM)
666 resp = (rndis_set_cmplt_type *) r->buf;
670 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
672 debug("set OID %08x value, len %d:\n", OID, buf_len);
673 for (i = 0; i < buf_len; i += 16) {
674 debug("%03d: %08x %08x %08x %08x\n", i,
675 get_unaligned_le32(&buf[i]),
676 get_unaligned_le32(&buf[i + 4]),
677 get_unaligned_le32(&buf[i + 8]),
678 get_unaligned_le32(&buf[i + 12]));
683 params = &rndis_per_dev_params[configNr];
685 case OID_GEN_CURRENT_PACKET_FILTER:
688 * these NDIS_PACKET_TYPE_* bitflags are shared with
689 * cdc_filter; it's not RNDIS-specific
690 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
691 * PROMISCUOUS, DIRECTED,
692 * MULTICAST, ALL_MULTICAST, BROADCAST
694 *params->filter = (u16) get_unaligned_le32(buf);
695 debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
696 __func__, *params->filter);
699 * this call has a significant side effect: it's
700 * what makes the packet flow start and stop, like
701 * activating the CDC Ethernet altsetting.
708 params->state = RNDIS_DATA_INITIALIZED;
710 params->state = RNDIS_INITIALIZED;
713 case OID_802_3_MULTICAST_LIST:
714 /* I think we can ignore this */
715 debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
719 case OID_GEN_RNDIS_CONFIG_PARAMETER:
721 struct rndis_config_parameter *param;
722 param = (struct rndis_config_parameter *) buf;
723 debug("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
725 min(cpu_to_le32(param->ParameterNameLength), 80),
726 buf + param->ParameterNameOffset);
733 case OID_PNP_SET_POWER:
735 * The only real power state is USB suspend, and RNDIS requests
736 * can't enter it; this one isn't really about power. After
737 * resuming, Windows forces a reset, and then SET_POWER D0.
738 * FIXME ... then things go batty; Windows wedges itself.
740 i = get_unaligned_le32(buf);
741 debug("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
743 case NdisDeviceStateD0:
744 *params->filter = params->saved_filter;
745 goto update_linkstate;
746 case NdisDeviceStateD3:
747 case NdisDeviceStateD2:
748 case NdisDeviceStateD1:
749 params->saved_filter = *params->filter;
757 * no wakeup support advertised, so wakeup OIDs always fail:
758 * - OID_PNP_ENABLE_WAKE_UP
759 * - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
763 #endif /* RNDIS_PM */
766 debug("%s: set unknown OID 0x%08X, size %d\n",
767 __func__, OID, buf_len);
777 static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
779 rndis_init_cmplt_type *resp;
782 if (!rndis_per_dev_params[configNr].dev)
785 r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
788 resp = (rndis_init_cmplt_type *) r->buf;
790 resp->MessageType = __constant_cpu_to_le32(
791 REMOTE_NDIS_INITIALIZE_CMPLT);
792 resp->MessageLength = __constant_cpu_to_le32(52);
793 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
794 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
795 resp->MajorVersion = __constant_cpu_to_le32(RNDIS_MAJOR_VERSION);
796 resp->MinorVersion = __constant_cpu_to_le32(RNDIS_MINOR_VERSION);
797 resp->DeviceFlags = __constant_cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
798 resp->Medium = __constant_cpu_to_le32(RNDIS_MEDIUM_802_3);
799 resp->MaxPacketsPerTransfer = __constant_cpu_to_le32(1);
800 resp->MaxTransferSize = cpu_to_le32(
801 rndis_per_dev_params[configNr].mtu
803 + sizeof(struct rndis_packet_msg_type)
805 resp->PacketAlignmentFactor = __constant_cpu_to_le32(0);
806 resp->AFListOffset = __constant_cpu_to_le32(0);
807 resp->AFListSize = __constant_cpu_to_le32(0);
809 if (rndis_per_dev_params[configNr].ack)
810 rndis_per_dev_params[configNr].ack(
811 rndis_per_dev_params[configNr].dev);
816 static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
818 rndis_query_cmplt_type *resp;
821 debug("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID));
822 if (!rndis_per_dev_params[configNr].dev)
826 * we need more memory:
827 * gen_ndis_query_resp expects enough space for
828 * rndis_query_cmplt_type followed by data.
829 * oid_supported_list is the largest data reply
831 r = rndis_add_response(configNr,
832 sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
835 resp = (rndis_query_cmplt_type *) r->buf;
837 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
838 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
840 if (gen_ndis_query_resp(configNr, get_unaligned_le32(&buf->OID),
841 get_unaligned_le32(&buf->InformationBufferOffset)
843 get_unaligned_le32(&buf->InformationBufferLength),
845 /* OID not supported */
846 resp->Status = __constant_cpu_to_le32(
847 RNDIS_STATUS_NOT_SUPPORTED);
848 resp->MessageLength = __constant_cpu_to_le32(sizeof *resp);
849 resp->InformationBufferLength = __constant_cpu_to_le32(0);
850 resp->InformationBufferOffset = __constant_cpu_to_le32(0);
852 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
854 if (rndis_per_dev_params[configNr].ack)
855 rndis_per_dev_params[configNr].ack(
856 rndis_per_dev_params[configNr].dev);
860 static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
862 u32 BufLength, BufOffset;
863 rndis_set_cmplt_type *resp;
866 r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
869 resp = (rndis_set_cmplt_type *) r->buf;
871 BufLength = get_unaligned_le32(&buf->InformationBufferLength);
872 BufOffset = get_unaligned_le32(&buf->InformationBufferOffset);
875 debug("%s: Length: %d\n", __func__, BufLength);
876 debug("%s: Offset: %d\n", __func__, BufOffset);
877 debug("%s: InfoBuffer: ", __func__);
879 for (i = 0; i < BufLength; i++)
880 debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
885 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
886 resp->MessageLength = __constant_cpu_to_le32(16);
887 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
888 if (gen_ndis_set_resp(configNr, get_unaligned_le32(&buf->OID),
889 ((u8 *) buf) + 8 + BufOffset, BufLength, r))
890 resp->Status = __constant_cpu_to_le32(
891 RNDIS_STATUS_NOT_SUPPORTED);
893 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
895 if (rndis_per_dev_params[configNr].ack)
896 rndis_per_dev_params[configNr].ack(
897 rndis_per_dev_params[configNr].dev);
902 static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
904 rndis_reset_cmplt_type *resp;
907 r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
910 resp = (rndis_reset_cmplt_type *) r->buf;
912 resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
913 resp->MessageLength = __constant_cpu_to_le32(16);
914 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
915 /* resent information */
916 resp->AddressingReset = __constant_cpu_to_le32(1);
918 if (rndis_per_dev_params[configNr].ack)
919 rndis_per_dev_params[configNr].ack(
920 rndis_per_dev_params[configNr].dev);
925 static int rndis_keepalive_response(int configNr,
926 rndis_keepalive_msg_type *buf)
928 rndis_keepalive_cmplt_type *resp;
931 /* host "should" check only in RNDIS_DATA_INITIALIZED state */
933 r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
936 resp = (rndis_keepalive_cmplt_type *) r->buf;
938 resp->MessageType = __constant_cpu_to_le32(
939 REMOTE_NDIS_KEEPALIVE_CMPLT);
940 resp->MessageLength = __constant_cpu_to_le32(16);
941 resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
942 resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
944 if (rndis_per_dev_params[configNr].ack)
945 rndis_per_dev_params[configNr].ack(
946 rndis_per_dev_params[configNr].dev);
953 * Device to Host Comunication
955 static int rndis_indicate_status_msg(int configNr, u32 status)
957 rndis_indicate_status_msg_type *resp;
960 if (rndis_per_dev_params[configNr].state == RNDIS_UNINITIALIZED)
963 r = rndis_add_response(configNr,
964 sizeof(rndis_indicate_status_msg_type));
967 resp = (rndis_indicate_status_msg_type *) r->buf;
969 resp->MessageType = __constant_cpu_to_le32(
970 REMOTE_NDIS_INDICATE_STATUS_MSG);
971 resp->MessageLength = __constant_cpu_to_le32(20);
972 resp->Status = cpu_to_le32(status);
973 resp->StatusBufferLength = __constant_cpu_to_le32(0);
974 resp->StatusBufferOffset = __constant_cpu_to_le32(0);
976 if (rndis_per_dev_params[configNr].ack)
977 rndis_per_dev_params[configNr].ack(
978 rndis_per_dev_params[configNr].dev);
982 int rndis_signal_connect(int configNr)
984 rndis_per_dev_params[configNr].media_state
985 = NDIS_MEDIA_STATE_CONNECTED;
986 return rndis_indicate_status_msg(configNr,
987 RNDIS_STATUS_MEDIA_CONNECT);
990 int rndis_signal_disconnect(int configNr)
992 rndis_per_dev_params[configNr].media_state
993 = NDIS_MEDIA_STATE_DISCONNECTED;
995 #ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
996 return rndis_indicate_status_msg(configNr,
997 RNDIS_STATUS_MEDIA_DISCONNECT);
1003 void rndis_uninit(int configNr)
1008 if (configNr >= RNDIS_MAX_CONFIGS)
1010 rndis_per_dev_params[configNr].used = 0;
1011 rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
1013 /* drain the response queue */
1014 while ((buf = rndis_get_next_response(configNr, &length)))
1015 rndis_free_response(configNr, buf);
1018 void rndis_set_host_mac(int configNr, const u8 *addr)
1020 rndis_per_dev_params[configNr].host_mac = addr;
1023 enum rndis_state rndis_get_state(int configNr)
1025 if (configNr >= RNDIS_MAX_CONFIGS || configNr < 0)
1027 return rndis_per_dev_params[configNr].state;
1033 int rndis_msg_parser(u8 configNr, u8 *buf)
1035 u32 MsgType, MsgLength;
1037 struct rndis_params *params;
1039 debug("%s: configNr = %d, %p\n", __func__, configNr, buf);
1044 tmp = (__le32 *) buf;
1045 MsgType = get_unaligned_le32(tmp++);
1046 MsgLength = get_unaligned_le32(tmp++);
1048 if (configNr >= RNDIS_MAX_CONFIGS)
1050 params = &rndis_per_dev_params[configNr];
1053 * NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
1054 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
1055 * and normal HC level polling to see if there's any IN traffic.
1058 /* For USB: responses may take up to 10 seconds */
1060 case REMOTE_NDIS_INITIALIZE_MSG:
1061 debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__);
1062 params->state = RNDIS_INITIALIZED;
1063 return rndis_init_response(configNr,
1064 (rndis_init_msg_type *) buf);
1066 case REMOTE_NDIS_HALT_MSG:
1067 debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__);
1068 params->state = RNDIS_UNINITIALIZED;
1071 case REMOTE_NDIS_QUERY_MSG:
1072 return rndis_query_response(configNr,
1073 (rndis_query_msg_type *) buf);
1075 case REMOTE_NDIS_SET_MSG:
1076 return rndis_set_response(configNr,
1077 (rndis_set_msg_type *) buf);
1079 case REMOTE_NDIS_RESET_MSG:
1080 debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__);
1081 return rndis_reset_response(configNr,
1082 (rndis_reset_msg_type *) buf);
1084 case REMOTE_NDIS_KEEPALIVE_MSG:
1085 /* For USB: host does this every 5 seconds */
1086 #if defined(DEBUG) && defined(DEBUG_VERBOSE)
1087 debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__);
1089 return rndis_keepalive_response(configNr,
1090 (rndis_keepalive_msg_type *) buf);
1094 * At least Windows XP emits some undefined RNDIS messages.
1095 * In one case those messages seemed to relate to the host
1096 * suspending itself.
1098 debug("%s: unknown RNDIS message 0x%08X len %d\n",
1099 __func__ , MsgType, MsgLength);
1102 for (i = 0; i < MsgLength; i += 16) {
1104 " %02x %02x %02x %02x"
1105 " %02x %02x %02x %02x"
1106 " %02x %02x %02x %02x"
1107 " %02x %02x %02x %02x"
1115 buf[i+10], buf[i+11],
1116 buf[i+12], buf[i+13],
1117 buf[i+14], buf[i+15]);
1126 int rndis_register(int (*rndis_control_ack)(struct eth_device *))
1130 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1131 if (!rndis_per_dev_params[i].used) {
1132 rndis_per_dev_params[i].used = 1;
1133 rndis_per_dev_params[i].ack = rndis_control_ack;
1134 debug("%s: configNr = %d\n", __func__, i);
1138 debug("%s failed\n", __func__);
1143 void rndis_deregister(int configNr)
1145 debug("%s: configNr = %d\n", __func__, configNr);
1147 if (configNr >= RNDIS_MAX_CONFIGS)
1149 rndis_per_dev_params[configNr].used = 0;
1154 int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu,
1155 struct net_device_stats *stats, u16 *cdc_filter)
1157 debug("%s: configNr = %d\n", __func__, configNr);
1160 if (configNr >= RNDIS_MAX_CONFIGS)
1163 rndis_per_dev_params[configNr].dev = dev;
1164 rndis_per_dev_params[configNr].stats = stats;
1165 rndis_per_dev_params[configNr].mtu = mtu;
1166 rndis_per_dev_params[configNr].filter = cdc_filter;
1171 int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
1173 debug("%s: configNr = %d\n", __func__, configNr);
1176 if (configNr >= RNDIS_MAX_CONFIGS)
1179 rndis_per_dev_params[configNr].vendorID = vendorID;
1180 rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
1185 int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
1187 debug("%s: configNr = %d, %u %u\n", __func__, configNr, medium, speed);
1188 if (configNr >= RNDIS_MAX_CONFIGS)
1191 rndis_per_dev_params[configNr].medium = medium;
1192 rndis_per_dev_params[configNr].speed = speed;
1197 void rndis_add_hdr(void *buf, int length)
1199 struct rndis_packet_msg_type *header;
1202 memset(header, 0, sizeof *header);
1203 header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
1204 header->MessageLength = cpu_to_le32(length + sizeof *header);
1205 header->DataOffset = __constant_cpu_to_le32(36);
1206 header->DataLength = cpu_to_le32(length);
1209 void rndis_free_response(int configNr, u8 *buf)
1212 struct list_head *act, *tmp;
1214 list_for_each_safe(act, tmp,
1215 &(rndis_per_dev_params[configNr].resp_queue))
1217 r = list_entry(act, rndis_resp_t, list);
1218 if (r && r->buf == buf) {
1225 u8 *rndis_get_next_response(int configNr, u32 *length)
1228 struct list_head *act, *tmp;
1233 list_for_each_safe(act, tmp,
1234 &(rndis_per_dev_params[configNr].resp_queue))
1236 r = list_entry(act, rndis_resp_t, list);
1239 *length = r->length;
1247 static rndis_resp_t *rndis_add_response(int configNr, u32 length)
1251 /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
1252 r = malloc(sizeof(rndis_resp_t) + length);
1256 r->buf = (u8 *) (r + 1);
1260 list_add_tail(&r->list,
1261 &(rndis_per_dev_params[configNr].resp_queue));
1265 int rndis_rm_hdr(void *buf, int length)
1267 /* tmp points to a struct rndis_packet_msg_type */
1271 /* MessageType, MessageLength */
1272 if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
1273 != get_unaligned(tmp++))
1277 /* DataOffset, DataLength */
1278 offs = get_unaligned_le32(tmp++) + 8 /* offset of DataOffset */;
1279 if (offs != sizeof(struct rndis_packet_msg_type))
1280 debug("%s: unexpected DataOffset: %d\n", __func__, offs);
1284 len = get_unaligned_le32(tmp++);
1285 if (len + sizeof(struct rndis_packet_msg_type) != length)
1286 debug("%s: unexpected DataLength: %d, packet length=%d\n",
1287 __func__, len, length);
1289 memmove(buf, buf + offs, len);
1294 int rndis_init(void)
1298 for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1299 rndis_per_dev_params[i].confignr = i;
1300 rndis_per_dev_params[i].used = 0;
1301 rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
1302 rndis_per_dev_params[i].media_state
1303 = NDIS_MEDIA_STATE_DISCONNECTED;
1304 INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
1310 void rndis_exit(void)