#ifndef VMCTL_H #define VMCTL_H #include /* vmctl.h — public API for a QEMU VM Input layer (actuator): input injection + * power/lifecycle actuation. One handle; the input driver is selected * declaratively through vmctl_config. OS-agnostic surface. */ typedef struct vmctl vmctl_t; /* opaque handle */ /* ===== Input drivers + open ===== */ typedef enum { VMCTL_DRIVER_QMP, /* QMP input-send-event (no guest driver required) */ VMCTL_DRIVER_UINPUT /* host uinput source; optional passthrough into guest */ /* via QEMU virtio-input-host-pci (Linux). uinput != virtio. */ } vmctl_driver; #define VMCTL_PTR_ABS 1 /* uinput: absolute tablet */ #define VMCTL_PTR_REL 2 /* uinput: relative mouse */ #define VMCTL_PTR_BOTH 3 /* uinput: two devices A=abs B=rel */ typedef struct { unsigned bustype; /* HID bus type, e.g. 0x0003 (USB) */ unsigned vendor; /* vendor id */ unsigned product; /* product id */ unsigned version; /* device version */ const char* name; /* device name; library copies it */ } vmctl_uinput_id; typedef struct { vmctl_driver driver; const char* qmp_path; /* QMP unix socket; required for QMP, optional (passthrough) for UINPUT */ const char* input_bus; /* virtio-input-host-pci bus "pci.0" for passthrough; "" = none */ int ptr_mode; /* UINPUT VMCTL_PTR_*; 0 for QMP */ const vmctl_uinput_id* uinput_id; /* UINPUT only; NULL = built-in defaults */ } vmctl_config; vmctl_t* vmctl_open (const vmctl_config* cfg); /* NULL on error */ void vmctl_close(vmctl_t* v); /* safe on NULL */ /* ===== Input constants ===== */ #define VMCTL_ABS_MAX 32767 /* abs coordinates 0..VMCTL_ABS_MAX */ #define VMCTL_AXIS_X 0 #define VMCTL_AXIS_Y 1 #define VMCTL_SCROLL_V 0 /* vertical */ #define VMCTL_SCROLL_H 1 /* horizontal */ #define VMCTL_BTN_LEFT 0 #define VMCTL_BTN_RIGHT 1 #define VMCTL_BTN_MIDDLE 2 #define VMCTL_BTN_SIDE 3 #define VMCTL_BTN_EXTRA 4 #define VMCTL_BTN_FORWARD 5 #define VMCTL_BTN_BACK 6 #define VMCTL_BTN_TASK 7 /* ===== Event batch (value-type, stack; build ONLY via builders — ev[] is not API) ===== */ #define VMCTL_BATCH_MAX 64 typedef struct { int kind; /* internal event-kind code; set by builders */ int code; /* axis / button / evdev-code (per kind) */ int value; /* abs-value / rel-delta / down(0|1) */ double scroll; /* scroll magnitude (scroll only) */ } vmctl_event; typedef struct { vmctl_event ev[VMCTL_BATCH_MAX]; int count; } vmctl_batch; void vmctl_batch_init (vmctl_batch* b); void vmctl_batch_abs (vmctl_batch* b, int axis, int value); void vmctl_batch_rel (vmctl_batch* b, int axis, int delta); void vmctl_batch_btn (vmctl_batch* b, int btn, int down); void vmctl_batch_key (vmctl_batch* b, int evdev_code, int down); void vmctl_batch_scroll(vmctl_batch* b, int axis, double value); int vmctl_batch_send (vmctl_t* v, vmctl_batch* b); /* one round-trip; 0=ok, -1=err */ /* ===== Single events (wrappers over a 1-event batch) ===== */ int vmctl_abs (vmctl_t* v, int axis, int value); /* 0..VMCTL_ABS_MAX */ int vmctl_rel (vmctl_t* v, int axis, int delta); int vmctl_btn (vmctl_t* v, int btn, int down); /* VMCTL_BTN_* */ int vmctl_key (vmctl_t* v, int evdev_code, int down); /* Linux KEY_* */ int vmctl_scroll(vmctl_t* v, int axis, double value); /* VMCTL_SCROLL_* */ /* ===== Power/lifecycle actuation (requires a QMP connection; -1 if there is none) ===== */ int vmctl_powerdown(vmctl_t* v); /* system_powerdown (ACPI soft-off) */ int vmctl_reset (vmctl_t* v); /* system_reset */ int vmctl_wakeup (vmctl_t* v); /* system_wakeup (from S3/S4) */ int vmctl_pause (vmctl_t* v); /* stop */ int vmctl_resume (vmctl_t* v); /* cont */ /* Transfer sequencing/context belongs to signaling; timing and decisions to * control; reading VM state to sensors. Here, in the Input layer, only atomic * actuation. */ #endif /* VMCTL_H */