world leader in high performance signal processing
Trace: » ethernet

Ethernet over USB (Gadget)

The USB peripheral will enumerate to the host as an Ethernet device, using the “usbnet” driver with Linux hosts or Microsoft's RNDIS driver with Windows hosts. Set it up like any other two-host Ethernet link; bridging it to the LAN from the USB host may be the easiest way to run. Linux hosts do this with CONFIG_BRIDGE and tools like “brctl”. Windows XP hosts have a GUI for bridging; it comes up when the RNDIS driver creates a second network link.

This driver can interoperate with hosts running Linux, MS-Windows, and other operating systems; if the OS can talk to a cable modem, it probably supports this driver. To do this, it supports several modes:

  • CDC Ethernet … the Communications Device Class (CDC) “Ethernet Model” protocol is the standard way for USB devices to expose Ethernet style functionality, with full specifications available at www.usb.org. Linux hosts prefer using CDC Ethernet; they use a class driver, and don't need vendor-specific updates. Most non-Linux hosts support CDC Ethernet, although to use it with MS-Windows you need a non-Microsoft driver.
  • CDC Subset … this minimalist protocol is used with controllers where hardware limitations (no altsetting support) prevent use of CDC Ethernet. Two examples of such controllers are the PXA25x and SuperH UDCs. The Linux “usbnet” driver handles this, but since it's not a standard class it might need vendor-specific updates. Few non-Linux hosts support this protocol.
  • RNDIS … when talking to MS-Windows hosts, RNDIS is used. RNDIS is Microsoft's analogue of CDC Ethernet, with complex frame encapsulation and its own internal RPC protocol. (This overview may help you, and a partial protocol specification is available. For example, some requests from Windows 2000 and XP are undocumented.) Use the Documentation/usb/linux.inf file (convert to DOS CRLF format) to “install” the driver; the driver is bundled in XP, and the url in linux.inf says where to get Microsoft's drivers for older Windows releases. For some step-by-step instructions with WinXP screenshots, see the gumstix wiki showing one way to use that “linux.inf” file. Don't forget to read the comments there, explaining how to shorcut past some needless complications in those instructions.

To better support DHCP, ZCIP, and related network autoconfiguration, you'll want to manage Ethernet addresses so that each peripheral reuses the same unique address every time it boots. You should assign those addresses using a registered IEEE 802 company id; this will also make the device appear to Linux hosts as an “ethN” interface, not as “usbN”. It's easy to do this without a separate ID PROM (or an initrd) if you're using boot firmware like U-Boot:

# manufacturing assigns Ethernet addresses; company id is xx:xx:xx
setenv eth_a_host    xx:xx:xx:01:23:45
setenv eth_a_gadget  xx:xx:xx:67:89:ac
setenv eth_i_vendor  "Great Stuff, LLC"
setenv eth_i_product "Our Cool Thing"
setenv eth_args             g_ether.host_addr=\$(eth_a_host)
setenv eth_args $(eth_args) g_ether.dev_addr=\$(eth_a_gadget)
setenv eth_args $(eth_args) g_ether.iManufacturer=\$(eth_i_vendor)
setenv eth_args $(eth_args) g_ether.iProduct=\$(eth_i_product)
# you can assign USB vendor/product/version codes too...
setenv add_eth_args setenv bootargs $(eth_args) \$(bootargs)
...
setenv bootcmd run add_eth_args\;bootm

Kernel config of Ethernet over USB (Gadget)

<M> Support for USB Gadgets 
<M>   Ethernet Gadget (with CDC Ethernet support)
[*]     RNDIS support (EXPERIMENTAL)

BF609:

[*] USB support  --->
    <*>   Support for Host-side USB
    <*>   Inventra Highspeed Dual Role Controller (TI, ADI, ...)
    <*>     Platform Glue Layer (Blackfin)  --->
    <*>   USB Gadget Support  --->
        USB Peripheral Controller  --->
            <*> Inventra HDRC USB Peripheral (TI, ADI, ...)
        <M>   USB Gadget Drivers
        <M>     Ethernet Gadget (with CDC Ethernet support)
        [*]       RNDIS support

Using Ethernet over USB (Gadget)

  • Install g_ether module with MAC address configuration. On the Windows host, you will be asked to install RNDIS driver for this new USB ethernet controller. Please use Document/usb/linux.inf (in Linux kernel source tree) as the RNDIS driver for Windows.
root:~> modprobe g_ether host_addr=00:dc:c8:f7:75:05 dev_addr=00:dd:dc:eb:6d:f1
usb0: Ethernet Gadget, version: May Day 2005
usb0: using musb_hdrc, OUT ep6out IN ep5in STATUS ep1in
usb0: MAC 00:dd:dc:eb:6d:f1
usb0: HOST MAC 00:dc:c8:f7:75:05
usb0: RNDIS ready
root:~> usb0: high speed config #2: 100 mA, Ethernet Gadget, using RNDIS
  • Setup usb0 with IP address. On the Windows Host, please set the USB ethernet controller's IP address for 192.168.1.56. After following usb0 setup, you will get a 480Mbps ethernet connection on Windows host.
root:~> ifconfig usb0 192.168.1.66 up
root:~> ifconfig
eth0      Link encap:Ethernet  HWaddr 00:E0:22:FE:B7:4F  
          inet addr:192.168.0.66  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
                    Interrupt:175 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:27 errors:0 dropped:0 overruns:0 frame:0
          TX packets:27 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          
usb0      Link encap:Ethernet  HWaddr 00:DD:DC:EB:6D:F1  
          inet addr:192.168.1.66  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
  • Ping from EZKIT-BF548 to Windows host to test the ethernet over USB connection
root:~> ping 192.168.1.56
PING 192.168.1.56 (192.168.1.56): 56 data bytes
64 bytes from 192.168.1.56: icmp_seq=0 ttl=128 time=1.8 ms
64 bytes from 192.168.1.56: icmp_seq=1 ttl=128 time=1.5 ms
64 bytes from 192.168.1.56: icmp_seq=2 ttl=128 time=1.5 ms
64 bytes from 192.168.1.56: icmp_seq=3 ttl=128 time=1.6 ms
64 bytes from 192.168.1.56: icmp_seq=4 ttl=128 time=1.5 ms
64 bytes from 192.168.1.56: icmp_seq=5 ttl=128 time=1.6 ms
64 bytes from 192.168.1.56: icmp_seq=6 ttl=128 time=1.7 ms

--- 192.168.1.56 ping statistics ---
7 packets transmitted, 7 packets received, 0% packet loss
round-trip min/avg/max = 1.5/1.6/1.8 ms
  • Telnet from Windows host PC to EZKIT-BF548 to test the ethernet over USB connection
C:\>telnet 192.168.1.66

BusyBox v1.4.1 (2007-11-26 16:53:35 CST) Built-in shell (msh)
Enter 'help' for a list of built-in commands.

root:~> ls
bin        fsg.block  lib        root       tmp
dev        home       mnt        sbin       usr
etc        init       proc       sys        var
root:~> uname -a
Linux blackfin 2.6.22.14-ADI-2007R2-pre-svn3935 #27 Wed Nov 28 14:58:48 CST 2007
 blackfin unknown
root:~>

Testing Ethernet over USB

  • ping -f -l50 -c 1000 192.168.1.66 (on host) … no errors or lossage
$ sudo ping -f -l50 -c 1000 192.168.1.66
PING 192.168.1.66 (192.168.1.66) 56(84) bytes of data.
                                                  
--- 192.168.1.66 ping statistics ---
1000 packets transmitted, 1000 received, 0% packet loss, time 110ms
rtt min/avg/max/mdev = 0.633/5.289/6.160/0.739 ms, pipe 50, ipg/ewma 0.110/4.773 ms
roc@roc-laptop:~/blackfin/usbtest$ sudo ping -f -l50 -c 1000 192.168.1.66
  • ping -f -l50 -c 1000 192.168.1.55 (on peripheral) … no errors or lossage (Currently, Busybox on EZKIT-BF548 doesn't support '-f' option):
root:~> ping -c 1000 192.168.1.55        
PING 192.168.1.55 (192.168.1.55): 56 data bytes
64 bytes from 192.168.1.55: icmp_seq=0 ttl=64 time=1.9 ms
64 bytes from 192.168.1.55: icmp_seq=1 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=2 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=3 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=4 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=5 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=6 ttl=64 time=0.3 ms
......
64 bytes from 192.168.1.55: icmp_seq=76 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=77 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=78 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=79 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=80 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=81 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=82 ttl=64 time=0.3 ms
64 bytes from 192.168.1.55: icmp_seq=83 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=84 ttl=64 time=0.4 ms
64 bytes from 192.168.1.55: icmp_seq=85 ttl=64 time=0.4 ms

--- 192.168.1.55 ping statistics ---
86 packets transmitted, 86 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.3/1.9 ms
  • preceding ping tests may be modified, interchanged, interspersed
  • also, try 'ping -c 1 -s SIZE' for sizes 1..4K
  • setup netperf testing for ethernet over USB
  • during both ping and netperf tests, also test unplugging
  • if your initial test host was Linux, rerun the same tests with an MS-Windows host (e.g. SP2); otherwise, rerun them with a Linux host.