Skip to content

Instantly share code, notes, and snippets.

@peedy2495
Last active April 25, 2024 16:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peedy2495/e9ed5938bf0c2e3983185d0c9622e97d to your computer and use it in GitHub Desktop.
Save peedy2495/e9ed5938bf0c2e3983185d0c9622e97d to your computer and use it in GitHub Desktop.
Deploy USB-devices via Network as simple and stable as possible

Deploy USB-devices via Network as simple and stable as possible

Features:

  • auto-export on host when a defined usb-device has been plugged
  • auto-attachment on client when a disappeared remote-device is available, again.

Files Included:

README.md
usbip-export@.service
usbip-attach@.service

Package dependencies

  • usbip
  • lsusb (pre-installed on most distributions)

Installation

install the systemd-files as root.

usb-host:
install -m 644 -o root -g root -t /lib/systemd/system/ /your/filepath/usbip-export@.service

usb-client:
install -m 644 -o root -g root -t /lib/systemd/system/ /your/filepath/usbip-attach@.service

execute on both sides:
systemctl daemon-reload

Usage

To export a pysical usb-device you have to determine the vendor and product id of your device with lsusb the format is [idVendor]:[idProduct] like: 301b:56f1

Now, you're able to export/provide your usb-device.
Syntax:
usbip-export@[idVendor]:[idProduct].service e.g:
systemctl start usbip-export@301b:56f1

At last, you're able to attach the usb-device from the remote IP on a client.
Syntax:
usbip-attach@.service@[host]_[idVendor]:[idProduct].service e.g.:
systemctl start usbip-attach@192.168.0.10_301b:56f1

Background information for interested fellows ;-)

usbip-export human readable relevant code parts:

starting:

# bind
dev=%i
statePrev=1
state=$(/usr/bin/lsusb|grep -q $dev; echo $?)
while true; do
    if [ $state -ne $statePrev ]; then
        /usr/sbin/usbip bind --busid=$(/usr/sbin/usbip list -p -l | grep "$dev" | cut '-d#' -f1 | cut '-d=' -f2 | tr -d '[:space:]')
    fi
    sleep 1
    statePrev=$state
    state=$(/usr/bin/lsusb|grep -q $dev; echo $?)
done

stopping:

# unbind
/usr/sbin/usbip unbind --busid=$(/usr/sbin/usbip list -p -l | grep "%i" | cut '-d#' -f1 | cut '-d=' -f2 | tr -d '[:space:]')
killall usbipd

usbip-attach human readable relevant code parts:

starting:

# attach
host=$(echo %i|cut '-d_' -f1|tr -d '[:space:]')
dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]')
while true; do
    /usr/bin/lsusb | grep -q $dev
    if [ $? -ne 0 ]; then
        busid=$(/usr/sbin/usbip list -p -r $host | grep $dev | cut '-d:' -f1 | xargs echo -n)
        /usr/sbin/usbip port|grep -q $dev
        if [ $? -ne 0 ]; then
            /usr/sbin//usr/sbin/usbip attach --remote=$host --busid=$busid
        fi
    fi
    sleep 1
done

stopping:

# detach
dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]')
/usr/sbin/usbip port | while read i; do
    echo $i | grep -q $dev
    if [ $? -eq 0 ]; then
        /usr/sbin/usbip detach --port=$port
    fi
    echo $i | grep -q Port
    if [ $? -eq 0 ]; then
        port=$(echo $i | cut '-d ' -f2 | cut '-d:' -f1 | tr -d '[:space:]')
    fi
done

Tags: usb usbip tcp teleport gateway ip network systemd service remote deploy export

# Attach remote devices by calling this service with: # systemctl start usbip-attach@[host]_[idVendor]:[idProduct].service
# refer dmesg or lsusb on remote-host to catch your preferred device
[Unit]
Description=attach remote device from usbip-host
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
ExecStart=/bin/sh -c "host=$(echo %i|cut '-d_' -f1|tr -d '[:space:]'); dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); while true; do /usr/bin/lsusb | grep -q $dev; if [ $? -ne 0 ]; then busid=$(/usr/sbin/usbip list -p -r $host | grep $dev | cut '-d:' -f1 $
ExecStop=/bin/sh -c "dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); /usr/sbin/usbip port | while read i; do echo $i | grep -q $dev; if [ $? -eq 0 ]; then /usr/sbin/usbip detach --port=$port; fi; echo $i | grep -q Port; if [ $? -eq 0 ]; then port=$(echo $i $
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target
# Export devices by calling this service with: # systemctl start usbip-export@[idVendor]:[idProduct].service
# refer dmesg or lsusb to catch your preferred device
[Unit]
Description=exporting device via usbip host daemon
After=network-online.target
[Service]
Type=forking
ExecStart=/usr/sbin/usbipd -D
ExecStartPost=/bin/sh -c "dev=%i; statePrev=1; state=$(/usr/bin/lsusb|grep -q $dev; echo $?); while true; do if [ $state -ne $statePrev ]; then /usr/sbin/usbip bind --busid=$(/usr/sbin/usbip list -p -l | grep "$dev" | cut '-d#' -f1 | cut '-d=' -f2 | tr -d '[:space:]'); fi; sleep 1; statePrev=$state; state=$(/usr/bin/lsusb|grep -q $dev; echo $?); done &"
ExecStop=/bin/sh -c "/usr/sbin/usbip unbind --busid=$(/usr/sbin/usbip list -p -l | grep "%i" | cut '-d#' -f1 | cut '-d=' -f2 | tr -d '[:space:]'); killall usbipd"
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target
@axi92
Copy link

axi92 commented Aug 21, 2023

In the "usbip-attach@.service" both ExecStart and ExecStop look like cut of at the end.

I recreated it from the explanation part of you port:

usbip-attach@.service

# Attach remote devices by calling this service with: # systemctl start usbip-attach@[host]_[idVendor]:[idProduct].service
# refer dmesg or lsusb on remote-host to catch your preferred device

[Unit]
Description=attach remote device from usbip-host
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
ExecStart=/bin/sh -c "host=$(echo %i|cut '-d_' -f1|tr -d '[:space:]'); dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); while true; do /usr/bin/lsusb | grep -q $dev; if [ $? -ne 0 ]; then busid=$(/usr/sbin/usbip list -p -r $host | grep $dev | cut '-d:' -f1 | xargs echo -n); /usr/sbin/usbip port|grep -q $dev; if [ $? -ne 0 ]; then /usr/sbin/usbip attach --remote=$host --busid=$busid; fi; fi; sleep 1; done;
ExecStop=/bin/sh -c "dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); /usr/sbin/usbip port | while read i; do echo $i | grep -q $dev; if [ $? -eq 0 ]; then /usr/sbin/usbip detach --port=$port; fi; echo $i | grep -q Port; if [ $? -eq 0 ]; then port=$(echo $i | cut '-d ' -f2 | cut '-d:' -f1 | tr -d '[:space:]'); fi; done;

Restart=on-failure
RestartSec=30s

[Install]
WantedBy=multi-user.target

PS: Never copy from nano always use cat xD

@axi92
Copy link

axi92 commented Aug 21, 2023

For me on the usb-host I had to use those two cmds:

sudo modprobe usbip_core
sudo modprobe usbip_host

Only after this the service was able to bind the device.
The error before was like this:
usbip: error: failed to open /usr/share/hwdata//usb.ids
and
usbip: error: unable to bind device on 2-1.7

@peedy2495
Copy link
Author

peedy2495 commented Aug 26, 2023

In the "usbip-attach@.service" both ExecStart and ExecStop look like cut of at the end.

I recreated it from the explanation part of you port:

usbip-attach@.service

# Attach remote devices by calling this service with: # systemctl start usbip-attach@[host]_[idVendor]:[idProduct].service
# refer dmesg or lsusb on remote-host to catch your preferred device

[Unit]
Description=attach remote device from usbip-host
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
ExecStart=/bin/sh -c "host=$(echo %i|cut '-d_' -f1|tr -d '[:space:]'); dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); while true; do /usr/bin/lsusb | grep -q $dev; if [ $? -ne 0 ]; then busid=$(/usr/sbin/usbip list -p -r $host | grep $dev | cut '-d:' -f1 | xargs echo -n); /usr/sbin/usbip port|grep -q $dev; if [ $? -ne 0 ]; then /usr/sbin/usbip attach --remote=$host --busid=$busid; fi; fi; sleep 1; done;
ExecStop=/bin/sh -c "dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); /usr/sbin/usbip port | while read i; do echo $i | grep -q $dev; if [ $? -eq 0 ]; then /usr/sbin/usbip detach --port=$port; fi; echo $i | grep -q Port; if [ $? -eq 0 ]; then port=$(echo $i | cut '-d ' -f2 | cut '-d:' -f1 | tr -d '[:space:]'); fi; done;

Restart=on-failure
RestartSec=30s

[Install]
WantedBy=multi-user.target

PS: Never copy from nano always use cat xD

The relevant lines you've pointing to haven't been cut ...
here is my current running part:

ExecStart=/bin/sh -c "host=$(echo %i|cut '-d_' -f1|tr -d '[:space:]'); dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); while true; do lsusb | grep -q $dev; if [ $? -ne 0 ]; then busid=$(usbip list -p -r $host | grep $dev | cut '-d:' -f1 | xargs echo -n); usbip port|grep -q $dev; if [ $? -ne 0 ]; then /usr/sbin/usbip attach --remote=$host --busid=$busid; fi; fi; sleep 30; done &"

ExecStop=/bin/sh -c "dev=$(echo %i|cut '-d_' -f2|tr -d '[:space:]'); usbip port | while read i; do echo $i | grep -q $dev; if [ $? -eq 0 ]; then usbip detach --port=$port; fi; echo $i | grep -q Port; if [ $? -eq 0 ]; then port=$(echo $i | cut '-d ' -f2 | cut '-d:' -f1 | tr -d '[:space:]'); fi; done"

the only significant modification in ExecStart is setting sleep to 30s.
... and depending on distributions the installation path of executable binaries may vary ... therefore I changed absolute paths to dynamic.

@peedy2495
Copy link
Author

For me on the usb-host I had to use those two cmds:

sudo modprobe usbip_core
sudo modprobe usbip_host

Only after this the service was able to bind the device. The error before was like this: usbip: error: failed to open /usr/share/hwdata//usb.ids and usbip: error: unable to bind device on 2-1.7

Certainly, depending on your distri, kernel modules might be not loaded automatically by installation.
Refer your distribution how to load additional modules on boot.

Ubuntu and most other distries are using entries in /etc/modues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment