fix(input): resolve the real evdev node for input-linux, not the sysfs name

UI_GET_SYSNAME returns the input-class directory name (inputNNN), not a usable
device node -- /dev/input/inputNNN does not exist, so QEMU's input-linux failed
with "Could not open". Resolve the actual evdev node (/dev/input/eventN) as the
event* child of /sys/class/input/<sysname>/. Confirmed against the live host
sysfs. The unit path can't exercise this (no /dev/uinput in CI) -- armed only.

Bump 0.3.10.
This commit is contained in:
2026-06-24 16:50:05 +03:00
parent 228dc5af79
commit 85041c12ab
2 changed files with 24 additions and 3 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.9" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag")
set(VMSIG_VERSION "0.3.10" CACHE STRING "Release version (MAJOR.MINOR.PATCH); CI passes the tag")
project(vmsig VERSION ${VMSIG_VERSION} LANGUAGES C)
set(CMAKE_C_STANDARD 17)
+23 -2
View File
@@ -31,6 +31,7 @@
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <linux/uinput.h>
#include <linux/input-event-codes.h>
@@ -120,8 +121,28 @@ static int uinput_create(const uinput_role* role, const vmctl_uinput_id* id,
char sysname[64] = {0};
evdev[0] = '\0';
if (ioctl(fd, UI_GET_SYSNAME(sizeof sysname), sysname) >= 0)
snprintf(evdev, 64, "/dev/input/%s", sysname);
/* UI_GET_SYSNAME returns the input-class directory name (e.g. "input174"), NOT the usable
* device node: a bare /dev/input/<sysname> does not exist (QEMU input-linux fails to open
* it). The evdev character device is /dev/input/eventN, exposed as the "event*" child of
* /sys/class/input/<sysname>/ — resolve it there. */
if (ioctl(fd, UI_GET_SYSNAME(sizeof sysname), sysname) >= 0) {
char dpath[128];
snprintf(dpath, sizeof dpath, "/sys/class/input/%s", sysname);
DIR* dir = opendir(dpath);
if (dir) {
struct dirent* de;
while ((de = readdir(dir)) != NULL)
if (strncmp(de->d_name, "event", 5) == 0) {
size_t nl = strlen(de->d_name);
if (nl + 11 < 64) { /* "/dev/input/" is 11 chars + name + NUL */
memcpy(evdev, "/dev/input/", 11);
memcpy(evdev + 11, de->d_name, nl + 1);
}
break;
}
closedir(dir);
}
}
if (!evdev[0]) {
ioctl(fd, UI_DEV_DESTROY);