Skip to main content

Connect USB devices via USB/IP

The USB/IP protocol allows you to share USB devices between your virtual machine and another device.

USB/IP is an open-source tool for encapsulating USB I/O messages into TCP/IP messages. The host device shares a USB peripheral that the client device can use as if it were directly attached to the client. Read more about the protocol on the USB/IP SourceForge page.

In this article, we will show an example of how to Use Your Local Linux Computer as the USB/IP Host to directly control the cursor on a virtual Raspberry Pi Desktop device over a VPN connection.

We will also show examples of how to Use a Virtual STM32U5 Board as the USB/IP Host to share both input and output USB peripherals.

Use Your Local Linux Computer as the USB/IP Host

We will be using a physical computer with a fresh install of Ubuntu Desktop 22.04 LTS and a Raspberry Pi 4 running the Desktop version of firmware 11.2.0.

Start with the USB peripheral disconnected from your device.

:::Note The USB device we use will stop working on your host, so make sure to have a second mouse (or laptop trackpad) to control your computer. :::

Set Up the USB/IP Daemon on Your Computer

Start with a fresh install of the most recent LTS version of Ubuntu Desktop as the host and a virtual Raspberry Pi 4 Desktop board as the client.

  1. Install the required packages.

    sudo apt update && sudo apt install -y linux-tools-$(uname -r) hwdata ubuntu-restricted-extras
  2. Download the .ovpn file from the Raspberry Pi 4's Connect tab and connect to your AVH project using openvpn. Make note of the VPN's IP address, which in our example is 10.11.3.5.

    sudo openvpn --config ~/Downloads/AVH_config.ovpn

    Connect to AVH VPN

  3. Open a new Terminal window and load the USB/IP Host kernel module.

    sudo modprobe usbip_host

    Load the USBIP host kernel package

  4. Start the USB/IP daemon in the background.

    sudo usbipd &

    Run the USBIP daemon

  5. With the USB mouse dongle still disconnected, list the available peripherals.

    usbip list -l

    USBIP list without device

  6. Connect the physical USB mouse dongle to your computer and run the list command again. You should see a new device on a new bus number. In our example, we have a new device on bus 1-1.

    USBIP list with device

  7. Bind the appropriate USB bus, 1-1 in our case. (This will cause the device to stop functioning on your host computer, so make sure to have a backup in the case of a mouse.)

    sudo usbip bind -b 1-1

    USBIP bind

Attach a Physical Device to the Virtual Board Client

To attach a physical device to the virtual board client:

  1. On your newly created Raspberry Pi 4 virtual board, log in with the credentials pi and raspberry.

    Log in to RPi 4 Desktop

  2. Install the USB/IP package.

    sudo apt update && sudo install usbip
  3. Load the Virtual Host Controller Interface kernel module.

    sudo modprobe vhci-hcd

    Load the VHCI kernel module

  4. Using the VPN IP address from openvpn, list the exportable USB devices on the host. Look for the same bus number from the previous section.

    usbip list -r 10.11.3.5

    USBIP list on RPi4 Desktop

  5. Attach to USB bus 1-1, which corresponds to our mouse.

    sudo usbip attach -r 10.11.3.5 -b 1-1

    USBIP attach on RPi4 Desktop

  6. You should now be able to control the cursor on the Raspberry Pi 4 Desktop.

(Optionally) Close the Connection When Finished

When you are finished, you can optionally close the connection by detaching on the client and unbinding the host's USB bus.

This process is necessary if you want to access the USB resource again on your host device.

  1. On the USB/IP client, which in our case is the virtual Raspberry Pi 4 Desktop board, list the imported USB devices. Look for the appropriate port number.

    usbip port

    USBIP port on RPi4 Desktop

  2. Detach port 00, which corresponds to our mouse. Look for a response showing detached.

    sudo usbip detach -p 00

    USBIP detach on RPi4 Desktop

  3. Switch over to your USB/IP host, which in our case is the Ubuntu machine, and unbind the appropriate USB bus. Look for a response showing complete.

    usbip unbind -b 1-1

    USBIP unbind

Use a Virtual STM32U5 Board as the USB/IP Host

We will be using firmware files that are offered as examples in STMicroelectronics's STM32CubeIDE tool.

You will need to build the Ux_Device_HID.elf and Ux_Device_HID_CDC_ACM.elf firmware files.

Build USB Firmware Files with the STM32CubeIDE Tool

Follow this process to build the required .elf custom firmware files using free tools from STMicroelectronics.

  1. Install the STM32CubeIDE tool. In our example, we will use the MacOS version.

    Download CubeIDE

  2. Create a new project by clicking New -> STM32 Project from the File menu.

    New Project

  3. When the STM32 Project window appears, click on Example Selector.

    Example Selector

  4. Choose the example name Ux_Device_HID and the board name B-U585I-IOT02A, click on the example you want to build, then click Next.

    Choose Example

  5. Make note of your project name and path to your workspace then click Finish.

    Finish Project

  6. When the Project Explorer opens, right-click on your project name and select Build Project.

    Build Project

  7. While the project is building, you should see a progress message towards the bottom right. Open the Console if you prefer to follow the progress.

    Build Progress

  8. The .elf firmware file will be created inside your project directory, which is inside /<path_to_workspace>/<project_name>/STM32CubeIDE/Debug.

    ls ~/STM32CubeIDE/workspace_1.10.0/Ux_Device_DFU/STM32CubeIDE/Debug/*.elf

    List Firmware File

  9. The firmware file is ready to be uploaded to your AVH virtual STM32U5 board.

Attach a Virtual USB Peripheral to a Virtual Raspberry Pi 4 Board

To attach a virtual joystick to the Raspberry Pi 4:

  1. Create a new virtual STM32U5 board and manually upload the Ux_Device_HID.elf custom firmware you created.

    Upload joystick firmware

  2. Make note of the Services IP address on the Connect tab. In our example, we will use the Services IP 10.11.1.5.

    Joystick Services IP

  3. Create a new Raspberry Pi 4 virtual device using any version of the firmware. In our example, we will use the lite version of firmware 11.2.0.

    Create new Pi

  4. Log in as the root user with the username pi and password raspberry.

    Login to Pi as root

  5. Install the USB/IP package.

    sudo apt update && sudo apt install -y usbip

    Install usbip

  6. Load the Virtual Host Controller Interface kernel module.

    sudo modprobe vhci-hcd

    Load kernel module

  7. List the STM32U5's exportable USB devices using the Services IP and port 6000.

    usbip --tcp-port 6000 list -r 10.11.1.5

    List USB devices

  8. Attach to USB bus 0-1, which corresponds to the joystick peripheral. (Don't forget to sudo or the command will fail.)

    sudo usbip --tcp-port 6000 attach -r 10.11.3.3 -b 1-2

    Attach to USB bus 0-1

  9. The STM32U5's virtual joystick is now attached to your Raspberry Pi 4 virtual board. Confirm the device is attached using usbip port. Make note that the device is using port 00.

    Confirm the device is attached

  10. When you are finished, detach the peripheral from port 00.

    sudo usbip detach -p 00

    Detach the peripheral

Attach a Virtual USB Peripheral to a Physical Computer Using a VPN Connection

In this example, we will use a laptop running Ubuntu 20.04. We will also use Ux_Device_HID_CDC_ACM.elf, the "Mini LED Display" firmware file we created in the Build USB Firmware Files with the STM32CubeIDE Tool step.

  1. Create a new STM32U5 virtual device and manually upload the Ux_Device_HID_CDC_ACM.elf firmware you created in the STM32CubeIDE tool.

    Upload LED firmware

  2. Download the .ovpn file and make note of the Services IP address on the Connect tab. In our example, the Services IP is 10.11.1.1.

    STM32U5 VPN and Services IP

  3. On your Linux client machine, install the required packages.

    sudo apt update && sudo apt install -y linux-tools-$(uname -r) hwdata
  4. Connect to the AVH VPN using the .ovpn file you downloaded.

    sudo openvpn --config /Downloads/app.avh.corellium.com\ VPN\ -\ Default\ Project.ovpn

    OpenVPN

  5. Open a second Terminal window. Double-check your VPN connection by pinging the Services IP for your USB/IP host.

    Ping Test

  6. Load the Virtual Host Controller Interface kernel module.

    sudo modprobe vhci-hcd

    Load the kernel module

  7. List the exportable STM32U5 USB devices.

    usbip --tcp-port 6000 list -r 10.11.1.1

    List USB Devices

  8. Attach to USB bus 0-1, which corresponds to the LED display.

    sudo usbip --tcp-port 6000 attach -r 10.11.1.1 -b 0-1

    Attach to USB Device

  9. List the Imported USB devices to confirm the attach command was successful.

    usbip port

    Imported USB Device

  10. When you are finished, detach from port 00.

    sudo usbip detach -p 00

    Detach USB Device

Attach a Virtual USB Peripheral to a Physical Computer Using SSH Port Forwarding

In this example, we will use a laptop running Ubuntu 22.04. We will also use Ux_Device_HID_CDC.elf, the "Joystick in FS Mode" firmware file we created in the Build USB Firmware Files with the STM32CubeIDE Tool step.

  1. Upload the Ux_Device_HID_CDC.elf firmware file and start the STM device. Make note of the device's "Services IP".

  2. Next, we will find your project's unique identifier. The first option is to use the Get Projects API command. Alternatively, you can do the following.

    1. Boot up a virtual Raspberry Pi 4 board.

    2. Under the Connect tab, find to the Quick Connect SSH command

    3. Copy the part of the command showing your project's unique identifier <project identifier>@proxy.app.avh.corellium.com.

  3. On your Ubuntu computer, generate a public/private key pair using the Ed25519 signature scheme. In our example, we will use the default file path with no passphrase.

    ssh-keygen -t ed25519

    Add the public key (cat ~/.ssh/id_ed25519.pub) to your AVH project's authorized project keys under https://app.avh.corellium.com/admin/projects.

  4. Install USB/IP and the hardware identification tool.

    sudo apt update && sudo apt install -y linux-tools-$(uname -r) hwdata
  5. Load the USB Virtual Host Controller Interface kernel module.

    sudo modprobe vhci-hcd
  6. Use ssh to forward local port 6000 to port 6000 of your device's services IP.

    ssh -M -Ssock -N -f -L 6000:<STM_device_services_IP>:6000 <your_project_id>@proxy.app.avh.corellium.com
  7. List USBIP devices on localhost port 6000.

    usbip --tcp-port 6000 list -r localhost
  8. You should see the virtual STMicroelectronics USB peripheral appear.

  9. When you are finished, close the socket.

    ssh -Ssock -O exit proxy.corellium.com