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.
usb0 exists but NetworkManager says unmanaged Network management Check device management and udev properties before creating a profile.
Connection stops working after a reboot Interface name or temporary addressing Identify the host interface again and inspect addresses and profiles.
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 when it can supply sufficient power. If it cannot, consult the official USB gadget power guidance for a suitable powered hub; do not improvise multiple power sources. On a Zero-family board, use the micro-USB connector labelled USB, not PWR IN. Other boards have different device-capable ports; consult the same guidance 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.

Do not disconnect a cable solely for comparison if it also powers a running Pi. Instead, inspect host USB properties and system logs. An enumerated gadget can still lack carrier or an IP address; those are separate checks. After reboot, identify the device again: on our Pi 4B test the host's enx... interface name changed, so a profile bound to the old name no longer matched. A name alone does not prove device identity; see the manual guide's host identification and profile steps.

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

If the expected Pi interface exists but no NetworkManager profile activates it, inspect its management state and udev properties, replacing usb0 only if you have verified a different gadget interface:

nmcli -f GENERAL.NM-MANAGED,GENERAL.STATE device show usb0
udevadm info --query=property --path=/sys/class/net/usb0 | grep -E '^(DEVTYPE|NM_UNMANAGED)='

On the site's manually configured Pi 4B, NetworkManager reported usb0 as unmanaged and udev reported NM_UNMANAGED=1; creating a profile alone would not bring it up. This is an observed configuration, not a rule for every image or for the supported package. The NetworkManager documentation describes the udev property. For the manual path, the temporary address procedure provides a reversible test. Do not apply it over an active package-managed setup or another network manager.

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.

What was tested

On 28 October 2026, a Pi 4B running Debian 13-based Raspberry Pi OS and a Linux host were tested with the manual dwc2/g_ether setup. One connection powered the Pi without host enumeration; a different cable enumerated successfully, but the cause of the first failure was not established. With temporary static IP addresses, ping and host-key-verified SSH worked. After reboot, the Pi's temporary IP was gone and the host interface name changed; manually updating the settings restored SSH. See the full verification scope. The package-managed path, other boards, Windows and macOS were not tested in this experiment.

Donate