Linux USB ethernet gadget driver for RNDIS connection establishment


In this post I’ll document the RNDIS control message sequence between the USB RNDIS gadget driver and the device.

For those who are not familiar with RNDIS I refer you to Microsoft’s RNDIS page or the downloadable spec. In particular, you’ll need to become familiar with how RNDIS is mapped to USB. You’ll also need to have good familiarity with the USB.

This list summarizes the mapping:

  • USB Device
    • Interface #0
      • Endpoint #0 – Control endpoint, id 0x80 (IN) or 0x00 (OUT)
      • Endpoint #1 – Interrupt transfer, id 0x81 (IN)
    • Interface #1
      • Endpoint #3 – Bulk data transfer, id 0x03 (OUT)
      • Endpoint #2 – Bulk data transfer, id 0x82 (IN)

The above can be reproduced quite easily using the lsusb -v command.

Armed with that information I used Wireshark to sniff the USB bus. The USB capture is usually very verbose, I used the filter usb.data_flag == "present (0)" to get to the relevant packets.

Here’s the sequence of control messages that establish RNDIS communication. The first four bytes in the hex stream is the message id, in little endian order.

The REMOTE_NDIS_INITIALIZE_MSG sent by the driver over EP 0x00:

0000   02 00 00 00 18 00 00 00 01 00 00 00 01 00 00 00
0010   00 00 00 00 40 06 00 00

The REMOTE_NDIS_INITIALIZE_CMPLT message sent by the device over EP 0x80:

0000   02 00 00 80 34 00 00 00 01 00 00 00 00 00 00 00
0010   01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
0020   01 00 00 00 16 06 00 00 02 00 00 00 00 00 00 00
0030   00 00 00 00

A REMOTE_NDIS_QUERY_MSG message sent by the driver over EP 0x00. The OID is 0x00010202 (no official documentation):

0000   04 00 00 00 1c 00 00 00 02 00 00 00 02 02 01 00
0010   00 00 00 00 14 00 00 00 00 00 00 00

The REMOTE_NDIS_QUERY_CMPLT message sent by device as a reply, over EP 0x80. Status is RNDIS_STATUS_NOT_SUPPORTED:

0000   04 00 00 80 18 00 00 00 02 00 00 00 bb 00 00 c0
0010   00 00 00 00 00 00 00 00

The REMOTE_NDIS_QUERY_MSG message sent by the driver to discover the MAC address, over EP 0x00. The OID queried is OID_802_3_PERMANENT_ADDRESS:

0000   04 00 00 00 4c 00 00 00 03 00 00 00 01 01 01 01
0010   30 00 00 00 14 00 00 00 00 00 00 00 00 00 00 00
0020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0040   00 00 00 00 00 00 00 00 00 00 00 00

The REMOTE_NDIS_QUERY_CMPLT message sent by device with the MAC address, over EP 0x80. Query status is RNDIS_STATUS_SUCCESS:

0000   04 00 00 80 1e 00 00 00 03 00 00 00 00 00 00 00
0010   06 00 00 00 10 00 00 00 0a 00 3e 97 c5 df

The REMOTE_NDIS_SET_MSG message send by the driver over EP 0x00. The OID being set is OID_GEN_CURRENT_PACKET_FILTER, with the value NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_DIRECTED

0000   05 00 00 00 20 00 00 00 04 00 00 00 0e 01 01 00
0010   04 00 00 00 14 00 00 00 00 00 00 00 2d 00 00 00

The REMOTE_NDIS_SET_CMPLT message sent by the device in reply over EP 0x80:

0000   05 00 00 80 10 00 00 00 04 00 00 00 00 00 00 00

After the control message sequence is completed with success, rest of the communication is done using the REMOTE_NDIS_PACKET_MSG message (0x00000001) over the bulk transfer endpoints.

6 thoughts on “Linux USB ethernet gadget driver for RNDIS connection establishment

    1. Hi. An RNDIS device reports itself as CDC ACM with a communication interface class protocol of 0xFF. It is not ECM compatible.

  1. Dear dev,
    What all are RNDIS compatible devices?
    I have few queries:
    I am planning for windows device drivers development. I dont have hardware i am planning to build gadget driver on linux PC such that it will act as target device(PC). meanwhile if i connect target device to windows PC it need to detect so that i can develop windows driver right ?

    is RNDIS gadget driver will act as target device if i build with linux kernel?

    or any option you for suggestion?

    1. RNDIS devices are becoming increasingly rare, most Windows CE/Mobile devices use it.

      The good thing about RNDIS is that you don’t need to write a Windows driver, you just need to create a driver package with an INF file. Microsoft provides an INF template that you can reuse.

      If I understand you correctly, you want to build a Linux system that appears as a target device on Windows. The RNDIS gadget driver is not appropriate for doing that. Jungo have a USB RNDIS stack that might work.

  2. Thank you dev, I was looking for same information. I have came across Ethernet gadget driver with (ECM and EEM) if we build in linux kernel it will act as target device either for windows or linux host but i am looking for windows host.

    I thought similar stuff will work with RNDIS gadget driver on linux distribution to act device on windows. above stuff(RNDIS) how you did dev ?
    Can please guide to learn some interesting stuff on drivers like this.

    1. The above information was obtained by sniffing the USB bus using Wireshark. Google is your best friend to find more information on the subject.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s