Skip to content

Turn your Raspberry Pi into a USB Ethernet gadget (CDC-ECM/RNDIS) for headless networking, Internet sharing, and remote development over a single USB cable.

License

Notifications You must be signed in to change notification settings

raspberrypi/rpi-usb-gadget

Repository files navigation

Raspberry Pi USB Gadget

This package turns your Raspberry Pi into a USB Ethernet gadget using the kernel’s g_ether driver. On the host it appears as:

  • CDC-ECM on Linux and macOS
  • RNDIS on Windows (use the included Raspberry Pi USB RNDIS driver for fastest onboarding)

It’s designed for headless setups and for places where Wi-Fi isn’t available or communication between network devices is restricted. With a single Micro USB or USB-C cable you get a network link that’s ideal for SSH, file copy, and remote dev (e.g. VS Code), with very low latency.

What’s new / how it behaves

  • Auto client/shared switching (NetworkManager): We install two NM profiles on the gadget interface (default usb0) and run a small watcher service:

    • USB Gadget (client): Pi is a DHCP client of the host (used when host Internet Connection Sharing is detected; typical host gateways: 192.168.137.1, 192.168.2.1, 10.42.0.1).
    • USB Gadget (shared): Pi provides DHCP + NAT to the host at 10.12.194.1/28.

    The watcher automatically flips between these modes based on whether an ICS gateway is reachable.

  • USB Ethernet only by default: We do not enable a serial gadget (/dev/ttyGS0) by default.

  • Host support: Windows (with RNDIS driver), macOS, and Linux hosts.

    Make sure to have any VPNs disabled on the host, as they can interfere with the local networking!

Features

  • Plug-and-play: Just connect a Micro USB or USB-C cable; NM profiles and the watcher handle networking.

  • Headless operation: No Wi-Fi, monitor, or keyboard required.

  • Low latency: Typically sub-millisecond round-trips on the USB link.

  • Internet sharing either way:

    • Via host ICS (Pi is client), or
    • Via Pi shared (Pi serves DHCP/NAT at 10.12.194.1/28).
  • Wide compatibility: Works on Raspberry Pi Zero/Zero 2 W, 3A+, 4B, 5, and similar models with USB device mode.

Tip: If you attach multiple Pis to the same host, prefer host ICS (so each Pi gets a unique host-assigned IP), or adjust each Pi’s shared subnet (nmcli con modify "USB Gadget (shared)" ipv4.addresses …).

Addressing & Modes

This package creates two NetworkManager profiles on the Pi’s USB gadget interface (default usb0) and a small watcher that auto-switches between them:

  • CLIENT mode – the Pi is a DHCP client of the host.

    • Used when an Internet Connection Sharing (ICS) gateway is detected on the host.
    • Typical host ICS gateways: 192.168.137.1 (Windows), 192.168.2.1 (macOS), 10.42.0.1 (Linux).
    • The Pi receives its IP and default route from the host. No NAT on the Pi.
  • SHARED mode – the Pi serves DHCP/NAT to the host (via NM “shared”).

    • Default address on the Pi: 10.12.194.1/28
    • DHCP pool to the host: 10.12.194.2–10.12.194.14 (short 2-minute leases)
    • NAT is performed on the Pi to its other uplink(s).

The watcher (rpi-usb-gadget-ics.service) checks for a reachable ICS gateway on usb0. If found, it switches to CLIENT; otherwise it runs SHARED.

Default subnetwork (SHARED mode)

  • Network: 10.12.194.0/28
  • Pi address (gateway): 10.12.194.1
  • Usable host pool: 10.12.194.210.12.194.14 (14 IPs)
  • Broadcast: 10.12.194.15
  • Mask: 255.255.255.240 (/28)

This narrow subnet minimizes the chance of colliding with the host’s other networks.

Multiple Pis on one host: If you plug several Pis into the same machine at the same time, and they all run SHARED mode with the default /28, the host will see overlapping subnets. Prefer enabling host ICS so devices run in CLIENT mode, or change each Pi’s SHARED subnet, e.g.:

sudo nmcli connection modify "USB Gadget (shared)" ipv4.addresses 10.12.195.1/28
sudo nmcli connection down "USB Gadget (shared)"; sudo nmcli connection up "USB Gadget (shared)"

mDNS (<hostname>.local) is still a convenient way to reach a specific Pi.

How It Works

This package enables the USB Ethernet gadget (g_ether kernel module) and configures NetworkManager to manage the gadget link:

  • Interface: usb0 (or set USB_GADGET_IFACE in the service environment)

  • Profiles:

    • USB Gadget (client) – DHCP client of the host (for host ICS)
    • USB Gadget (shared) – NetworkManager “shared” (DHCP+NAT served by the Pi)
  • Auto-switcher: rpi-usb-gadget-ics.service probes for a host ICS gateway via ARP and flips profiles accordingly.

Note: The current package ships USB Ethernet only.

Accessing the Pi

  • In SHARED mode: the Pi is 10.12.194.1. SSH: ssh pi@10.12.194.1
  • In CLIENT mode: the Pi receives its IP from the host’s ICS network (check the host adapter); you can also try ssh pi@<hostname>.local (mDNS).

On Windows, installing the supplied Raspberry Pi USB RNDIS Driver helps the host bind quickly to the gadget as an Ethernet adapter.

Installation

The package will be included in a future release of Raspberry Pi OS. Once it is in the official apt repositories you can follow the APT instructions below to install it on existing Raspberry Pi OS (trixie based) systems.

a) Using the APT repository (recommended for easy updates)

  1. Update your package list and install the package:
    sudo apt update
    sudo apt install rpi-usb-gadget
  2. Enable the feature:
    sudo rpi-usb-gadget on
  3. Reboot your Raspberry Pi.
    sudo reboot

Manual installation

  1. Download the .deb package from the releases page.
  2. Install the package using:
    sudo apt install ./rpi-usb-gadget.deb
  3. Enable the feature:
    sudo rpi-usb-gadget on
  4. Reboot your Raspberry Pi.
    sudo reboot

Usage

Simply plug your Raspberry Pi into your PC/laptop using a USB cable, and it will be recognized as an Ethernet device.

Important: Not all USB ports on your Raspberry Pi support USB OTG (which is required for this to work). On Pi 4 / 5 models, use the USB-C port, and on Pi Zero models, use the micro-USB port closest to the mini-HDMI port. For the A / A+ models, you'll need to use a custom USB-A to USB-A cable with the 5V wire snipped.

You can then connect to it via SSH, transfer files, or use remote development tools like VS Code.

Windows setup & troubleshooting (ICS + RNDIS)

When the gadget is working on Windows, you should see a network adapter named:

Raspberry Pi USB Remote NDIS Network Device

If Windows doesn't show this adapter in Device Manager or the Control Panel, the Raspberry Pi RNDIS driver isn’t installed. 👉 Install it from the project’s Releases: https://github.com/raspberrypi/rpi-usb-gadget/releases

How ICS is supposed to look (on Windows)

  • Turn on Internet Connection Sharing (ICS) on your upstream adapter (usually Wi-Fi). In the ICS dialog, set the Home networking connection to Raspberry Pi USB Remote NDIS Network Device.
  • Windows assigns 192.168.137.1/24 to the gadget NIC and runs a DHCP server.
  • The Pi (in CLIENT profile) gets an address like 192.168.137.x with gateway 192.168.137.1.
  • If ICS is off, the Pi will switch to SHARED mode and serve 10.12.194.0/28 to the host.

Symptoms & what they mean

  • Can’t reach the Pi by hostname (or ping -4 <hostname> fails), and on the Pi you see the ICS watcher/profile flapping between CLIENT and SHARED: Windows likely didn’t bind ICS to the gadget NIC or got confused after a reboot/cable replug.
  • Adapter shows “Unidentified adapter”: The RNDIS driver isn’t installed—install from the Releases page above.
  • Pi shows 169.254.x.x (APIPA) instead of 192.168.137.x: Windows’ DHCP isn’t serving—ICS isn’t actually active on the gadget NIC.

Quick fixes (most issues)

  1. Toggle ICS on the upstream adapter

    • Open the upstream adapter’s Sharing tab.
    • Uncheck “Allow other network users to connect…”OK.
    • Reopen the dialog, re-check it, and pick Raspberry Pi USB Remote NDIS Network Device as the Home networking connection.
    • Optional: Disable/Enable the gadget NIC in Device Manager or unplug/replug the USB cable.
  2. Driver fix (if “Unidentified adapter”)

    • Install the RNDIS driver from the Releases page.
    • Then repeat the ICS toggle above.
  3. Clear stale IPs (Windows quirk)

    • If the Pi wasn’t connected during boot, Windows sometimes “shares” to a different NIC and leaves a static IP on the gadget NIC.
    • Toggling ICS as above usually resets it. If not, open the gadget NIC’s IPv4 properties and set it back to Obtain an IP address automatically, then re-enable ICS.
  4. Nudge the Pi

    • From the Pi (UART/console/SSH), you can poke the client profile:

      sudo nmcli con up 'USB Gadget (client)'
      
    • Or reboot the Pi after you’ve corrected ICS on Windows.

Useful checks

  • On Windows, run ipconfig. The gadget NIC should be 192.168.137.1 when ICS is on.

  • On the Pi, run ip -4 a show usb0:

    • CLIENT (ICS): you should see 192.168.137.x/24 with a default route to 192.168.137.1.
    • SHARED: you should see 10.12.194.1/28 and no default route to the host.

Using Raspberry Pi Imager

You can also configure this functionality directly within the Raspberry Pi Imager tool (requires version 2.0 or newer). Simply select "USB Gadget mode" in the Interfaces & Features customization tab to enable it and make sure you have also configured ssh for remote access in imager.

For command-line users, this feature can also be activated with the --usb-gadget flag when using the rpi-imager-cli.

rpi-imager-cli --usb-gadget

Contributions

Contributions are welcome! Please submit a pull request or open an issue for feedback and improvements.