USB Gadget/Ethernet

From linux-sunxi.org
Jump to navigation Jump to search

USB Ethernet support

This allows ethernet emulation over USB, allowing for all sorts of nifty things like SSH and NFS in one go plus charging over the same wire, at higher speeds than most Wifi connections.

Kernel support

Mainline kernel (via configfs)

The configfs approach allows you to configure the device dynamically from user-space.Thereby, additional configuration needs to be done to bring up the gadget compared with precomposed configurations.

(Instructions below were tested on A20 with kernel 5.9.0.)

The RNDIS gadget with configfs requires a number of menuconfig options being enabled:

    Device Drivers  --->
        [*] USB support  --->
        <M> Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)
                MUSB Mode Selection (Dual Role mode)  --->
                *** Platform Glue Layer ***
            <M> Allwinner (sunxi)
                *** MUSB DMA mode ***
            [*] Disable DMA (always use PIO)
        USB Physical Layer drivers  --->
            <M> NOP USB Transceiver Driver
        <M>   USB Gadget Support  --->
            <M>   USB Gadget functions configurable through configfs
            [*]     RNDIS
Sticky-note-pin.png Note: You need to select both "Inventra Highspeed Dual Role Controller" and "NOP USB Transceiver Driver" before the required "Allwinner (sunxi)" option (CONFIG_USB_MUSB_SUNXI) becomes available.

Now you can compile the kernel and modules. For details, you can refer to our manual build howto.

Mainline kernel (via Precomposed Configurations)

See http://thread.gmane.org/gmane.comp.hardware.netbook.arm.sunxi/19214/focus=19215

(Instructions below were tested on A20 with kernel 4.4.6.)

For Allwinner SoCs based on the sun4i controller (CONFIG_PHY_SUN4I_USB=y), the "MUSB" (Multipoint Highspeed Dual-Role Controller) driver provides the OTG / gadget functionality. For successful operation, a number of Kconfig options need to be enabled:

CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_MUSB_DUAL_ROLE=y
CONFIG_USB_MUSB_SUNXI=m
CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_PHY=y
CONFIG_NOP_USB_XCEIV=m

(Substitute "y" for "m" where desired, if you do not wish modules to be built and want the drivers compiled-in instead.)

With menuconfig this looks like

    Device Drivers  --->
        [*] USB support  --->
        <M> Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)
                MUSB Mode Selection (Dual Role mode)  --->
                *** Platform Glue Layer ***
            <M> Allwinner (sunxi)
                *** MUSB DMA mode ***
            [*] Disable DMA (always use PIO)
        USB Physical Layer drivers  --->
            <M> NOP USB Transceiver Driver
Sticky-note-pin.png Note: You need to select both "Inventra Highspeed Dual Role Controller" and "NOP USB Transceiver Driver" before the required "Allwinner (sunxi)" option (CONFIG_USB_MUSB_SUNXI) becomes available.

You'll probably also want to select

        <*> USB Gadget Support

and any desired gadget drivers on top of that.

Proceed with compiling and installing your kernel and its corresponding modules (for assistance check our howto).

MBOX icon information.png If you compiled the MUSB driver as module(s), make sure to load those first - before you attempt to use any of the gadget drivers:
modprobe sunxi

Upon successful initialization the kernel will report something similar to:

[   33.950832] usb_phy_generic.0.auto supply vcc not found, using dummy regulator
[   33.951799] musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn)
[   33.951833] musb-hdrc: MHDRC RTL version 0.0 
[   33.951872] musb-hdrc: 11/11 max ep, 5184/8192 memory
[   33.952312] musb-hdrc musb-hdrc.1.auto: MUSB HDRC host driver
[   33.952355] musb-hdrc musb-hdrc.1.auto: new USB bus registered, assigned bus number 5
[   33.956664] hub 5-0:1.0: USB hub found
[   33.956828] hub 5-0:1.0: 1 port detected

After that, you should be able to use the USB gadget drivers/modules (g_ether, g_mass_storage, ...) as described below.

sunxi-3.4

Currently, the g_ether module is not compiled as part of our kernel configuration.

To enable this, follow the kernel building information of our manual build howto. But then after making defconfig, either run:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

Then trawl down the options and set the "Ethernet Gadget" to "m":

    Device Drivers  --->
        USB support  --->
            <*>    USB Gadget Support  --->
                <m>    Ethernet Gadget (with CDC Ethernet support)
            <*>    NOP USB Transceiver Driver
            [*]    SUNXI USB2.0 Dual Role Controller support --->
                [*]    Sunxi USB2.0 Manager
                       USB0 Controller support (otg support) --->
                           (*) otg support

Or just run:

./scripts/config -m CONFIG_USB_ETH -e CONFIG_USB_ETH_RNDIS -e CONFIG_USB_OTG_UTILS -e CONFIG_NOP_USB_XCEIV 
 -e CONFIG_USB_SW_SUNXI_USB -e CONFIG_USB_SW_SUNXI_USB_MANAGER -e CONFIG_USB_SW_SUNXI_USB0_OTG

You can now continue following our manual build howto to continue kernel compilation and installation.

Note that for sun4i devices (A10), you also need to enable SoftWinner SUNXI USB peripheral controller in order to enable high-speed operation for gadget- otherwise it will be limited to full-speed only.

    Device Drivers  --->
        USB support  --->
            <*>     USB Gadget Support --->
                <m> SoftWinner SUNXI USB Peripheral Controller 

Loading the driver (on the device)

configfs

The configfs approach requires a number of modules being loaded:

modprobe sunxi
modprobe configfs
modprobe libcomposite
modprobe u_ether
modprobe usb_f_rndis

If you see nothing is printed to the kernel ring buffer, it is just normal since the gadget is not enabled until configurations under configfs are done.

Precomposed Configurations

We should now be able to run:

modprobe g_ether

successfully. We can then make this module autoload by adding it to /etc/modules.

Now, so that g_ether doesn't randomly generate a new id every reboot, stick the following in /etc/modprobe.d/g_ether.conf:

options g_ether host_addr=00:11:22:33:44:55

g_ether should've just generated a pair of addresses for you, so replace 00:11:22:33:44:55 with the outcome of:

 dmesg | grep "HOST MAC"

We can also use dev_addr option to set device MAC address.

Configuring the gadget under configfs

MBOX icon information.png This chapter is for configfs approach only. Users who adopt precomposed configurations should skip following steps.

Some configuration must be done to set up the gadget properly.

cd /sys/kernel/config/usb_gadget
mkdir g1
cd g1
echo "0x1d6b" > idVendor
echo "0x0104" > idProduct
mkdir functions/rndis.rn0
mkdir configs/c1.1
ln -s functions/rndis.rn0 configs/c1.1/

Here "0x1d6b" for idVendor stands for Linux Foundation and "0x0104" for idProduct stands for Multifunction Composite Gadget. In case your host can not identify these ids to recognize your device properly, you may need manually install RNDIS driver on your host for your device.

Finally, the gadget can be enabled with

echo <udc name> > UDC

where <udc name> is one of those found in /sys/class/udc/* which is musb-hdrc.1.auto on my device.

Similarly, the gadget can be disabled with

echo "" > UDC

You can use this to disconnect or reconnect your device to the host logically.

Configuring the device's networking

Ubuntu/Debian

Without network manager

Stop networkmanager:

 stop network-manager 

To prevent network-manager from starting, run:

echo "manual" > /etc/init/network-manager.override

Now add the following to /etc/network/interfaces:

auto usb0
iface usb0 inet static
	address 192.168.0.2
	netmask 255.255.255.0

To manually activate the interface and set an IP (NOTE: if configured with ip from iproute2 it will not work):

     ifconfig usb0 up
     ifconfig usb0 192.168.0.2

Setting up the host

You can convince networkmanager to connect automatically to a specific MAC address, and then you need to hardcode the address to 192.168.0.1 for this connection.

If all goes well, you should now be able to just plug in the USB cable.

See also

Experiments with USB ethernet and H3 @ Armbian forums: