The Microsoft Windows XP and Windows CE .NET operating systems include built-in support for RNDIS USB Drivers. This article is provided for hardware manufacturers who are creating USB network adapters that take advantage of these capabilities in Windows operating systems. It is assumed that the reader is familiar with the Remote NDIS Specification; Universal Serial Bus Specification, Revision 1.1; and the USB Communications Device Class Specification, Revision 1.0.
| Introduction and Background | |
| USB and Windows | |
| Remote NDIS | |
| USB Remote NDIS Ethernet Adapter | |
| Sample USB Remote NDIS Ethernet Adapter | |
| Call to Action | |
| References |
Remote NDIS is a Windows architecture for natively supporting network devices on dynamic Plug and Play buses. Windows XP and Windows CE .NET ship with native support for USB Remote NDIS Ethernet adapters. This article provides an informational overview and guide to building a USB Remote NDIS adapter, including a USB descriptor sample.
Readers should be familiar with Universal Serial Bus specification. In particular, readers should understand the hierarchical set of descriptors that define Universal Serial Bus (USB) device functionality to the operating system. The Remote NDIS Specification is required as the definitive document. The other specifications listed at the end of this article are required for reference.
The "legacy-free" PC revolution will eliminate not only legacy connection ports such as serial, parallel, and PS/2 but also legacy expansion buses such as ISA and PCI in mainstream PCs. The resulting "sealed case" PCs will require either built-in networking support on the motherboard or support for network adapters on external buses. Microsoft has designed the Remote NDIS architecture to support external network adapters and provide native vendor-independent driver support in Windows.
USB ports exist on almost all new PCs and are natively supported in current versions of Windows. In addition to providing for external expansion and dynamic Plug and Play, USB allows devices to be self-describing. USB devices describe their functionality to the PC through a set of descriptors similar to those shown in the sample later in this article. Those descriptors include class codes that indicate to the operating system which drivers to load, even if there is no direct Vendor ID (VID) or Product ID (PID) match in the installed INF.
Remote NDIS is a simple extension of the well-understood and time-tested NDIS architecture. It allows for standard, in-the-box support for network adapters on external Plug and Play buses such as USB.
NDIS provides support for a wide range of functionality for traditional network adapters. The potentially large set of features of a network adapter is exposed and managed through NDIS-defined Object Identifiers (OIDs), which are traditionally serviced by the NDIS miniport driver for the adapter. Remote NDIS leverages this large body of specification and architecture work by routing OIDs to the device itself and eliminating the adapter-specific miniport driver. In a sense, the miniport driver is implemented in the RNDIS-compliant network adapter itself.
From the adapters point of view, Remote NDIS consists of a small set of control messages and a conduit for OIDs and data packets. Tables 1 through 3 list the Remote NDIS control messages and data messages. For details, see the Remote NDIS Specification.
Table 1: Control messages sent by the host PC to the adapter
| Message | Description |
REMOTE_NDIS_INITIALIZE_MSG | Initialize the adapter. |
REMOTE_NDIS_QUERY_MSG | Send a query OID. |
REMOTE_NDIS_SET_MSG | Send a set OID. |
REMOTE_NDIS_KEEPALIVE_MSG | Send every few seconds during idle periods to check that the device is still responsive. |
REMOTE_NDIS_RESET_MSG | Perform a soft reset on the adapter. |
REMOTE_NDIS_HALT_MSG | Halt the adapter. This is the only host control message that does not get a response. |
Table 2: Control messages sent by the adapter to the host PC
| Message | Description |
REMOTE_NDIS_INITIALIZE_CMPLT | Response to REMOTE_NDIS_INITIALIZE_MSG. |
REMOTE_NDIS_QUERY_CMPLT | Response to REMOTE_NDIS_QUERY_MSG. |
REMOTE_NDIS_SET_CMPLT | Response to REMOTE_NDIS_SET_MSG. |
REMOTE_NDIS_KEEPALIVE_CMPLT | Response to REMOTE_NDIS_KEEPALIVE_MSG. |
REMOTE_NDIS_RESET_CMPLT | Response to REMOTE_NDIS_RESET_MSG. |
REMOTE_NDIS_INDICATE_STATUS_MSG | Indicates that the Ethernet cable has been connected or disconnected. |
The Remote NDIS Specification lists the OIDs that the adapter must support. The specification also lists optional OIDs that the adapter can support for value-added features.
Table 3: Data message used by both PC and adapter to transmit packets
| Message | Description |
REMOTE_NDIS_PACKET_MSG | Transmit an Ethernet packet. |
In a working scenario, a Remote NDIS Ethernet adapter and a host PC would exchange messages as follows:
1. | A USB Remote NDIS Ethernet adapter is plugged in and initialized at the USB level. |
2. | The host then sends REMOTE_NDIS_INITIALIZE_MSG to initialize the adapter. |
3. | The adapter responds with REMOTE_NDIS_INITIALIZE_CMPLT, indicating its buffering and alignment constraints. |
4. | The host then uses REMOTE_NDIS_QUERY_MSG and REMOTE_NDIS_SET_MSG messages to send OIDs to query and configure the new network adapter and set its packet filter. |
5. | The adapter responds with REMOTE_NDIS_QUERY_CMPLT and REMOTE_NDIS_SET_CMPLT messages, respectively. |
6. | After the adapter is initialized, it begins sending REMOTE_NDIS_PACKET_MSG messages to return Ethernet packets from the network; and the host begins sending REMOTE_NDIS_PACKET_MSG messages to send Ethernet packets on the network. |
7. | If the host does not receive any packets from the adapter for a few seconds, it sends REMOTE_NDIS_KEEPALIVE_MSG to check that the adapter is still functioning; the adapter responds with REMOTE_NDIS_KEEPALIVE_CMPLT. |
8. | To halt the adapter (for example, when Windows shuts down or stops devices for hardware resource rebalancing), the host sends REMOTE_NDIS_HALT_MSG. |
Remote NDIS has a provision for combining multiple RndisPackets into a single bus transfer. On the adapter side, using multi-packet transmits is essential for good performance.
For each bus type, the control and data messages must be transmitted to the adapter in a different way. The Remote NDIS Specification includes a chapter for each supported bus that describes the low-level issues related to message transmission on that bus.
The USB chapter describes how control and data messages are addressed to device endpoints. A USB Remote NDIS device is required to implement the following endpoints:
| • | Two Bulk endpoints for read data and write data. |
| • | An Interrupt endpoint for device notifications. |
| • | The generic Control endpoint, as required for any USB device. This bi-directional Control endpoint is used for Remote NDIS control messages. |
The USB Remote NDIS microport driver continuously reads the Interrupt endpoint for device notifications. The only defined notification indicates that the host should read the Control endpoint. This scheme eliminates the need to post reads to the Control endpoint until there is something there to read.
The next section shows a sample set of descriptors that describe the Interface and Endpoint layout of a USB Remote NDIS Ethernet adapter.
The following is a sample set of descriptors for a USB Remote NDIS Ethernet Adapter. It includes a Communication Class interface and a Data Class interface, which is required for the adapter to qualify as a legal USB Communication Device Class (CDC) device even though it is a single-function device.
The Device Descriptor is returned independently. The Configuration descriptor and all following descriptors are returned as a single block in the order shown.
Control messages are sent on the Control endpoint. Notification messages are sent on the Interrupt In endpoint in the Communication Class interface. Data messages are sent on the Bulk In and Bulk Out endpoints in the Data interface. For brevity, string descriptors are not shown.
If any portion of this sample contradicts a controlling specification, the specification takes precedence.
Table A1: USB Device Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x12 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x01 | DEVICE descriptor |
2 | bcdUSB | 2 | 0x0110 | 1.1 - current revision of USB spec |
4 | bDeviceClass | 1 | 0x02 | Communication Device Class |
5 | bDeviceSubClass | 1 | 0x00 | Unused |
6 | bDeviceProtocol | 1 | 0x00 | Unused |
7 | bMaxPacketSize0 | 1 | 0x08 | Max packet size on control pipe |
8 | idVendor | 2 | 0xXXXX | Vendor ID |
10 | idProduct | 2 | 0xXXXX | Product ID |
12 | bcdDevice | 2 | 0xXXXX | Device Release Code |
14 | iManufacturer | 1 | 0x01 | Index of manufacturer string |
15 | iProduct | 1 | 0x02 | Index of product string |
16 | iSerialNumber | 1 | 0x03 | Index of device serial number string |
17 | bNumConfigurations | 1 | 0x01 | One configuration |
Table A2: USB Configuration Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x09 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x02 | CONFIGURATION descriptor |
2 | wTotalLength | 2 | 0x003E | Length of the total configuration block, including this descriptor and all following descriptors, in bytes |
4 | bNumInterfaces | 1 | 0x02 | Two interfaces |
5 | bConfigurationValue | 1 | 0x01 | ID of this configuration |
6 | iConfiguration | 1 | 0x00 | Unused |
7 | bmAttributes | 1 | 0x80 | Bus Powered |
8 | MaxPower | 1 | 0x64 | 200 mA |
Table A3: USB Communication Class Interface Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x09 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x04 | INTERFACE descriptor |
2 | bInterfaceNumber | 1 | 0x00 | Index of this interface |
3 | bAlternateSetting | 1 | 0x00 | Index of this setting |
4 | bNumEndpoints | 1 | 0x01 | One endpoint |
5 | bInterfaceClass | 1 | 0x02 | Communication Class |
6 | bInterfaceSubclass | 1 | 0x02 | Abstract Control Model |
7 | bInterfaceProtocol | 1 | 0xFF | Vendor-specific protocol |
8 | iInterface | 1 | 0x00 | Unused |
The following are class-specific descriptors of the USB Communication Class. As such, they follow the Communication Class Interface descriptor and precede any Endpoint descriptors for the interface.
Table A4: USB Communication Class Call Management Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x05 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x24 | CS_INTERFACE; i.e. applies to interface (not endpoint) |
2 | bDescriptorSubtype | 1 | 0x01 | Call Management Descriptor |
3 | bmCapabilities | 1 | 0x00 | Device does not handle Call Management itself. |
4 | bDataInterface | 1 | 0x01 | bInterfaceNumber of Data Class Interface |
Table A5: USB Communication Class Abstract Control Management Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x04 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x24 | CS_INTERFACE; that is, applies to interface (not endpoint) |
2 | bDescriptorSubtype | 1 | 0x02 | Abstract Control Management Descriptor |
3 | bmCapabilities | 1 | 0x00 | None |
Table A6: USB Communication Class Union Functional Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x05 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x24 | CS_INTERFACE; that is, applies to interface (not endpoint) |
2 | bDescriptorSubtype | 1 | 0x06 | Union Functional Descriptor |
3 | bMasterInterface | 1 | 0x00 | bInterfaceNumber of the Communication Class Interface |
4 | BSlaveInterface0 | 1 | 0x01 | bInterfaceNumber of Data Class Interface |
Table A7: Descriptor for Notification Endpoint
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x07 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x05 | ENDPOINT descriptor |
2 | bEndpointAddress | 1 | 0x81 | Endpoint 1 IN |
3 | bmAttributes | 1 | 0x03 | Interrupt Endpoint |
4 | wMaxPacketSize | 2 | 0x0008 | 8-byte maximum packet size |
6 | bInterval | 1 | 0x01 | Polling interval |
Table A8: USB Data Class Interface Descriptor
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x09 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x04 | INTERFACE descriptor |
2 | bInterfaceNumber | 1 | 0x01 | Index of this interface |
3 | bAlternateSetting | 1 | 0x00 | Index of this setting |
4 | bNumEndpoints | 1 | 0x02 | Two endpoints |
5 | bInterfaceClass | 1 | 0x0A | Data Class |
6 | bInterfaceSubclass | 1 | 0x00 | Unused |
7 | bInterfaceProtocol | 1 | 0x00 | Unused |
8 | iInterface | 1 | 0x00 | Unused |
Table A9: Descriptor for Bulk IN Endpoint
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x07 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x05 | ENDPOINT descriptor |
2 | bEndpointAddress | 1 | 0x82 | Endpoint 2 IN |
3 | bmAttributes | 1 | 0x02 | Bulk Endpoint |
4 | wMaxPacketSize | 2 | 0x0040 | 64-byte maximum packet size |
6 | bInterval | 1 | 0x00 | Unused |
Table A10: Descriptor for Bulk OUT Endpoint
| Offset | Field | Size | Value | Description |
0 | bLength | 1 | 0x07 | Size of this descriptor, in bytes |
1 | bDescriptorType | 1 | 0x05 | ENDPOINT descriptor |
2 | bEndpointAddress | 1 | 0x03 | Endpoint 3 OUT |
3 | bmAttributes | 1 | 0x02 | Bulk Endpoint |
4 | wMaxPacketSize | 2 | 0x0040 | 64-byte maximum packet size |
6 | bInterval | 1 | 0x00 | Unused |
| • | Hardware vendors should support USB Remote NDIS on their devices as described in this article and in the Remote NDIS Specification. |
| • | For questions and feedback related to USB Remote NDIS on Windows operating systems, send an e-mail message to rndisfb@microsoft.com |
Universal Serial Bus Specification, Revision 1.1, at
http://www.usb.org/developers/ ![]()
USB Communications Device Class Specificaiton, Revision 1.0, at
http://www.usb.org/developers/ ![]()
Remote NDIS Specification, Revision 1.0, at
http://www.microsoft.com/ hwdev/ tech/ network/default.mspx