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.
This commit is contained in:
2026-06-24 16:41:46 +03:00
parent d6c45ddb04
commit 228dc5af79
3 changed files with 10 additions and 8 deletions
+1 -1
View File
@@ -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)
+5 -3
View File
@@ -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);
+4 -4
View File
@@ -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);