mirror of
https://dev.lirent.ru/Vatrog/vm-automation-signaling.git
synced 2026-07-11 17:46:37 +03:00
feat(input): daemon sets up the host->guest input-linux bridge via QMP
The uinput devices the input adapter creates were never forwarded into the guest: the input-linux bridge was external (manual monitor object_add), so it was lost on every reconfigure and whenever the kernel-assigned device numbers changed. Make the vmhost seam -- which already owns the VM's single QMP connection -- add the input-linux objects itself on reaching READY (A=keyboard +abs with grab_all, B=mouse) and object_del them on teardown. The input adapter publishes the uinput evdev paths into a per-endpoint home; discovery attaches input before vmhost so the paths are ready. No second QMP socket or connection. Also move the mouse buttons (incl. middle) and the wheel onto device B, so B is a complete relative mouse and A is keyboard+abs only. Bump 0.3.8.
This commit is contained in:
@@ -56,6 +56,10 @@ struct vmsig_discovery {
|
||||
* keep pointers, and detach is deferred, so this must outlive the candidate. Overwritten
|
||||
* only on the NEXT attach to the endpoint, which never races a still-open prior adapter. */
|
||||
vmsig_host_facts ep_facts[VMSIG_SLOT_COUNT];
|
||||
/* Stable per-endpoint home for the uinput evdev paths of the input bridge. The input seam
|
||||
* writes these at attach; the vmhost seam borrows them to add input-linux objects. Same
|
||||
* lifetime discipline as ep_facts (outlives the deferred adapter reap). */
|
||||
struct { char evdev_a[64]; char evdev_b[64]; } ep_bridge[VMSIG_SLOT_COUNT];
|
||||
};
|
||||
|
||||
static uint64_t now_ns(void) {
|
||||
@@ -265,17 +269,27 @@ static void bootstrap_scan(vmsig_discovery* d) {
|
||||
|
||||
static int default_attach(void* ud, vmsig_core* core, uint32_t vmid, uint32_t endpoint,
|
||||
const vmsig_host_facts* f) {
|
||||
(void)ud; (void)vmid;
|
||||
(void)vmid;
|
||||
vmsig_discovery* d = ud; /* default sink carries the discovery handle (ep_bridge home) */
|
||||
char* ev_a = d ? d->ep_bridge[endpoint].evdev_a : NULL;
|
||||
char* ev_b = d ? d->ep_bridge[endpoint].evdev_b : NULL;
|
||||
if (d) { ev_a[0] = '\0'; ev_b[0] = '\0'; } /* clear stale paths from a prior attach */
|
||||
|
||||
vmsig_memctx_cfg mc; memset(&mc, 0, sizeof mc);
|
||||
mc.stub = 0; mc.ram_path = f->ram_path; mc.low = f->low; mc.ro_fd = -1;
|
||||
vmsig_vmhost_cfg vh; memset(&vh, 0, sizeof vh);
|
||||
vh.stub = 0; vh.qmp_path = f->qmp_path;
|
||||
vmsig_input_cfg in; memset(&in, 0, sizeof in);
|
||||
in.stub = 0; in.qmp_path = NULL; /* input is uinput; power/lifecycle via the vmhost seam */
|
||||
/* input is uinput; power/lifecycle via the vmhost seam. The adapter publishes its uinput
|
||||
* evdev paths into ep_bridge so the vmhost seam can forward them via input-linux. */
|
||||
in.stub = 0; in.qmp_path = NULL; in.out_evdev_a = ev_a; in.out_evdev_b = ev_b;
|
||||
vmsig_vmhost_cfg vh; memset(&vh, 0, sizeof vh);
|
||||
/* vmhost borrows the (now-populated) evdev paths to add the input-linux bridge at READY. */
|
||||
vh.stub = 0; vh.qmp_path = f->qmp_path; vh.bridge_evdev_a = ev_a; vh.bridge_evdev_b = ev_b;
|
||||
|
||||
/* Order matters: input attaches BEFORE vmhost so the evdev paths are written into ep_bridge
|
||||
* before the vmhost seam reads them (READY is async and always later than both attaches). */
|
||||
if (vmsig_core_add_adapter(core, vmsig_memctx_ops(), &mc, endpoint) < 0) goto fail;
|
||||
if (vmsig_core_add_adapter(core, vmsig_vmhost_ops(), &vh, endpoint) < 0) goto fail;
|
||||
if (vmsig_core_add_adapter(core, vmsig_input_ops(), &in, endpoint) < 0) goto fail;
|
||||
if (vmsig_core_add_adapter(core, vmsig_vmhost_ops(), &vh, endpoint) < 0) goto fail;
|
||||
return 0;
|
||||
fail:
|
||||
vmsig_core_detach_endpoint(core, endpoint); /* roll back any partial trio (deferred) */
|
||||
@@ -319,7 +333,7 @@ vmsig_discovery* vmsig_discovery_new(vmsig_core* core,
|
||||
pve_conf ? pve_conf : "/etc/pve/qemu-server",
|
||||
qmp_dir ? qmp_dir : "/var/run/qemu-server");
|
||||
if (sink) d->sink = *sink;
|
||||
else { d->sink.attach = default_attach; d->sink.detach = default_detach; d->sink.ud = NULL; }
|
||||
else { d->sink.attach = default_attach; d->sink.detach = default_detach; d->sink.ud = d; }
|
||||
|
||||
slot_load(&d->slots, d->persist ? d->slots_path : NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user