This project is an ESP-IDF scaffold for ESP32-P4 / ESP32-S3 USB dev boards that:
- runs USB Host mode,
- enumerates and exports multiple non-hub USB devices (including devices behind a USB hub),
- exposes it over IP using the Linux USB/IP protocol on TCP port
3240.
Implemented now:
OP_REQ_DEVLIST(usbip list -r <ip>works when device is attached)OP_REQ_IMPORT(usbip attach -r <ip> -b <busid>)USBIP_CMD_SUBMITfor control endpointEP0onlyUSBIP_CMD_UNLINK
Not implemented yet:
- non-control endpoints (bulk/interrupt/isochronous)
- robust recovery for all host and network edge cases
USB/IP wire format is implemented from Linux kernel documentation:
- https://docs.kernel.org/usb/usbip_protocol.html
- https://docs.kernel.org/usb/usbip_protocol.html#architecture
main/main.c: application startupmain/network_init.c: target-specific network bring-up (Ethernet or Wi-Fi STA)main/usb_backend.c: USB Host backend, device discovery, EP0 control transfersmain/usbip_server.c: TCP server and USB/IP message handlingmain/usbip_protocol.h: protocol constants and packet structsmain/Kconfig.projbuild: board/server configuration options
This repository is pinned to ESP-IDF v6.0-beta2 (latest 6.0 beta as of February 20, 2026).
- Clone/install ESP-IDF locally for this project:
./scripts/setup-esp-idf.sh- In every new shell, load the project-local ESP-IDF environment:
source ./scripts/idf-env.shTwo board profiles are provided:
p4-function-ev: ESP32-P4-Function-EV board, USB/IP over Ethernets3-usb-otg: ESP32-S3-USB-OTG board, USB/IP over Wi-Fi STA
Set your serial port once (example):
export ESPPORT=/dev/ttyUSB0Console output defaults by target:
p4-function-ev: USB Serial/JTAG consoles3-usb-otg:UART0console (to avoid USB host conflicts)
Build:
./scripts/build-board.sh p4-function-ev buildFlash and monitor:
ESPPORT=$ESPPORT ./scripts/build-board.sh p4-function-ev flash
ESPPORT=$ESPPORT ./scripts/build-board.sh p4-function-ev monitorBefore building, edit sdkconfig.defaults.s3-usb-otg:
CONFIG_USBIP_WIFI_SSID: your AP SSIDCONFIG_USBIP_WIFI_PASSWORD: your AP passwordCONFIG_USBIP_WIFI_AUTHMODE:2= WPA2-PSK (recommended for most home/office APs)3= WPA2/WPA3 transition mode0= open (debug only)
CONFIG_USBIP_WIFI_DISABLE_MODEM_SLEEP=y(recommended for USB host stability)
Build:
./scripts/build-board.sh s3-usb-otg buildFlash and monitor:
ESPPORT=$ESPPORT ./scripts/build-board.sh s3-usb-otg flash
ESPPORT=$ESPPORT ./scripts/build-board.sh s3-usb-otg monitorClean board build output and board sdkconfig (forces regeneration from defaults on next build):
./scripts/build-board.sh s3-usb-otg clean
./scripts/build-board.sh p4-function-ev cleanIf switching targets or recovering from config mismatch, erase flash:
idf.py -B build-s3-usb-otg -DIDF_TARGET=esp32s3 -DSDKCONFIG=sdkconfig.s3-usb-otg erase-flashInstall/load USB/IP support on Linux host:
sudo modprobe vhci-hcdDiscover bridge by mDNS:
avahi-browse -rt _usbip._tcpResolve host (example):
avahi-resolve-host-name usbip-xxxxxx.localList and attach exported device:
usbip list -r <bridge-ip-or-hostname>
sudo usbip attach -r <bridge-ip-or-hostname> -b 1-<devaddr>Example bus ID format from this firmware: 1-1.
USB/IP protocol itself does not define mDNS discovery. This firmware advertises a custom DNS-SD service:
- Service type:
_usbip._tcp - Port:
3240 - TXT keys:
transport,state,busid,vid,pid,target countindicates the number of exported devices (busid=multiwhencount > 1)
Linux discovery examples:
avahi-browse -rt _usbip._tcp
avahi-resolve-host-name usbip-xxxxxx.local- USB/IP in this scaffold is intentionally minimal and aimed at incremental bring-up.
- ESP-IDF version constraint is set in
main/idf_component.ymlto>=6.0.0-beta2.