How To Virtualize a Windows 10 machine with a USB peripheral with KVM

Intro

I have a Canon CanoScan 4400F usb scanner and I haven't found a way to directly use it with GNU/Linux. So I scan through a KVM Windows 10 Virtual Machine.

Configuration

Device Owner

On my system, the scanner device is mounted with root owner rights. To be able to use it on my KVM virtual machine, I need to change the owner from root to user.

[user@host ~]$ lsusb | grep "Canon"
Bus 002 Device 002: ID 04a9:2228 Canon, Inc. CanoScan 4400F
[user@host ~]$ ls -l /dev/bus/usb/002/002
crw-rw-r-- 1 root root 189, 129 31 oct.  09:20 /dev/bus/usb/002/002

Temporary solution

A temporary solution is to change the owner from a root prompt. We will have to do it each time after a reboot.

root@host:~# chown user:user /dev/bus/usb/002/002

Permanent solution

To make it works permanently we will create a udev rule.

root@host:~# udevadm info --attribute-walk --path=$(udevadm info --query=path --name=/dev/bus/usb/002/002)
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:14.0/usb2/2-10':
    KERNEL=="2-10"
    SUBSYSTEM=="usb"
[...]
    ATTR{idProduct}=="2228"
    ATTR{idVendor}=="04a9"
[...]

Now we have device attributes we can create our udev rule.

KERNEL=="2-10", SUBSYSTEM=="usb", ATTR{idVendor}=="04a9", ATTR{idProduct}=="2228", OWNER="user", GROUP="user"
root@host:~# udevadm control --reload
root@host:~# udevadm test $(udevadm info --query=path --name=/dev/bus/usb/002/002) | less
[...]
Reading rules file: /etc/udev/rules.d/80-scanner.rules
[...]
[user@host ~]$ ls -l /dev/bus/usb/002/002
crw-rw-r-- 1 user user 189, 129 31 oct.  09:20 /dev/bus/usb/002/002

KVM Hypervisor Configuration

Installation

root@host:~# pacman -S qemu; modprobe virtio

Virtual Disk Creation

root@host:~# qemu-img create -f raw WIN_HDD01 20G

Grow disk size

root@host:~# qemu-img resize -f raw WIN_HDD01 +30G

Download virtio drivers

Link here : Drivers

root@host:~# wget 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso'

Install Windows

[user@host ~]$ qemu-system-x86_64 -smp 2 -net nic,model=e1000,macaddr=52:54:00:12:34:56 -net user,id=mynet0,net=192.168.76.0/24,dhcpstart=192.168.76.9,hostfwd=tcp::5555-:3389 -cpu host -vga cirrus -m 4096 -cdrom /data/en_windows_10_enterprise_ltsc_2019_x64_dvd_74865958.iso -enable-kvm -boot order=d -drive file=/data/WIN_10_LTSB_HDD01,index=0,media=disk,if=virtio,format=raw -drive file=/tmp/virtio-win.iso,media=cdrom,index=3

Load driver

Remote Access

Start VM with RDP redirection and USB

[user@host ~]$ qemu-system-x86_64 -smp 2 -net nic,model=e1000,macaddr=52:55:01:11:34:53 -net user,id=mynet0,net=192.168.76.0/24,dhcpstart=192.168.76.9,hostfwd=tcp::5555-:3389 -cpu host -vga cirrus -m 4096 -enable-kvm -boot order=d -drive file=/vdisks/WIN_HDD01,index=0,media=disk,if=virtio,format=raw -device nec-usb-xhci -device usb-host,hostbus=1,hostaddr=3

RDP to the VM with a shared folder with xfreerdp or rdesktop

Here, two examples with rdesktop and xfreerdp.

To facilitate files transfer between our systems, we will use the redirected folders feature, so the /tmp/share folder will be usable from our Windows :

[user@host ~]$ rdesktop 127.1:5555 -r disk:docs=/tmp/share -0 -r sound:remote
[user@host ~]$ mkdir /tmp/share;xfreerdp /v:127.0.0.1:5555 /w:1900 /h:1024 /cert-ignore /drive:share,/tmp/share
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Contact :