I am trying to pass a keyboard and mouse to a windows hvm (or any hvm) via libvirt xml config. For reference, I do not want to use a USB kvm or use the USB proxy. I do not want the hvm to have control of the usb device. I want to pass this mouse/keyboard inputs via software only. I cannot seem to find a lot of information about passing mouse/keyboard in Xen or qubes specifically. Could the stubdom-linux may be getting in the way?
Can you explain what you want to do, that isn’t already there by default? When you start a HVM, it gets emulated mouse (or rather tablet) and keyboard connected, that sends it input events when you interact with that HVM’s window. It isn’t your real full USB device. So, it sounds like exactly what you want, no?
Technically, qemu running in a stubdomain has built in GUI agent that shows just a single window (the one you see) using our GUI protocol.
I appreciate the fast reply. I want to quickly switch my keyboard and mouse between dom0 and the windows hvm. If i used a linux hvm, I can accomplish this using the input-proxy running from dom0 to the linux hvm to pass a keyboard and mouse. I guess I am curious why a custom libvirt xml for my windows hvm does not actually pass anything windows can see?
Also could I use the emulated mouse and keyboard without creating the VGA or gui agent window?
Edit: I also do not want to pass my usb keyboard/mouse to an untrusted domain and would prefer to just send inputs.
I should have given more context because there may be a solution I am not thinking about.
I have a windows hvm that has an nvidia gpu passed to it. The GPU, xen disk/network drivers are all working. Installing Qubes core agent in windows causes problems. I have read that some users can pass usb to the vm via a usb qube but it seemed not as stable. I also worry that virtually hot plugging a mouse and keyboard from the usb qube to windows and back will just cause issues. I do not need (or on the security side want) windows to have usb control over the mouse and keyboard. I only need the input sent to it.
I have the kind of input system that I want on a Debian HVM by doing the following:
This seems to work very well. I wanted to create ability to switch between the gaming gpu enabled windows 10 and dom0 just like how in the KVM hypervisor you can switch control between host and guest. In KVM’s case it uses an evdev device tag in the libvirt XML. Xen does not have access to this: libvirt: Domain XML format. I do not need this to be built into Xen. I can use the libvirt-evdev program to do the split and switching for me but I cant seem to figure out how to do passthrough of a mouse and keyboard in Xen. In my search for this I cannot find any libvirt or xl config that demonstrates a keyboard/mouse passthrough. I have tried appending this libvirt config without any luck:
I see, so you can’t use the standard input integration because your VM doesn’t have normal VGA (and even if it would, its resolution, and screen location doesn’t match your actual video output through attached GPU.
The way you are trying to do it with libvirt xml won’t work, because it controls qemu that is running inside stubdomain, not dom0. So, it doesn’t have access to whatever /dev/input/* you point it at. It’s probably possible to add input proxy to the stubdomain to transfer input events there, and then attach that to qemu (via libvirt xml), but that will require some tinkering. If you want to try anyway, the stubdomain sources are here: GitHub - QubesOS/qubes-vmm-xen-stubdom-linux. The “full” variant already has qrexec (which is used for USB passthrough), so the missing piece would be “just” input proxy.
Technically, attaching USB keyboard/mouse directly would be simpler to accomplish (if you enable stubdom-qrexec feature using qvm-features tool), but as you correctly identified, it comes with exposing your USB devices to potential attack from that VM.
Unfortunately I don’t see any simple option that would just work and meet your requirements.
Using qrexec-client to pass commands to the stubdomain I can see that the uinput device is being created.
I am now stuck as I cannot run input-proxy-reciever before qemu starts since the vchan connection or socket isn’t established yet. It looks like in the init script for the stubdomain there is a qemu socket you could connect to. I tried finding how to connect to it from dom0 but cannot find any information. Is there a way to add a device while qemu is running?
If there is not a way to add an input device while its running then I will need to use something like libvirt-evdev to create a dummy uinput device for qemu to grab then later forward commands to it. This seems unnecessary to me though.
Update: uinput is working but an evdev or event device isn’t being created in /dev. I am not sure what is needed for that to be created.
I’m stuck in the “attach that to qemu (via libvirt xml)” part, could you please give an example, when I tried using input type passtrough in libvirt as the example above it still says it’s missing the evdev path despite /dev/input/device0 being present in stubdom (I’ve created a dummy to be used until I run: sudo qrexec-client -d example-dm -l 'input-proxy-sender /dev/input/device*' root:'input-proxy-receiver --keyboard')
I am running this all from dom0 only because that is where my keyboard is attached, but the input proxy was designed to run from sys-usb. Ideally I would use sys-usb.
I modified the package but am only copying the rootfs to dom0. I followed the qubes builder page, had it download some sources so I didn’t have to build everything, and then ran make vmm-xen-stubdom-linux. I rebuilt it with CONFIG_INPUT_EVDEV and I do see the correct event device in /dev/input now. Let me know if you have more questions about this part, I can post what I did exactly.
How and at what time during the stub domain boot up are you creating the dummy device? I do not see how to call any qrexec commands before qemu has started in the stub domain. I imagine qemu is trying to use that dummy input before you have created it.
But since you can’t call qrexec commands before qemu starts; It won’t boot unless it gets a valid input device that’s why I’d like to create a fake input that receives the real input if that makes any sense (like a symlink).