As promised in my previous blog post on the topic, the SPICE protocol is capable of USB redirection. I didn’t dive into it for that post, but now the future is here and I’ve added USB redirection to my Raspberry Pi thin client. I’ve tested it with USB flash drives, webcams, and pretty much all of the USB devices I could find. And I’m here to tell you how it all works.
Adding USB Ports in Proxmox⌗
This one is pretty simple. In the VM’s Hardware panel, you just add USB ports, and select ‘SPICE’. You can add as many as you want. Each USB port you add can be used to pass through one USB device from the client, so add plenty of them. You need to restart the VM when you change the number of USB ports, but you can remap the USB ports you’ve already created while the machine is running (including changing them from SPICE to pass-through of host devices and back).
You can choose either USB2 or USB3 for this. In Proxmox, the underlying emulator (qemu) is emulating a USB host chipset and then attaching all of the USB ports to it, so choosing USB2 or USB3 changes the model fo the emulated chipset. It’s been recommended that the USB2 chipset is more reliable than USB3, and in our use case, it’s unlikely we will ever be able to exceed USB2 bandwidth in a thin client setup anyway (or that we’d want our users to tie up 1G+ of network bandwidth).
Configuring Remote Viewer⌗
At this point, I edited the
thinclient.sh file I created in the previous topic to switch from the locked down kiosk mode to simple full screen mode. you do this by changing
-k --kiosk-quit on-disconnect to
-f in the line which calls remote-viewer. This lets you use the UI of remote viewer by moving your mouse to the top of the screen.
Once you restart remote viewer so you have access to the UI (either reboot, or run
killall xinit over SSH and then
startx -- on the local terminal), you can pick USB devices to redirect from the USB button in the menu at the top. If you don’t have a USB button on the menu, then remote-viewer thinks there are no SPICE USB ports configured on the server, so check your Proxmox config and make sure you reboot if necessary to add more ports.
Of course, when passing through hardware, make sure you don’t pass through something critical to the system. Don’t pass through your actual keyboard and mouse, since you’ll lose the ability to even close the USB redireciton window.
Raspberry Pi Internal USB peripherals⌗
On many models of the Raspberry Pi, devices are connected to the internal USB bus via a USB hub chip. On the Model A, the internal USB root is directly connected to the single USB port. But, on all Model B variants except the Pi 4, the single USB 2 root is connected to a USB hub and USB Ethernet chip. So, if we pass through absolutely everything, then the Ethernet chip will get passed through, and the Pi will lose ethernet. Not a great experience. So, we need to figure out what the USB vendor/product IDs of the Ethernet chip are so we can not pass them through automatically. To do this, use
lsusb which should show a list of connected USB devices. In my case, I get something like this for a Pi 1 with nothing connected:
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
In this case, the Fast Ethernet Adapter at 0424:ec00 is the device we are concerned about. Make sure you do this on the same model of Pi, since each Pi model uses slightly different hardware, especially the 3, 3+, and 4.
SPICE Client USB Redirection Rules⌗
If you want to automatically connect some devices when the thin client starts, or automtaically while it runs, there are command line options for this. However, I was unable to get auto redirect to work in my setup once the thin client was already running - auto connect on start worked fine, and the USB redirection menu also worked fine, but plugging in a device and automatically passing it through didn’t happen.
The manual page is here for reference. It’s essentially all of the information available on the topic.
The key to this is that the rules (on-connect and auto-redirect) are written as a list which follows the following format:
You then chain together rules, which are processed in order, like this
The example given is to block USB human interface devices and pass everything else, which is this:
If you’re crafting rules, a handy reference is the USB device class list.
In my case, I wanto automatically redirect everything but USB HID devices and the USB Fast Ethernet controller on my Pi, so I wrote this rule:
Auto Redirect Script Changes⌗
I added a few new lines to
thinclient.sh from the previous article. Here’s the new last few lines of the file:
#Define USB redirection rule USBREDIR="0x03,-1,-1,-1,0|-1,0x0424,0xec00,-1,0|-1,-1,-1,-1,1" #Call remote-viewer in fullscreen with redirection on connect and auto redirection exec remote-viewer -f --spice-usbredir-auto-redirect-filter="$USBREDIR" --spice-usbredir-redirect-on-connect="$USBREDIR" spiceproxy
With this script, USB devices plugged in to the Pi will redirect when the Pi starts, although I wasn’t able to get them to redirect automatically in this environment.
This is a very useful feature that really sets SPICE apart from a lot of other open source or free VDI protocols. Some VNC servers/clients implement USB on their own (outside of the standard), but as far as I know, the Proxmox VNC server does not support these. Windows Remote Desktop Protocol (RDP) supports both high level redirection (of devices like USB drives and audio with the driver running on the client) as well as low level USB redirection, but it’s disabled by default and requires editing the group policies to allow it. RDP also doesn’t work natively with Linux guests, where SPICE works with all guests (even as far back as Windows XP).