
Awhile after completing my PINGPONG-CDC project, I upgraded some of my computers to Vista to discover that networking over serial cables was no longer supported. This meant I could not use my PINGPONG-CDC project for an Internet connection. This made me think that perhaps serial replacement was not the correct model to use and that maybe Ethernet was better.
Initially, I considered writing my own Windows device driver, but then I learned about RNDIS which is the standard USB Ethernet protocol for Windows. Windows includes an in box driver for Windows XP and Vista so I decided maybe this was a better choice.
I decided to reuse old hardware and simply write a new firmware for the PINGPONG-CDC device. I also could reuse the FHSS code from that project.
One major limitations of the 18f2550 hardware is that it does not have enough RAM to buffer an entire Ethernet frame. It’s necessary to stream the frame to the PC over USB as soon as part of the frame is received without buffering the entire frame. Since an entire frame can’t be buffered, it’s impossible to implement a traditional checksum over the entire frame so the underlying wire protocol needs to perform integrity checks and retransmissions.
To keep things simple, the XE1205-RNDIS project only supports two nodes in the virtual Ethernet subnet. One node is the master and the other node is the slave just like the PINGPONG-CDC project. Essentially, XE1205-RNDIS is still a serial replacement with error correction and detection that looks like an Ethernet network to Windows.
The hardware for the XE1205-RNDIS project is identical to the PINGPONG-CDC project with one notable exception. I upgraded the PIC from a revision A3 18f2550 to a revision B6 18f2553. The A3 has a silicon bug that I hit during this project. If long USB transfers are used as required by RNDIS and the PIC is connected to some laptops, the PIC will hit random bus turnaround time errors. A workaround for this is to insert a USB hub between the laptop and the PIC but I thought it was easier to upgrade to a newer revision. I chose the 18f2553 because Microchip Direct was out of the 18f2550s at the time and I thought I could use the higher resolution A/D for other projects.
The major change to the wire protocol is to add error detection and correction. This is needed for two reasons. The first is that wired Ethernet includes a checksum at the end of the frame, and RNDIS assumes that this checksum has been verified before the hardware passes the frame. I believe Windows relies on the Ethernet checksum for frames arriving from the same subnet such as DHCP and ARP traffic. UDP and TCP have a separate checksums on top of the Ethernet checksum. The second reason detection and correction is required is that when the wireless connection approaches the maximum distance the 1514 byte frame will likely have multiple errors in it which means no frames would make it over the link if the Ethernet frame checksum alone was used.
The new packet format adds an ACK bit, a data toggle bit, and a sum based 16bit checksum. These objects are used independently for both directions of the half duplex link. The master to slave link has it’s own data toggle and checksum, with the ACK being sent in the slave to master direction. The opposite is true for the slave to master direction.
The data toggle and ACK ensure that a data packet is received exactly one time. The data toggle is changed on the sender when an ACK is received and on the receiver when a new packet is received. If the data is lost, an ACK will not be sent and the data will be retransmitted. If the ACK is lost, the sender will resend with the old data toggle. When the receiver receives the packet, the data toggle will not match and the data will be discarded. An ACK will still be returned so that the sender can toggle it’s data toggle and send new data, but the data toggle on the receiver remains unchanged.
The maximum size of a USB endpoint is 64 bytes. Some cases are simplified if the endpoint buffer size is the same as the maximum packet size in the wire protocol. As will be explained later, it was necessary to add a data type to the packet in the RNDIS specific code so the maximum data size in the packet was extended to 65 bytes from the original 64 bytes.
| Offset | Size | Function |
| None | 1 | Preamble - single 0xAA |
| 0 | 4 | Packet Identifier |
| 4 | 1 | Data payload size not including headers or trailers |
| 5 | 1 | 2's completement of payload size |
| 6 | 1 | Flags (includes ACK and data toggle bits ) |
| 7 | N=0 to 65 | Payload data |
| N+7 | 2 | Checksum (sum of offset N to N+6) |
RNDIS adds another layer to the wire protocol. It’s necessary to indentify the beginnings of each frame and the frame length. To do this, the data in the packet can be one of two things. The first is the byte 0xAF followed by a 16bit frame size. The other is the byte 0xFA followed by up to 64 bytes of frame data. By identifying the start of frames, it’s possible to resynchronize the sender and receiver in the case of a link disconnection. If the receiver connects in the middle or a frame, it can discard all the packets until the next frame is received.
The software components are the same for XE1205-RNDIS as for PINGPONG-CDC. The INF file is different, but the PINGPONG-CONTROL application for configuring the LINK ID and the setting the mode is the same. See PINGPONG-CDC for more details.
| Directory | Function |
| inc | General Include Directory |
| rf-networking/XE1205-RNDIS | Modem firmware(Build first) |
| Drivers/XE1205-RNDIS | INF and WinUSB resources |
| usbdrvclilib | C++ WinUSB wrapper(Build second) |
| deviceutils/pingpong-control | Modem configuration utility(Build third) |
RNDIS in general, is based on the CDC abstract control model USB class. Extensions are implemented as encapsulated commands. The driver sends a send encapsulated command request, the firmware processes the command asynchronous, then the firmware notifies the driver through the CDC notification endpoint. The driver will then send a get encapsulated response request. RNDIS is a direct extension of NDIS, so it exposes most of the configuration through OIDs which are essentially device properties. Frame data is sent and received via the CDC data endpoints. A frame consists of a header, some optional data such as TCP checksums, and the actual frame data.
RNDIS has a unique feature in that an entire Ethernet frame must be contained inside the same USB transaction which means exactly 64 bytes needs to be sent and received for each USB transaction until the end of the frame which can then be a short transaction. This added considerable complexity to the firmware as some buffering is required between the sender and receiver.
Testing for this project was considerably more difficult that any other USB project I have done. Making it past the network identification logic in Vista was itself challenging. What I found necessary was to disable all the network protocols for the adapter in Windows Connection Manager and install a driver called NDISPROT from the Windows WDK. This driver makes it possible to send and receive individual Ethernet frames of arbitrary size using an included utility called uiotest.exe. Only when I was able to reliably send and receive individual frames did I enable TCP/IP and test browsing the Internet.
For this project, I found having a USB analyzer essential. I used two different analyzers for this project. SnoopyPro which is a freeware software analyzer and the MQP Packet Master USB12 hardware analyzer. The MQP was great because sometimes SnoopyPro will simply report URB level errors and the MQP allowed me to see exactly what was happening.
I ran some benchmarks of downloading large files off the Internet, and XE1205-RNDIS can reliably sustain about 34kbps which is on the order of telephone modem speed. Some of the problem is inefficiencies in the wire protocol and some of it is simply that the 18f2553 doesn’t quite have enough horsepower.
RNDIS Documentation from Microsoft
SnoopyPro - Freeware Software Analyzer
MQP Packet Master USB12 - Hardware USB Analyzer