Project

General

Profile

Enabling USB RNDIS Support

RNDIS support allows a PC to talk to a Linux-based embedded system over USB by making the embedded system look like a USB attached Ethernet adapter.

In order to enable this feature, you must first enable RNDIS in your Linux kernel. This involves compiling the kernel, which is described elsewhere in this wiki.

Start the Linux Kernel Configuration tool:

$ make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm menuconfig

Select Device Drivers from the main menu.

...
...
Power management options --->
[ ] Networking support --->
Device Drivers --->
File systems --->
Kernel hacking --->
...
...

Select USB support as shown here

...
...
<*> Sound card support --->
[*] HID Devices --->
[*] USB support --->
<*> MMC/SD/SDIO card support --->
...
...

Go to USB Gadget Support as shown here

...
...
< > USB YUREX driver support
<*> USB Gadget Support ---> * OTG and related infrastructure *
< > GPIO based peripheral-only VBUS sensing 'transceiver'
...
...

Select Inventra HDRC USB Peripheral as shown here

...
...
(2) Maximum VBUS Power usage (2-500 mA)
(2) Number of storage pipeline buffers
<*> USB Peripheral Controller (Inventra HDRC USB Peripheral (TI, ADI, ...)) --->
< > USB Gadget Drivers
...
...

Select Ethernet Gadget as shown here

...
...
<*> USB Peripheral Controller (Inventra HDRC USB Peripheral (TI, ADI, ...)) --->
< > USB Gadget Drivers
...
&lt;M&gt; Ethernet Gadget (with CDC Ethernet support)
[*] RNDIS support
[ ] Ethernet Emulation Model (EEM) support
...
...

Once this is done, save the configuration and compile the kernel and modules.

RNDIS gadget driver module can be inserted using $ insmod g_ether.ko

You can, alternatively, change the <M> for USB Gadget Drivers to <*> and this will compile the drivers into the kernel, so you won't have to load the module. You will need to first de-select all child modules under USB Gadget Drivers, then press space bar over USB Gadget Drivers to change the <M> to a <*>.

The RNDIS Gadget driver will create an Ethernet device by the name usb0. You need to assign an IP address to the device and bring up the device. The typical command for that would be:
$ ifconfig usb0 <IP_ADDR> netmask 255.255.255.0 up

This command will start up the Ethernet link with the listed IP_ADDR IP address. Unfortunately, the PC will try to get a DHCP address and when it fails it will use a default IP address that will likely not be on the same subnet as the one you choose for IP_ADDR.

One way to solve this is to set up a DHCP server on the ARM. Busybox includes udhcpd, which is a DHCP server. To set this up you need to do a few things...

First, create a udhcpd.conf file in /etc. This file sets the IP address and range which will be used to give addresses to clients (the PC). As a minimum, you will need a start address. Here is an example of this file:

start 10.199.199.100
end 10.199.199.102
option subnet 255.255.255.0
interface usb0
lease_file /tmp/udhcpd.leases

You will then need to tell Linux to start up the DHCP server on bootup.

systemd makes starting up dhcp very difficult -- I have not figured out how to do that...

Here is the approach I used:

Create /etc/network/if-up.d/start_udhcpd with the following contents:

#!/bin/sh
if [ $IFACE usb0 ] && [ $MODE start ]
then
touch /tmp/udhcpd.leases
/usr/sbin/udhcpd /etc/udhcpd.conf
fi

Next create /etc/network/if-down.d/stop_dhcp with the following contents:

#!/bin/sh
if [ $IFACE usb0 ] && [ $MODE stop ]
then
pkill udhcpd
fi
exit 0

Now, in your application start script (where you typically load drivers and the FPGA), add the following:

ifdown usb0
ifup usb0

Now, when you run your start script, dhcp will run.

Add picture from clipboard (Maximum size: 500 MB)