This application runs as a service on the host, monitors device add/remove events using libudev and dynamically attaches devices to virtual machines based on rules defined in a configuration file.
- Automatically detects when devices are added or removed from the host.
- Integrates with QEMU and crosvm to add or remove devices in real time.
- Uses libudev for device monitoring on the host.
- No extra udev configuration is required.
- Different device types can be assigned to different virtual machines.
- Supports USB and PCI devices.
- Supports evdev passthrough (virtio-input-host-pci) of non-USB input devices for QEMU.
Device assignment is based on rules defined in the configuration file. Each rule can match devices using one or more parameters. The same parameters can be used in allow and deny rule sets. Only the fields present in a rule are used for matching. If multiple rules match a device, the first match is used.
The following parameters can be used for USB passthrough:
- vendorId — USB vendor ID (e.g., "0bda")
- productId — USB product ID (e.g., "4852")
- vendorName — Vendor name (from udev or USB database, supports regular expressions)
- productName — Product name (from udev or USB database, supports regular expressions)
- bus - USB bus number
- port - USB root port
- interfaceClass — USB interface class (e.g., 224)
- interfaceSubclass — USB interface subclass (e.g., 1)
- interfaceProtocol — USB interface protocol (e.g., 1)
- deviceClass — USB device class (e.g., 224)
- deviceSubclass — USB device subclass (e.g., 1)
- deviceProtocol — USB device protocol (e.g., 1)
Note: Many USB devices are composite devices, meaning they expose multiple interfaces. When matching against interfaceClass, interfaceSubclass and interfaceProtocol, it is sufficient for at least one interface to match the rule. In practice, matching by interfaces is often more reliable than using deviceClass, since many real-world USB devices leave the device-level class fields unset or use generic values like 0 (defined at the interface level instead).
The following parameters can be used for PCI passthrough:
- address — PCI address (e.g. "0000:00:14.3")
- vendorId — PCI vendor ID (e.g., "8086")
- deviceId — PCI device ID (e.g., "a7a1")
- deviceClass — PCI device class (e.g., 2)
- deviceSubclass — PCI device subclass (e.g., 128)
- deviceProgIf — PCI device programming interface (e.g., 0)
sudo python3 -m vhotplug -a -c ./vhotplug.conf
usage: vhotplug [-h] -c CONFIG
[-a | --attach-connected | --no-attach-connected]
[-d | --debug | --no-debug]
Hot-plugging USB devices to the virtual machines
options:
-h, --help show this help message and exit
-c CONFIG, --config CONFIG
Path to the configuration file
-a, --attach-connected, --no-attach-connected
Attach connected devices on startup (default: False)
-d, --debug, --no-debug
Enable debug messages (default: False)
{
"usbPassthrough": [
{
"description": "Devices for VM1",
"targetVm": "vm1",
"allow": [
{
"interfaceClass": 3,
"interfaceProtocol": 2,
"description": "HID Mouse",
},
{
"productName": ".*ethernet.*",
"description": "Ethernet devices",
},
{
"vendorId": "067b",
"productId": "23a3",
"description": "Prolific USB-to-Serial Bridge",
"disable": true
}
],
"deny": [
{
"vendorId": "046d",
"productId": "c52b",
"description": "Logitech, Inc. Unifying Receiver"
},
{
"vendorId": "0b95",
"productId": "1790",
"description": "AX88179 Gigabit Ethernet"
}
]
}
],
"pciPassthrough": [
{
"description": "Devices for VM1",
"targetVm": "vm1",
"allow": [
{
"address": "0000:00:14.3",
"description": "Intel WiFi card"
},
{
"vendorId": "8086",
"deviceId": "a7a1",
"description": "Intel Iris GPU"
}
]
}
],
"evdevPassthrough": {
"disable": true,
"targetVm": "vm1"
},
"vms": [
{
"name": "vm1",
"type": "qemu",
"socket": "/tmp/qmp-socket1"
}
]
}This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
If you would like to contribute to this project, please fork the repository and submit a pull request with your changes.