/* test_uinputlayout.c — DECLARATIVE uinput capability split (pure, no /dev/uinput). * * Verifies the ptr_mode -> A/B role mapping that drives both device creation and the hot-path * button/wheel carrier selection: in PTR_BOTH A is keyboard+abs and B is rel+buttons+wheel, and * the button/wheel carrier is B; single-pointer modes keep buttons+wheel on the sole device. * The actuation ioctls remain armed-only (they need a real /dev/uinput); this covers the logic * that decides the layout, which is the part that single-mode regressions would break. */ #include "vmctl.h" #include "uinput_layout.h" #include static int g_fail = 0; #define CHECK(cond, msg) do { \ if (!(cond)) { printf(" FAIL: %s\n", (msg)); g_fail = 1; } \ } while (0) int main(void) { uinput_role a, b; int btn_on_b; /* PTR_BOTH: A = keyboard + absolute pointer, no buttons/wheel; B = relative pointer + * buttons + wheel; carrier is B. This is the requested layout (mouse buttons incl. middle * and the wheel moved off A onto B). */ vmctl_uinput_layout(VMCTL_PTR_BOTH, &a, &b, &btn_on_b); CHECK(a.present && b.present, "BOTH: two devices"); CHECK(a.want_keyboard, "BOTH: A has keyboard"); CHECK(!a.rel_motion, "BOTH: A is absolute"); CHECK(!a.want_buttons, "BOTH: A has NO mouse buttons"); CHECK(!a.want_wheel, "BOTH: A has NO wheel"); CHECK(!b.want_keyboard, "BOTH: B has no keyboard"); CHECK(b.rel_motion, "BOTH: B is relative"); CHECK(b.want_buttons, "BOTH: B has mouse buttons"); CHECK(b.want_wheel, "BOTH: B has wheel"); CHECK(btn_on_b == 1, "BOTH: button/wheel carrier is B"); /* PTR_REL: single relative device A carries motion + buttons + wheel (no B). */ vmctl_uinput_layout(VMCTL_PTR_REL, &a, &b, &btn_on_b); CHECK(a.present && !b.present, "REL: single device A"); CHECK(a.rel_motion, "REL: A is relative"); CHECK(a.want_buttons, "REL: A has buttons"); CHECK(a.want_wheel, "REL: A has wheel"); CHECK(a.want_keyboard, "REL: A has keyboard"); CHECK(btn_on_b == 0, "REL: carrier is A"); /* PTR_ABS: single absolute device A carries abs + buttons + wheel (the only device). */ vmctl_uinput_layout(VMCTL_PTR_ABS, &a, &b, &btn_on_b); CHECK(a.present && !b.present, "ABS: single device A"); CHECK(!a.rel_motion, "ABS: A is absolute"); CHECK(a.want_buttons, "ABS: A has buttons (sole device)"); CHECK(a.want_wheel, "ABS: A has wheel (sole device)"); CHECK(btn_on_b == 0, "ABS: carrier is A"); /* evdev export contract: a NULL handle reports "not a uinput handle" (-1). The populated * path (real /dev/input/eventN) is armed-only — it needs a created uinput device. */ { char ea[64], eb[64]; CHECK(vmctl_uinput_evdev(NULL, ea, eb) == -1, "evdev export: NULL handle -> -1"); } printf("uinputlayout tests: %s\n", g_fail ? "FAIL" : "PASS"); return g_fail ? 1 : 0; }