From 228dc5af792a9d49effa42825fdd13467a272e1f Mon Sep 17 00:00:00 2001 From: Gregory Lirent Date: Wed, 24 Jun 2026 16:41:46 +0300 Subject: [PATCH] fix(input): use the hyphenated QMP object-add/object-del command names The 0.3.8 bridge sent object_add/object_del (underscores, modeled on the legacy device_add) but QMP's object commands are hyphenated -- object-add/object-del -- so QEMU rejected them with CommandNotFound and no bridge was set up. Confirmed against the live monitor: object-add/object-del exist, object_add does not, and input-linux is a creatable type. The stub QMP in the unit test used the same wrong string, so it didn't catch this -- only the armed monitor did. Bump 0.3.9. --- CMakeLists.txt | 2 +- src/adapter/vmhost/vmhost.c | 8 +++++--- src/test/test_vmhost.c | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2367c62..6ee4565 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) # Single source of truth for the version: CI passes -DVMSIG_VERSION=${TAG#v}, so the project # version (-> libvgpu-perception SONAME/.so version) and the .deb version come from one tag. -set(VMSIG_VERSION "0.3.8" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag") +set(VMSIG_VERSION "0.3.9" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag") project(vmsig VERSION ${VMSIG_VERSION} LANGUAGES C) set(CMAKE_C_STANDARD 17) diff --git a/src/adapter/vmhost/vmhost.c b/src/adapter/vmhost/vmhost.c index 25e6e58..1033cf8 100644 --- a/src/adapter/vmhost/vmhost.c +++ b/src/adapter/vmhost/vmhost.c @@ -133,7 +133,9 @@ static int bridge_add(struct vmsig_adapter* a, char ab, const char* evdev, int g uint32_t qid = ++a->next_id; char line[320]; int len = snprintf(line, sizeof line, - "{\"execute\":\"object_add\",\"arguments\":{\"qom-type\":\"input-linux\"," + /* QMP object commands use HYPHENS (object-add/object-del); only the legacy + * device_add/device_del keep underscores. Underscore here => CommandNotFound. */ + "{\"execute\":\"object-add\",\"arguments\":{\"qom-type\":\"input-linux\"," "\"id\":\"%s\",\"evdev\":\"%s\"%s},\"id\":%u}\r\n", id, evdev, grab_all ? ",\"grab_all\":true" : "", qid); p->used = 1; p->id = qid; p->origin = 0; p->corr = 0; p->op = VH_OP_BRIDGE_ADD; @@ -150,7 +152,7 @@ static void bridge_del_fire(struct vmsig_adapter* a, char ab) { bridge_id(id, sizeof id, a->endpoint, ab); char line[160]; int len = snprintf(line, sizeof line, - "{\"execute\":\"object_del\",\"arguments\":{\"id\":\"%s\"}}\r\n", id); + "{\"execute\":\"object-del\",\"arguments\":{\"id\":\"%s\"}}\r\n", id); ssize_t r = write(a->fd, line, (size_t)len); (void)r; } @@ -227,7 +229,7 @@ static void handle_line(struct vmsig_adapter* a, const char* line) { /* Bridge infrastructure: never surfaces to control. Log a failed add so the * stand can see it; otherwise silent. */ if (p->op == VH_OP_BRIDGE_ADD && strstr(line, "\"error\"")) - fprintf(stderr, "vmsig vmhost: input-linux object_add failed: %s\n", line); + fprintf(stderr, "vmsig vmhost: input-linux object-add failed: %s\n", line); } else if (p->op == VMSIG_VMOP_QUERY && strstr(line, "\"return\"")) { char stbuf[32]; uint32_t s = VMSIG_VM_UNKNOWN; if (jstr(line, "\"status\"", stbuf, sizeof stbuf)) s = status_state(stbuf); diff --git a/src/test/test_vmhost.c b/src/test/test_vmhost.c index a644fcc..dbf0012 100644 --- a/src/test/test_vmhost.c +++ b/src/test/test_vmhost.c @@ -142,7 +142,7 @@ int main(void) { /* On READY the seam adds the input-linux bridge BEFORE the SEAM_UP-driven CMD_VM query * (bridge ids 1,2; query id 3). Verify both object_add lines and their properties. */ - CHECK(srv_expect(c, "object_add"), "seam sent object_add (input-linux bridge)"); + CHECK(srv_expect(c, "object-add"), "seam sent object-add (input-linux bridge)"); CHECK(srv_expect(c, "\"input-linux\""), "bridge object uses qom-type input-linux"); CHECK(srv_expect(c, "\"vmsig-in-a-0\""), "bridge A has neutral per-endpoint id"); CHECK(srv_expect(c, "\"vmsig-in-b-0\""), "bridge B has neutral per-endpoint id"); @@ -224,12 +224,12 @@ int main(void) { pthread_join(th2, NULL); vmsig_core_free(core2); - for (int i = 0; i < 50 && !strstr(g_rx, "object_del"); i++) { + for (int i = 0; i < 50 && !strstr(g_rx, "object-del"); i++) { rx_pump(c2); struct timespec t = { 0, 10 * 1000000 }; nanosleep(&t, NULL); } - const char* d = strstr(g_rx, "object_del"); - CHECK(d != NULL, "scenario2: teardown fired object_del"); + const char* d = strstr(g_rx, "object-del"); + CHECK(d != NULL, "scenario2: teardown fired object-del"); CHECK(strstr(g_rx, "vmsig-in-a-0"), "scenario2: object_del for bridge A"); CHECK(strstr(g_rx, "vmsig-in-b-0"), "scenario2: object_del for bridge B"); close(c2);