12. USB Devices

12.1. USB device access for RT-Linux guests

Caution

Starting with version 9.0, USB device access for RT-Linux guests is no longer supported in RTOSVisor.

A single USB device can be accessed from within one single RT-Linux guest using usbip.
This will expose a USB device from the Hypervisor Host to the RT-Linux guest via the virtual network.

12.1.1. Hypervisor Host usbip package

In a first step, the respective software package for the RTOSVisor may have to be installed. Run the following command to check if the package is already available:

which usbipd

The package is available if you get the following result: /usr/bin/usbipd.

acontis linux kernel comes with preinstalled linux-extra- package, so it already includes usbip. If usbip package is not avaialble, please contact your technical support.

12.1.2. RT-Linux

The standard RT-Linux image shipped with the hypervisor does not support usbip. You need to exchange this image by the separately provided rtlinux515.x64-usbip.bin image file. This file is part of the CODESYS package and located in /hv/guests/etc/rt-linux/files/codesys/rtlinux. You need to initialize the RT-Linux example and adjust the configuration:

hv_open_example rt-linux
hv_sync_example rt-linux
cd /hv/guests/guestrtlinux
mousepad guest_config.sh

Adjust the following line:

export osImage=$HV_ROOT/guests/etc/rt-linux/files/codesys/rtlinux/rtlinux515.x64-usbip.bin

12.1.3. Prepare USB device exposal

The USB device which shall be exposed to RT-Linux needs to be prepared for exposal. In a first step you will need to determine the vendor and device ID of the USB device you want to expose. Insert the USB device and execute the following commands.

hv_hvusbip -init
hv_hvusbip -list

Hint

The call with the -init parameter is only required once.

A list of USB devices will be shown.

 1device list
 2***********
 3 - busid 3-2 (046d:c52b)
 4   Logitech, Inc. : Unifying Receiver (046d:c52b)
 5
 6 - busid 3-3 (046d:c52f)
 7   Logitech, Inc. : Unifying Receiver (046d:c52f)
 8
 9 - busid 3-5 (0e8d:0608)
10   MediaTek Inc. : unknown product (0e8d:0608)
11
12 - busid 3-8 (064f:2af9)
13   WIBU-Systems AG : CmStick (HID, article no. 1001-xx-xxx) (064f:2af9)
14
15 - busid 4-4 (18a5:0243)
16   Verbatim, Ltd : Flash Drive (Store'n'Go) (18a5:0243)
In this example, we will expose the WIBU CmStick device to the guest.
According to the above output, its vendor device id is 064f:2af9

Then you need to insert the vendor device ID into the respective configuration file.
cd /hv/config
mousepad usbip_exposed_device.sh
Insert the appropriate vendor device ID.
Don’t forget to remove the comment at the beginning of the line!
# one single device currently can be exposed to the RTOS
export usb_vendev=064f:2af9  # WIBU CodeMeter USB dongle

Hint

After booting, the hv_usbip_expose.service located in /hv/services will prepare USB device exposal.

12.1.4. Expose USB device to the guest

You need to copy the /hv/config/usbip_exposed_device.sh into the respective guest folder to expose the USB device.

cd GUEST_FOLDER
cp /hv/config/usbip_exposed_device.sh .

Hint

When starting RT-Linux, the GUEST_FOLDER/usbip_gen_init.sh script will dynamically create the GUEST_FOLDER/files/usbip_init.sh script.
This sub script will be called when RT-Linux is booted via the GUEST_FOLDER/files/autostart.sh script.

Caution

You must not adjust the GUEST_FOLDER/files/usbip_init.sh script manually, it will be overwritten when RT-Linux is started!

You may insert specific autostart activities when the RT-Linux guest starts.

cd GUEST_FOLDER
mousepad usbip_gen_init.sh

At the very bottom the required autostart activity for a specific WIBU Codemeter USB device is shown. Please adjust the script GUEST_FOLDER/usbip_gen_init.sh according to your needs.

# insert usbip specific autostart activities here
if [ $usb_vendev == "064f:2af9" ]; then
    # echo "start codemeter daemon"
    echo "start-stop-daemon --start --quiet --chuid root --exec /usr/sbin/CodeMeterLin" >>./rtfiles/usbip_init.sh
    echo "to verify CodeMeter status run 'cmu --cmdust'" >>./rtfiles/usbip_init.sh
fi

Then, the usbip expose service needs to be enabled which will start the usbip server on the Hypervisor Host:

sudo systemctl enable /hv/services/hv_usbip_expose.service

Finally you should start the service to make your changes effective. You may also reboot to do so.

sudo systemctl start hv_usbip_expose

Hint

This service will run the script /hv/config/usbip_expose.sh which will finally expose the device.
You can run the command systemctl status hv_usbip_expose.service to verify if exposing worked correctly.

Caution

If the USB device is removed and re-inserted, it has to be exposed again.
Furthermore, in RT-Linux the appropriate steps (executed in usbip_init.sh) also have to be executed again.

After you have started the service, you can check if the device is correctly exposed - before starting RT-Linux. Connect the USB device and then run the following command.

usbip list -r 127.0.0.1

A list of exportable USB devices will be shown. The one that you have set before should be shown.

Exportable USB devices
======================
 - 127.0.0.1
        3-3: WIBU-Systems AG : CmStick (HID, article no. 1001-xx-xxx) (064f:2af9)
           : /sys/devices/pci0000:00/0000:00:14.0/usb3/3-3
           : (Defined at Interface level) (00/00/00)
           :  0 - Human Interface Device / No Subclass / None (03/00/00)

Finally you can start RT-Linux, the USB device should be visible then. To verify this, you can run the following command (inside RT-Linux!).

usbip port

A list of imported USB devices will be shown. The one that you have set before should be shown.

Imported USB devices
====================
Port 00: <Port in Use> at Full Speed(12Mbps)
       WIBU-Systems AG : CmStick (HID, article no. 1001-xx-xxx) (064f:2af9)
       1-1 -> usbip://192.168.157.1:3240/3-3
           -> remote bus/dev 003/007

Hint

To stop exposing USB devices, you have to comment the device in /hv/config/usbip_exposed_device.sh.
# one single device currently can be exposed to the RTOS
# export usb_vendev=064f:2af9  # WIBU CodeMeter USB dongle

Then you should disable the service.

sudo systemctl disable hv_usbip_expose

12.1.5. Hypervisor Host usbip low level services

The usbip low level services are used by the scripts and services of the Hypervisor Host.
This background information may be helpful for debugging and diagnosis purposes.

Loading kernel modules:

sudo modprobe usbip_host
sudo modprobe usbip_core

Start the usbip daemon:

sudo usbipd -D

Show all USB connected devices:

usbip list -l

Expose a specific USB device:

sudo usbip bind -b busid

Show all currently exposed USB devices that are not in use:

usbip list -r 127.0.0.1

Stop exposing a specific USB device:

sudo usbip unbind -b busid

12.1.6. RT-Linux usbip low level services

The usbip low level services are used by the scripts and services of the RT-Linux guest.
This background information may be helpful for debugging and diagnosis purposes.

Loading kernel modules:

modprobe vhci-hcd

Show exposed devices:

usbip list -r 192.168.157.1

Attach exposed device:

usbip attach -r 192.168.157.1 -b "Device bus ID"

Show ports in use by attached devices:

usbip port

Detach a specific port:

usbip detach -p "port"

12.2. Windows/Linux USB guest access (non automatic mode)

In case the USB device is plugged in while the guest is already running, you need to determine some information about the USB device.

Using the lsusb command, a list of connected USB devices can be found:

lsusb
  Bus 002 Device 002: ID 0b95:1790 ASIX Electronics Corp. AX88179 Gigabit Ethernet
  Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
  Bus 001 Device 003: ID 8087:0025 Intel Corp. Wireless-AC 9260 Bluetooth Adapter
  Bus 001 Device 006: ID 064f:2af9 WIBU-Systems AG CmStick (HID, article no. 1001-xx-xxx)
  Bus 001 Device 005: ID 046d:c050 Logitech, Inc. RX 250 Optical Mouse
  Bus 001 Device 004: ID 046a:0011 Cherry GmbH G83 (RS 6000) Keyboard
  Bus 001 Device 002: ID 1a40:0101 Terminus Technology Inc. Hub
  Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Then you need to run the hv_guest_monitor command.

cd GUEST_FOLDER
hv_guest_monitor

If you want to dynamically connect the first USB device (Bus 002, Device 002), type in the following command:

device_add usb-host,id=MyUsbDevice,hostbus=2,hostaddr=2

The id value can be selected freely but it has to be unique in case multiple USB devices are connected.

12.3. Windows/Linux USB guest access (passthrough mode) for non Real-time guests

If a specific physical USB port shall be permanently used by the guest, this can be accomplished using USB passthrough mode.
In this case, the hypervisor will monitor a specific USB port and automatically passthrough a USB device (for example a USB 3.0 Stick) to an active guest.

In the first step, you need to determine the USB hostbus and hostport value pairs for the selected physical USB port.

Caution

Depending on the USB type (USB1/2 or USB3) there will be different values even if the same physical port is used.

Caution

If a USB mouse is connected to a specific USB port, you must not passthrough this USB port unless you are using graphics passthrough mode.
This means, the physical USB port where such mouse is connected must not be used for other devices.
Also, the USB mouse must not be connected to any physical USB port which is passed through to the guest.
If this port is passed through, the mouse pointer will not be visible!

12.3.1. USB1/2 devices

Connect a USB2 stick to the USB port you want to passthrough and execute the following on the Hypervisor Host:

lsusb -t

You will get a result similar to

1/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
2/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
3    |__ Port 4: Dev 18, If 0, Class=Mass Storage, Driver=usb-storage, 480M
4    |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
5    |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
The USB hostbus value for this physical port using USB1/USB2 devices is 1 (see line 2)
The USB hostport value for this physical port using USB1/USB2 devices is 4 (see line 3)

12.3.2. USB3 devices

Connect a USB3 stick to the USB port you want to passthrough and execute the following on the Hypervisor Host:

lsusb -t

You will get a result similar to

1/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
2    |__ Port 5: Dev 18, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
3/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
4    |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
5    |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
The USB hostbus value for this physical port using USB3 devices is 2 (see line 1)
The USB hostport value for this physical port using USB3 devices is 5 (see line 2)

12.3.3. USB hubs

If devices are connected behind a USB hub, you will see multiple nested ports behind which the device can be found.

Example 1: USB3 device behind a hub

1/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
2    |__ Port 1: Dev 15, If 0, Class=Hub, Driver=hub/4p, 5000M
3        |__ Port 2: Dev 16, If 0, Class=Vendor Specific Class, Driver=ax88179_178a, 5000M
4/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
5    |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
6    |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
The USB hostbus value for this physical port behind a hub is 2 (see line 1)
The USB hostport value for this physical port behind a hub is 1.2 (see lines 2 and 3)

Example 2: USB2 device behind two hubs

1/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
2/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
3    |__ Port 1: Dev 26, If 0, Class=Hub, Driver=hub/4p, 480M
4        |__ Port 1: Dev 29, If 0, Class=Hub, Driver=hub/4p, 480M
5            |__ Port 2: Dev 30, If 0, Class=Mass Storage, Driver=usb-storage, 480M
6    |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
7    |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
The USB hostbus value for this physical port behind a hub is 1 (see line 2)
The USB hostport value for this physical port behind a hub is 1.1.2 (see lines 3,4 and 5)

Caution

Some USB devices contain an internal USB hub to expose multiple USB device instances. Here, the same rules apply.

12.3.4. Guest configuration

The USB hostbus and hostport value pairs need to be used in the guest configuration file usr_guest_config.sh.
Below you will find the required entries for the above examples.
# USB host passthrough (automatic passthrough for any device connected to these ports).
#   Note: on the same physical USB port, different values for hostbus,hostport pairs will show up for different USB speed!
export USB_HOST_ADAPTER1_PASSTHROUGH=""
export USB_HOST_ADAPTER1_PASSTHROUGH="$USB_HOST_ADAPTER1_PASSTHROUGH -device usb-host,bus=$USB_HOST_ADAPTER1_NAME.0,hostbus=1,hostport=4"
export USB_HOST_ADAPTER1_PASSTHROUGH="$USB_HOST_ADAPTER1_PASSTHROUGH -device usb-host,bus=$USB_HOST_ADAPTER1_NAME.0,hostbus=2,hostport=5"
export USB_HOST_ADAPTER1_PASSTHROUGH="$USB_HOST_ADAPTER1_PASSTHROUGH -device usb-host,bus=$USB_HOST_ADAPTER1_NAME.0,hostbus=2,hostport=1.2"
export USB_HOST_ADAPTER1_PASSTHROUGH="$USB_HOST_ADAPTER1_PASSTHROUGH -device usb-host,bus=$USB_HOST_ADAPTER1_NAME.0,hostbus=1,hostport=1.1.2"

Launch the guest and try to physically connect and disconnect a USB device to the configured ports. The guest should then recognize such a device automatically.