The API provides a mechanism for managing USB device hotplug events and controlling their attachment to virtual machines. Communication is performed over JSON-encoded messages exchanged through either a TCP or VSOCK connection.
- Each message must be a valid JSON object encoded in UTF-8 and terminated with a newline (\n).
- Each request sent by the client results in a synchronous response from vhotplug.
- Every response contains a result field with value "ok" or "failed".
- In case of "ok", responses may include additional fields depending on the request.
- In case of "failed", an additional error field must be present.
- Clients may enable asynchronous notifications from vhotplug.
- The transport may use either TCP or VSOCK, as configured.
API is enabled by adding the following parameters to the "general" section in the configuration file:
"api": {
"enable": true,
"host": "0.0.0.0",
"port": 2000,
"unixSocket": "/var/lib/vhotplug/vhotplug.sock",
"transports": ["tcp", "vsock", "unix"],
"allowedCids": [3, 4, 5]
}
Supported transports: "tcp", "vsock", "unix".
A USB device is uniquely identified by its device node, which consists of the USB bus and address.
When a USB device is represented in the API, it may contain the following fields:
{
"device_node": "/dev/bus/usb/003/078",
"vid": "1111",
"pid": "2222",
"vendor_name": "Manufacturer",
"product_name": "Product",
"allowed_vms": ["vm1", "vm2"],
"vm": "vm1",
...
}
Depending on the message, extra fields may be present or some fields may be missing. The device_node field is the only one guaranteed to be present.
Request: {"action": "enable_notifications"}
Response: {"result": "ok"}
Request: {"action": "usb_list"}
Response: {"result": "ok", "usb_devices": [{...}, {...}]}
Request: {"action": "usb_attach", "device_node": "/dev/bus/usb/003/078", "vm": "vm1"}
Response: {"result": "ok"}
Request: {"action": "usb_attach", "bus": "1", "port": "2", "vm": "vm1"}
Response: {"result": "ok"}
Request: {"action": "usb_attach", "vid": "1111", "pid": "2222", "vm": "vm1"}
Response: {"result": "ok"}
Request: {"action": "usb_detach", "device_node": "/dev/bus/usb/003/078"}
Response: {"result": "ok"}
Request: {"action": "usb_detach", "bus": "1", "port": "2"}
Response: {"result": "ok"}
Request: {"action": "usb_detach", "vid": "1111", "pid": "2222"}
Response: {"result": "ok"}
{"event": "usb_connected", "usb_device": {...}}
{"event": "usb_disconnected", "usb_device": {...}}
{"event": "usb_attached", "usb_device": {...}, "vm": "vm1"}
{"event": "usb_detached", "usb_device": {...}, "vm": "vm1"}
{"event": "usb_select_vm", "usb_device": {...}, "allowed_vms": ["vm1", "vm2"]}