Skip to content

Manual USB Ethernet Gadget with dwc2 and g_ether

This advanced guide manually configures dwc2 and g_ether so a Raspberry Pi appears as a USB Ethernet adapter. Use it for custom or older images where you deliberately cannot use the supported package.

For current Raspberry Pi OS Trixie on a supported board, start with USB Gadget Mode 2026. The rpi-usb-gadget package handles host-specific USB networking and optional internet sharing without maintaining the manual kernel-command-line setup below.

Use this page only when you need explicit static addressing, custom images, or control of the low-level gadget configuration. Do not enable this manual path and rpi-usb-gadget at the same time; both need ownership of the USB device controller.

Check model and connector support first

Raspberry Pi Zero, Zero W, and Zero 2 W are the simplest targets: use the micro-USB port labelled USB, not PWR IN. Raspberry Pi 4 can use peripheral mode on its USB-C connector, but powering and connecting it safely is more complicated. The main USB-A ports are host-only. This guide does not target Pi 5.

Compatibility Matrix

Model Gadget connector Notes
Zero / Zero W / Zero 2 W Micro-USB USB port Recommended; power and data over one suitable cable
Pi 4 Model B USB-C power/OTG port Peripheral mode supported; plan a safe power arrangement
Compute Module Carrier-board USB device port Depends on carrier-board wiring
Pi 3/2/1 Model B USB-A None USB-A ports are connected as hosts
Pi 5 Not covered here Use current model-specific OTG documentation

Use a known data cable. Many charging cables contain no data conductors and cause the most common detection failure.

1. Enable the USB Device Controller

On Trixie and Bookworm, edit /boot/firmware/config.txt:

sudoedit /boot/firmware/config.txt

Add:

dtoverlay=dwc2,dr_mode=peripheral

For a Pi 4, ensure otg_mode=1 is not forcing the connector into host mode. Raspberry Pi's OTG guidance describes the separate USB-C controller.

2. Load the Ethernet Gadget at Boot

/boot/firmware/cmdline.txt must remain one physical line. Add modules-load=dwc2,g_ether after rootwait without adding a newline:

... rootwait modules-load=dwc2,g_ether ...

Before rebooting, make sure SSH is enabled and the login user exists. Raspberry Pi OS no longer assumes a default pi account.

sudo systemctl enable ssh
sudo reboot

3. Confirm Gadget Mode on the Pi

After reboot, connect through Wi-Fi or a local console for the first check:

1
2
3
4
lsmod | grep -E 'dwc2|g_ether|usb_f_ecm'
ip link show usb0
cat /sys/class/udc/*/state 2>/dev/null
journalctl -b -k | grep -Ei 'dwc2|g_ether|usb0'

usb0 may exist only after the gadget is bound. A UDC state such as configured indicates that a host has enumerated it.

4. Assign a Stable Address with NetworkManager

Create a profile on the Pi:

sudo nmcli connection add \
  type ethernet \
  ifname usb0 \
  con-name usb-gadget \
  ipv4.method manual \
  ipv4.addresses 192.168.7.2/24 \
  ipv6.method disabled

sudo nmcli connection modify usb-gadget connection.autoconnect yes
sudo nmcli connection up usb-gadget
ip address show usb0

If a profile already exists, modify it instead of creating a duplicate:

nmcli connection show
sudo nmcli connection modify usb-gadget ipv4.addresses 192.168.7.2/24

5. Configure the Host Computer

The host-side interface name is not necessarily usb0. Linux often names it enx followed by a MAC address.

1
2
3
4
5
6
nmcli device status
host_if=$(nmcli -t -f DEVICE,TYPE device | awk -F: '$2=="ethernet" {print $1}' | tail -1)
sudo nmcli connection add type ethernet ifname "$host_if" \
  con-name raspberry-pi-usb ipv4.method manual \
  ipv4.addresses 192.168.7.1/24 ipv6.method disabled
sudo nmcli connection up raspberry-pi-usb
1
2
3
ip link
sudo ip address add 192.168.7.1/24 dev <host-interface>
sudo ip link set <host-interface> up

Open System Settings → Network, select the new USB Ethernet interface, choose manual IPv4, and assign 192.168.7.1 with subnet mask 255.255.255.0.

Open ncpa.cpl, find the newly enumerated USB Ethernet adapter, and configure IPv4 as 192.168.7.1/24. Driver behaviour differs between Windows versions; a composite ConfigFS gadget with RNDIS may be required if g_ether is not recognised.

6. Test and Connect with SSH

From the host:

ping -c 3 192.168.7.2
ssh <your-user>@192.168.7.2

If Avahi is installed and multicast DNS is permitted on both ends, this may also work:

ssh <your-user>@raspberrypi.local

Use the numeric address for troubleshooting because .local name resolution is a separate service.

Optional: Share the Host's Internet Connection

On a NetworkManager Linux host, change the USB profile to shared mode:

1
2
3
4
sudo nmcli connection modify raspberry-pi-usb \
  ipv4.method shared ipv4.addresses 192.168.7.1/24
sudo nmcli connection down raspberry-pi-usb
sudo nmcli connection up raspberry-pi-usb

On the Pi, switch the profile to automatic addressing if you want the host to supply DHCP:

1
2
3
sudo nmcli connection modify usb-gadget ipv4.method auto ipv4.addresses ""
sudo nmcli connection down usb-gadget
sudo nmcli connection up usb-gadget

Do not configure both ends as connection-sharing DHCP servers.

Security Hardening

  • Use SSH keys and disable password authentication after confirming key login.
  • Do not bridge the gadget directly to an untrusted network.
  • Keep the static subnet unique; avoid collision with VPNs or home networks using 192.168.7.0/24.
  • Remove g_ether from cmdline.txt when gadget access is no longer needed.
  • Avoid --privileged containers or broad device permissions merely to access usb0.

Troubleshooting

Nothing appears on the host

Try another known data cable and host port. Verify the cable is connected to the Zero's USB connector. Check dtoverlay=dwc2,dr_mode=peripheral, confirm cmdline.txt is one line, and inspect the kernel journal.

The host sees USB but no network adapter

Check the host driver. Linux and macOS generally support CDC Ethernet. Windows may need a compatible RNDIS configuration. Confirm the USB device with lsusb, System Information, or Device Manager.

usb0 exists but ping fails

Run ip address on both ends, confirm the /24 prefix, temporarily inspect firewall rules, and make sure only one connection profile manages each interface.

The Pi repeatedly disconnects

Suspect power or cable quality first. A Pi 4 should not rely on an underpowered laptop port. Check for undervoltage messages:

vcgencmd get_throttled
journalctl -b -k | grep -i voltage

Install iperf3 on both machines and record the model, cable, host OS, and CPU load:

1
2
3
4
5
6
# Raspberry Pi
iperf3 --server

# Host
iperf3 --client 192.168.7.2 --time 30 --get-server-output
ping -c 100 192.168.7.2

Do not publish a single throughput value without the cable type, Pi model, host controller, and test duration.

FAQ

Can one cable provide both power and SSH?

Yes on Pi Zero-family boards with a capable host port and a proper data cable. Power demands and host port limits make separate power safer for larger models.

Can USB serial and Ethernet be enabled together?

Yes, but use ConfigFS to build a composite gadget rather than loading several legacy gadget modules independently.

Why is the interface name different on every host?

Predictable network naming may derive the name from the gadget MAC address. Identify the new interface with NetworkManager or ip link instead of assuming usb0.