USB passthrough not working with QEMU

VM running through QEMU is unable to detect usb host devices.

I’ve tried several fixes and haven’t been able to fix this. Any help regarding this is highly appreciated !

System specs:

OS: Manjaro Linux x86_64 
Host: Motherboard 
Kernel: 6.11.10-2-MANJARO 
Uptime: 5 hours, 25 mins 
Packages: 1243 (pacman) 
Shell: bash 5.2.37 
Resolution: 1920x1080 
DE: Plasma 6.2.4 
WM: KWin 
Theme: Breeze-Dark [GTK2], Breeze [GTK3] 
Icons: breeze [GTK2/3] 
Terminal: konsole 
CPU: Cpu 
GPU: Gpu
Memory: 2545MiB / 15917MiB 

QEMU command:

qemu-system-x86_64 \
 -enable-kvm \
 -M q35 \
 -m 4096 -smp 2 -cpu host \
 -bios /home/user/uefi/OVMF.4m.fd \
 -drive file=/home/user/qcow/vm.qcow2,format=qcow2,if=virtio \
 -usb \
 -device virtio-tablet \
 -device virtio-keyboard \
 -device qemu-xhci,id=xhci \
 -device usb-host,hostbus=001,hostport=001 \
 -device usb-host,hostbus=004,hostport=001 \
 -machine vmport=off \
 -device virtio-vga-gl \
 -display sdl,gl=on \
 -device ich9-intel-hda,id=sound0,bus=pcie.0,addr=0x1b \
 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 \
 -global ICH9-LPC.disable_s3=1 \
 -global ICH9-LPC.disable_s4=1 \
 -net nic,model=virtio,macaddr=52:54:00:00:00:01 \
 -net bridge,br=br0

I’ve tried other arguments for the usb-host line:

 -device usb-host,vendorid=0x1234,productid=0x1234

OR

 -device usb-host,hostbus=003,hostaddr=001

but the behaviour remains the same:
While QEMU does not output any errors, the guest VM is not able to detect the usb device at all.

The ONLY method I’ve been able to get to work is when I mention the path of the usb device /dev/bus/usb/003/001 AND run qemu with sudo OR change the permissions of the usb device manually.

Is there any way to get usb-passthrough to work without needing sudo priviledges ?

Why not make your life a bit easier and use virt-manager?
The GUI makes things easier …

I have been using virt-manager until recently.

It’s just that the graphics performance is significantly worse (even with 3D Acceleration enabled) than what I get by using just qemu, the graphics performance is almost like bare metal !

Youtube videos play at a smooth 60fps without any tearing or skipping.
Games like stardew valley also run at smooth framerate.

Oh, if it helps, I’m using a variety of distros in different VMs including Manjaro, Debian, PopOS etc.

Okay, well it’s been a couple of days and since nobody seemed interested in this, thus I tried to figure it out on my own.

I am sharing my findings over here for anyone who may encounter this issue in the future.

This is what I think is causing the problem:

The functionality for each type of USB device is different (USB pendrive vs USB printer), thus it’s handled by the kernel differently, and then the functionality of those devices are made available to the userspace by the kernel.

Now, QEMU tries to access access the USB devices directly in order to pass them through to the guest. This fails because the files representing the usb devices are owned by root.

This is the solution I’ve settled for:

First let’s clear up a few things, I was referencing the wrong device path all this time.
It’s not this: /dev/bus/usb/003/001
But infact this: /sys/bus/usb/devices/3-1

This is what should be used with QEMU:
-device usb-host,hostbus=3,hostport=1
This will passthrough the physical usb port to the guest vm, so you can use any usb device you want with it.

And obviously you need to set the correct permissions for the USB device itself using udev:
# vim /etc/udev/rules.d/99-qemu-usb.rules
And set the following permissions:
KERNEL=="3-1", OWNER="USER", MODE="0660"

Replace “USER” with your own user where qemu is running.
Replace “3-1” with the physical port you want to passthrough.
Here 3 is the host bus and 1 is the host port.

You have to do a bit of trial and error to figure out which physical port on your PC/Laptop corresponds to which bus and port number.

I had to tinker around and keep track of the ports using this:
$ watch -n 1 lsusb -t

You can even setup multiple ports in the same udev rules file.
After saving the file, just apply them:
# udevadm control --reload-rules
# udevadm control --reload
# udevadm trigger
Reboot your pc just to be safe.

And that’s it ! I hope this helped fix your issue !

2 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.