qemu-docker icon indicating copy to clipboard operation
qemu-docker copied to clipboard

[Question]: How to handle USB disconnects

Open fizzyduck opened this issue 8 months ago • 5 comments

Is your question not already answered in the FAQ?

  • [x] I made sure the question is not listed in the FAQ.

Is this a general question and not a technical issue?

  • [x] I am sure my question is not about a technical issue.

Question

This might be more of a kvm issue.

I pass a USB Bluetooth adaptor through to the VM using the usb-device method.

Sometimes this device disconnects and is "lost" from the VM. The only way to get it back is to restart the container.

Any thoughts on how I can re-expose it to the VM? I don't mind running a watchdog or similar on either the VM or the host.

fizzyduck avatar Mar 16 '25 17:03 fizzyduck

Looks like I would need to do the equivalent of this:

https://github.com/olavmrk/usb-libvirt-hotplug/blob/master/usb-libvirt-hotplug.sh

fizzyduck avatar Mar 16 '25 18:03 fizzyduck

Ok, it looks like we can use a combination of a qemu monitor socket which is a case of adding an argument:

-monitor unix:/var/run/qemu-monitor-socket,server,nowait

Then inside the docker image (not the VM), the process for reconnecting a host USB device to the VM is:

echo "device_add usb-host,vendorid=0x1b3f,productid=0x2008,id=usbsound" | nc -U -q0 /var/run/qemu-monitor-socket

Or alternatively on the docker host (qemu is the name of the qemu-docker service):

docker-compose exec qemu bash -c 'echo "device_add usb-host,vendorid=0x1b3f,productid=0x2008,id=usbsound" | nc -U -q0 /var/run/qemu-monitor-socket'

Note I've used an id above, so that we can also control device removal:

echo "device_del usbsound" | nc -U -q0 /var/run/qemu-monitor-socket

A daemon could run within the qemu-docker container to watch for hotplug events and if the device matches some docker-compose.yaml configuration supplied attributes, it could invoke the appropriate monitor command.

@kroese Do you have any thoughts on the best way to manage this?

fizzyduck avatar Mar 16 '25 20:03 fizzyduck

@kroese I've got a potential solution for this. I have successfully built mdevd which can run inside the qemu container. This can watch for hotplug events which come via the host and then issue the appropriate command to the qemu socket. I just need to create some logic to handle the matching of the vendorid and productid.

fizzyduck avatar Mar 23 '25 20:03 fizzyduck

I am just guessing, but would this work : https://github.com/sickcodes/Docker-OSX?tab=readme-ov-file#usbfluxd-iphone-usb---network-style-passthrough-osx-kvm-docker-osx ? It's forwarding through a TCP connection, your solution seems much simpler though.

EchoCoder1729 avatar Mar 27 '25 17:03 EchoCoder1729

SO my understanding is that with the server and nowait conditions on qemu-monitor you have ensured that the monitor is always eagerly listening for commands from the unix socket and just need to be provoked with an add device command when the device is reconnected to the host. The trouble is issuing the command from the host at the unix socket as soon as the device is reconnected. Now instead of having a daemon run inside the container, it should be run on the host system and that could be used for filtering out specific hardware. Sure we would be interested in specific hardware mentioned in the compose file but that is long-term support.

For short term we could have a daemon running on the host, monitoring reconnecting usbs using "lsusb -v" changes ( i think it should work? ) and then as soon as the changes concerning a specific device is seen, a command is issued using socat or nc to the qemu-monitor.

Expected latency might be tad bit higher.

EchoCoder1729 avatar Mar 27 '25 20:03 EchoCoder1729