USB over IP tunnel
USB/IP Project aims to develop a general USB device sharing system over IP network. To share USB devices between computers with their full functionality, USB/IP encapsulates “USB I/O messages” into TCP/IP payloads and transmits them between computers.
| |
Server on OpenWrt
Since Barrier Breaker release USBIP packets are missing - there's difference in installation procedure
First install the usb kernel module and usbip server and client packages:
Attitude Adjustment or newer release like OpenWrt 24.10.5:
opkg install kmod-usb-ohci usbip-server usbip-client
You will need both packages, because the usbip-server package will include the dependency to install the kernel modules. You will also have to install the usbip-client package which provides the usbip binary.
Barrier Breaker + Chaos Calmer:
opkg install kmod-usb-ohci opkg install http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages/usbip_1.1.1-2_ar71xx.ipk opkg install http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages/usbip-client_1.1.1-2_ar71xx.ipk opkg install http://downloads.openwrt.org/attitude_adjustment/12.09/ar71xx/generic/packages/usbip-server_1.1.1-2_ar71xx.ipk
(The packages are installed from AA, but kernel modules would be installed from BB automatically to match kernel ver)
Now use usbip list -l to list the local usb devices available that can be exported. In the following example a hub, usb printer, and an optical mouse are shown:
root@OpenWrt:~# usbip list -l
Local USB devices
=================
- busid 2-1 (05e3:0608)
2-1:1.0 -> hub
- busid 2-1.4 (04e8:344f)
2-1.4:1.0 -> unknown
2-1.4:1.1 -> unknown
- busid 2-2 (093a:2510)
2-2:1.0 -> unknown
The information that you are looking for is 2-2, which is the BUSID for the target device (an optical mouse).
Edit /etc/rc.local and before the exit 0 add the following lines:
usbipd -D & sleep 1 usbip bind -b 2-2
Use netstat to see if everything works:
root@OpenWrt:~# netstat -alpt Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:3240 0.0.0.0:* LISTEN 927/usbipd
Automate usbip Server device Sharing
Openwrt 24.10.5 will run usbipd (usbip server automatically on boot).
This guide aims to automate the process of running
usbip bind -b <bus id> or usbip unbind --busid <bus id> for a list of known devices.
Make sure that the folder /etc/hotplug.d/usb/ exists.
Then create a new file called /etc/hotplug.d/usb/90-usbip. This file will contain our shell script that runs on boot and during hotplug events (on plugging or unplugging usb devices).
mkdir /etc/hotplug.d/usb touch /etc/hotplug.d/usb/90-usbip
Edit /etc/hotplug.d/usb/90-usbip and add the following lines:
#!/bin/sh # Set the paths to the required files usbip_share_these_devices="/etc/usbip_share_these_devices.list" currently_shared_devices="/tmp/usbip_shared_devices.list" # Check if configuration file existst if [ ! -f "$usbip_share_these_devices" ]; then logger "Error: $usbip_share_these_devices not found" exit 1 fi # Check if USB/IP kernel modules are loaded lsmod | grep -q usbip_core || { logger "Error: USB/IP kernel modules not loaded" exit 1 } # Check if the usbip command exists command -v usbip >/dev/null 2>&1 || { logger "Error: usbip command not found."; exit 1; } # Function to check if the "br-lan" interface has an ip (IPv4 or IPv6) check_network() { if ifconfig br-lan | grep -qE "inet |inet6 "; then return 0 fi return 1 } # Function to check if a USB device is allowed is_device_allowed() { local vendor_id="$1" local device_id="$2" grep -q "$vendor_id:$device_id" "$usbip_share_these_devices" 2>/dev/null } # Function to check if a device is already in the connected devices file is_device_connected() { local bus_id="$1" grep -q ",$bus_id\$" "$currently_shared_devices" 2>/dev/null } # Function to add a device to the currently shared devices file share_device() { local vendor_id="$1" local device_id="$2" local bus_id="$3" # Try to bind, then add to tracking file. if usbip bind --busid "$bus_id"; then echo "$vendor_id,$device_id,$bus_id" >> "$currently_shared_devices" else logger "Error: Failed to bind device $bus_id" return 1 fi } # Function to unshare a device and remove the entry from the currently shared devices file unshare_device() { # Iterate through connected devices file while IFS=, read -r vendor_id device_id bus_id; do device_path="/sys/bus/usb/devices/$bus_id" # Check if the device path exists if [ -e "$device_path" ]; then # Device is still connected, do nothing continue else # No longer share that usbdevice over usbip usbip unbind --busid "$bus_id" # Device is no longer present echo "Device disconnected: $vendor_id $device_id $bus_id" # Remove the line from the connected devices file sed -i "/,$bus_id$/d" "$currently_shared_devices" fi done < "$currently_shared_devices" } # Parse hotplug events case "$ACTION" in add) # Check if the device has idVendor and idProduct in the same directory if [ -e /sys${DEVPATH}/idVendor ] && [ -e /sys${DEVPATH}/idProduct ]; then # Extract vendor ID, device ID, and bus ID vendor_id=$(cat /sys${DEVPATH}/idVendor) device_id=$(cat /sys${DEVPATH}/idProduct) bus_id=$(ls -d /sys${DEVPATH} | xargs basename) # Check if the device is intended to be shared and not already beeing shared. if is_device_allowed "$vendor_id" "$device_id" && ! is_device_connected "$bus_id"; then share_device "$vendor_id" "$device_id" "$bus_id" fi fi ;; remove) # Check if a device has been disconnected. unshare_device ;; esac # Main # Script running on boot if [ "$1" = "1" ]; then # Remove temp file if it is still there. rm -f "$currently_shared_devices" # Maximum number of attempts before giving up max_attempts=6 # Current attempt counter attempt=0 # Wait for network connection on the "br-lan" interface while [ $attempt -lt $max_attempts ]; do if check_network; then break else sleep 10 # Adjust the sleep interval based on your needs attempt=$((attempt + 1)) fi done # Check if we reached the maximum number of attempts if [ $attempt -eq $max_attempts ]; then exit 1 # Exit with an error code or take appropriate action fi # Share devices for DEVPATH in /sys/bus/usb/devices/*; do if [ -e "$DEVPATH/idVendor" ] && [ -e "$DEVPATH/idProduct" ]; then # Extract vendor ID, device ID, and bus ID vendor_id=$(cat "$DEVPATH/idVendor") device_id=$(cat "$DEVPATH/idProduct") bus_id=$(basename "$DEVPATH") # Check if the device is intended to be shared and not already beeing shared. if is_device_allowed "$vendor_id" "$device_id" && ! is_device_connected "$bus_id"; then share_device "$vendor_id" "$device_id" "$bus_id" fi fi done fi exit 0
Create a new file called /etc/usbip_share_these_devices.list. To this file we will add vendor IDs and device IDs like listed when running usbip list -l.
touch /etc/usbip_share_these_devices.list
Edit /etc/usbip_share_these_devices.list and add the devices that should automatically beeing shared:
# Add devices, that you want to automatically share, within this list. 048d:1336 04d8:fd92 046d:c52b
Edit /etc/rc.local and before the exit 0 add the following lines (this will make the script executable and run it on boot of the device):
[ -x /etc/hotplug.d/usb/90-usbip ] || chmod 750 /etc/hotplug.d/usb/90-usbip /etc/hotplug.d/usb/90-usbip 1
the
1 after the script name is intended. It tells the script that is is running during boot, in this mode the script will wait for the network interfaces to be ready, before starting usbip.
Edit /etc/sysupgrade.conf to preserve these changes over Firmware Upgrades.
/etc/hotplug.d/usb/90-usbip /etc/usbip_share_these_devices.list /etc/rc.local
Client side (Arch-linux PC)
Install usbip in your PC
[root@tool dani]# pacman -S usbip
Load the module for the client
[root@tool dani]# modprobe vhci_hcd
List the available remote devices at OpenWrt (server side).
[root@tool dani]# usbip list -r 192.168.1.1
Exportable USB devices
======================
- 192.168.1.1
2-2: Pixart Imaging, Inc. : Optical Mouse (093a:2510)
: /sys/devices/platform/bcm63xx_ohci.0/usb2/2-2
: (Defined at Interface level) (00/00/00)
: 0 - Human Interface Device / Boot Interface Subclass / Mouse (03/01/02)
Attach the remote device
[root@tool dani]# usbip attach -r 192.168.1.1 -b 2-2
If all went fine now you can move the mouse on your pc, but attached to the router with OpenWrt.
Client side (Windows PC (incl. W7 x64)
Solution consists of 2 parts:
1. Install Driver
2. Start usbip tool
1. Installing a driver could be a challenge - there is a signed drivers, included in 0.200 version of tool. Unfortunately the don't work anymore. at least for Win7 x64. Look through USBIP forum to find the latest compiled driver and tool. Unfortunately the Driver is not signed and in order to install it, you have to switch off Windows drivers signature check. a)Download the working Driver and usbip tool here: http://sourceforge.net/p/usbip/discussion/418507/thread/86c5e473/
b)Disable Windows Drivers check:
Open a command prompt as an admin and type:
bcdedit -set loadoptions DISABLE_INTEGRITY_CHECKS
bcdedit -set TESTSIGNING ON
NOTE: Turning off driver signing is a security risk.
If it doesn't work, for whatever reason, you can just remove loadoptions with bcedit and >switch testsigning off, though this is not recommended:
bcdedit /deletevalue loadoptions
bcdedit -set TESTSIGNING OFF
For Windows 8.1, use the details on this page:
[[http://www.howtogeek.com/167723/how-to-disable-driver-signature-verification-on-64-bit-windows-8.1-so-that-you-can-install-unsigned-drivers/]]
And then restart Windows.
2. Use the tool usbip.exe, downloaded with the working driver.
a) usbip -l <HOST IP address> to show all USB devices binded on the HOST b) usbip -a <HOST IP address> <BUSID> to connect to particular Device.
Tested on BB release. Working at least with USB Drives and Kvaser Leaf Lite CAN gateway.
Notes
- https://github.com/vadimgrn/usbip-win2 (usbip client with GUI for windows 11)
- #9953 (usbip server on OpenWRT fails after client tries to attach device) also features a small how to.