The libvirt documentation gives an example of how to pass a device by its idVendor and idProduct numbers, but what if you have several devices with the same numbers?

This quick tip shows how to pass in a USB device using the "bus:device" address format.

Like other libvirt configuration routines, we need to provide it with some XML:

  <hostdev mode='subsystem' type='usb'>
    <source startupPolicy='optional'>
      <address bus="002" dev="035"/>

The bus and device numbers can change every time you (re)plug your peripheral into a USB port, with only the bus number being stable for a given port. The linux USB subsystem will reassign a new device number each time a device has been plugged in, regardless of whether it has been plugged in before.

We can use a bash script to parameterize the hostdev element, allowing us to determine and provide the values dynamically.

Let's say that we want the last USB device according to devnum, and that our manufacturer string contains the substring "Hermit". We can find our device with the following bash script:

address=$(lsusb | grep "Hermit's" |\
	awk -e '{print $2 " " $4 }' |\
  sed -e 's/\:$//' |\
  sed -e 's/\b0*//g' |\
  sort -k 2 | tail -1)
busnum=$(echo $address | cut -f 1 -d \  -- )
devnum=$(echo $address | cut -f 2 -d \  -- )

echo address = $address
echo busnum = $busnum
echo devnum = $devnum

# Tell virsh about the USB device
cat <<EOF > virt-usb.xml
  <hostdev mode='subsystem' type='usb'>
    <source startupPolicy='optional'>
      <address bus='$busnum' device='$devnum'/>

virsh attach-device kdev virt-usb.xml --config

...and you'd now proceed to launch your VM.

© 2020