Skip to content

Raspberry Pi USB Gadget Not Working: Missing usb0, dwc2, and g_ether

If a Raspberry Pi USB Ethernet gadget is not working, separate controller detection, gadget binding, host enumeration, IP addressing, and SSH. Adding a static IP cannot fix a USB device that the host has not detected. A loaded dwc2 module alone does not prove that an Ethernet gadget is active.

Use this diagnostic guide after choosing either the supported Trixie USB gadget workflow or the manual dwc2/g_ether setup. Keep Wi-Fi, Ethernet, or a local console available while diagnosing the USB path.

Raspberry Pi USB gadget failure map

Observation Layer to check First action
Pi powers on, host detects no new USB device Cable, connector, power, device mode Use a known data cable and the model's device-capable connector.
/sys/class/udc is empty USB device controller Check the board's supported setup and boot configuration.
Controller exists, gadget cannot bind Gadget ownership/configuration Look for another gadget already using the controller.
Host sees a USB device but no Ethernet adapter USB descriptors or host driver Inspect the host's USB and network-device views.
Network adapter exists, no usable address DHCP, sharing, or manual profile Inspect addresses on both sides.
IP works, .local fails mDNS Use the numeric address and diagnose discovery separately.
Network works, SSH fails SSH server or credentials Check the configured account, SSH service, and exact error.

1. Check the cable and connector

A charging cable can power the Pi while carrying no USB data. Test with a known working data cable and a direct host connection before adding hubs. On a Zero-family board, use the micro-USB connector labelled USB, not PWR IN. Other boards have different device-capable ports; consult the official USB gadget announcement and compatibility details rather than assuming a USB-A host port can become a device.

If the Pi repeatedly disconnects or reboots, inspect power as well as software:

vcgencmd get_throttled
journalctl -b -k --no-pager | grep -Ei 'voltage|usb|reset|disconnect'

A laptop port may not supply enough power for a Pi plus peripherals. Use a supported power arrangement rather than improvising two independent supplies.

2. Inspect the USB device controller on the Pi

Run these on the Pi, not the host computer:

1
2
3
4
ls -1 /sys/class/udc
ip -brief link
lsmod | grep -E 'dwc2|g_ether|libcomposite|usb_f_'
journalctl -b -k --no-pager | grep -Ei 'udc|dwc2|g_ether|gadget'

An empty UDC directory means this kernel has not registered a USB device controller. Module lists are supporting evidence: a driver built into the kernel will not appear in lsmod. Do not conclude that it is missing from lsmod alone.

Read the state of each available controller:

1
2
3
4
5
for controller in /sys/class/udc/*; do
    [ -d "$controller" ] || continue
    printf '%s: ' "${controller##*/}"
    cat "$controller/state"
done

configured indicates a configured USB connection. If the controller exists but the host has not configured it, investigate the cable, host detection, gadget binding, and logs before assigning IP addresses.

3. Check which setup owns the gadget

Supported Trixie package

Verify the OS and package:

cat /etc/os-release
dpkg-query -W rpi-usb-gadget

The supported rpi-usb-gadget workflow uses g_ether internally. Seeing that module is expected, not proof of a conflict. A conflict can arise when you also retain an independent manual boot configuration or a custom ConfigFS gadget for the same controller. Return to the Trixie setup guide and use one deliberate configuration path.

Manual dwc2/g_ether setup

Inspect the active kernel command line and boot declarations:

1
2
3
cat /proc/cmdline
grep -nE 'dwc2|otg_mode' /boot/firmware/config.txt
cat /boot/firmware/cmdline.txt

For the manual setup described on this site, check dtoverlay=dwc2,dr_mode=peripheral and modules-load=dwc2,g_ether. Keep cmdline.txt on one physical line, and confirm the entries apply to your model and active configuration section. Compare against the manual setup guide before editing.

Custom ConfigFS gadget

If you deliberately created a composite gadget, inspect its UDC assignment:

1
2
3
4
5
for assignment in /sys/kernel/config/usb_gadget/*/UDC; do
    [ -f "$assignment" ] || continue
    printf '%s: ' "$assignment"
    cat "$assignment"
done

The Linux ConfigFS documentation explains that a gadget must be bound to a UDC for the host to enumerate it. An empty assignment is unbound. A directory missing from this check can also mean ConfigFS is not mounted or you are using a module-based gadget; it does not by itself prove failure. Do not unbind an active gadget while it is your only remote-access path.

4. Check USB enumeration on the host

On a Linux host, compare these before and after connecting the cable:

1
2
3
lsusb
ip -brief link
nmcli device status

The host-side network name might be enx..., not usb0. On macOS, inspect USB devices in System Information and network services in System Settings. On Windows, inspect Device Manager for the new USB and network device; use the official package's documented driver procedure when required.

If the host sees USB but no network interface, resolve the host driver or gadget-function problem before configuring DHCP. The supported package negotiates the host's Ethernet function; manually switching between unrelated gadget recipes can obscure the original failure.

5. Diagnose addresses, then SSH

On the Pi, inspect all interfaces rather than assuming their name:

1
2
3
ip -brief address
ip route
nmcli connection show --active

Inspect the host's USB Ethernet address as well. For a manual static setup, both ends need addresses on the intended subnet. For package-managed Trixie setup, use the package's documented DHCP/internet-sharing arrangement; do not layer the manual guide's static profile on top without a plan. The official package documents 10.12.194.1 as a fallback when host sharing is disabled, not a universal address for every gadget.

If numeric addressing works, try SSH with the username you created:

ssh your-user@PI_USB_ADDRESS

Connection refused means something different from a timeout or Permission denied. Use the headless troubleshooter to diagnose the observed SSH error. After a fix, reconnect once and confirm the link survives a planned reboot before making USB your normal recovery path.