Hi
On Wed, Jun 10, 2026 at 2:58 PM Marc-André Lureau
<[email protected]> wrote:
>
> Replace the legacy QEMUPutMouseEvent callbacks with a proper
> QemuInputHandler registration. The device now receives typed
> input events (BTN/ABS/REL) directly.
>
> Signed-off-by: Marc-André Lureau <[email protected]>
One of the 2 patches missing ack/review in this series,
thanks
> ---
> hw/usb/dev-wacom.c | 155
> ++++++++++++++++++++++++++++++++---------------------
> 1 file changed, 94 insertions(+), 61 deletions(-)
>
> diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
> index 14d07e81281..c69e247f7b7 100644
> --- a/hw/usb/dev-wacom.c
> +++ b/hw/usb/dev-wacom.c
> @@ -42,10 +42,10 @@
> struct USBWacomState {
> USBDevice dev;
> USBEndpoint *intr;
> - QEMUPutMouseEntry *eh_entry;
> - int dx, dy, dz, buttons_state;
> - int x, y;
> - int mouse_grabbed;
> + QemuInputHandlerState *hs;
> + int axis[INPUT_AXIS__MAX];
> + int dz;
> + bool btns[INPUT_BUTTON__MAX];
> enum {
> WACOM_MODE_HID = 1,
> WACOM_MODE_WACOM = 2,
> @@ -188,29 +188,37 @@ static const USBDesc desc_wacom = {
> .str = desc_strings,
> };
>
> -static void usb_mouse_event(void *opaque,
> - int dx1, int dy1, int dz1, int buttons_state)
> +static void usb_wacom_input_event(DeviceState *dev, QemuConsole *src,
> + QemuInputEvent *evt)
> {
> - USBWacomState *s = opaque;
> + USBWacomState *s = USB_WACOM(dev);
>
> - s->dx += dx1;
> - s->dy += dy1;
> - s->dz += dz1;
> - s->buttons_state = buttons_state;
> - s->changed = 1;
> - usb_wakeup(s->intr, 0);
> + switch (evt->type) {
> + case INPUT_EVENT_KIND_BTN:
> + if (evt->btn.down) {
> + if (evt->btn.button == INPUT_BUTTON_WHEEL_UP) {
> + s->dz--;
> + } else if (evt->btn.button == INPUT_BUTTON_WHEEL_DOWN) {
> + s->dz++;
> + }
> + }
> + s->btns[evt->btn.button] = evt->btn.down;
> + break;
> + case INPUT_EVENT_KIND_ABS:
> + s->axis[evt->abs.axis] = evt->abs.value;
> + break;
> + case INPUT_EVENT_KIND_REL:
> + s->axis[evt->rel.axis] += evt->rel.value;
> + break;
> + default:
> + break;
> + }
> }
>
> -static void usb_wacom_event(void *opaque,
> - int x, int y, int dz, int buttons_state)
> +static void usb_wacom_input_sync(DeviceState *dev)
> {
> - USBWacomState *s = opaque;
> + USBWacomState *s = USB_WACOM(dev);
>
> - /* scale to Penpartner resolution */
> - s->x = (x * 5040 / 0x7FFF);
> - s->y = (y * 3780 / 0x7FFF);
> - s->dz += dz;
> - s->buttons_state = buttons_state;
> s->changed = 1;
> usb_wakeup(s->intr, 0);
> }
> @@ -225,32 +233,57 @@ static inline int int_clamp(int val, int vmin, int vmax)
> return val;
> }
>
> +static void usb_wacom_register_input_handler(USBWacomState *s, bool absolute)
> +{
> + static const QemuInputHandler usb_wacom_abs_handler = {
> + .name = "QEMU PenPartner tablet",
> + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
> + .event = usb_wacom_input_event,
> + .sync = usb_wacom_input_sync,
> + };
> +
> + static const QemuInputHandler usb_wacom_rel_handler = {
> + .name = "QEMU PenPartner tablet",
> + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
> + .event = usb_wacom_input_event,
> + .sync = usb_wacom_input_sync,
> + };
> +
> + const QemuInputHandler *h = absolute ?
> + &usb_wacom_abs_handler : &usb_wacom_rel_handler;
> +
> + g_clear_pointer(&s->hs, qemu_input_handler_unregister);
> +
> + s->hs = qemu_input_handler_register(DEVICE(s), h);
> + qemu_input_handler_activate(s->hs);
> +}
> +
> static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
> {
> int dx, dy, dz, b, l;
>
> - if (!s->mouse_grabbed) {
> - s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
> - "QEMU PenPartner tablet");
> - qemu_activate_mouse_event_handler(s->eh_entry);
> - s->mouse_grabbed = 1;
> + if (!s->hs) {
> + usb_wacom_register_input_handler(s, false);
> }
>
> - dx = int_clamp(s->dx, -128, 127);
> - dy = int_clamp(s->dy, -128, 127);
> + dx = int_clamp(s->axis[INPUT_AXIS_X], -128, 127);
> + dy = int_clamp(s->axis[INPUT_AXIS_Y], -128, 127);
> dz = int_clamp(s->dz, -128, 127);
>
> - s->dx -= dx;
> - s->dy -= dy;
> + s->axis[INPUT_AXIS_X] -= dx;
> + s->axis[INPUT_AXIS_Y] -= dy;
> s->dz -= dz;
>
> b = 0;
> - if (s->buttons_state & MOUSE_EVENT_LBUTTON)
> + if (s->btns[INPUT_BUTTON_LEFT]) {
> b |= 0x01;
> - if (s->buttons_state & MOUSE_EVENT_RBUTTON)
> + }
> + if (s->btns[INPUT_BUTTON_RIGHT]) {
> b |= 0x02;
> - if (s->buttons_state & MOUSE_EVENT_MBUTTON)
> + }
> + if (s->btns[INPUT_BUTTON_MIDDLE]) {
> b |= 0x04;
> + }
>
> buf[0] = b;
> buf[1] = dx;
> @@ -265,32 +298,40 @@ static int usb_mouse_poll(USBWacomState *s, uint8_t
> *buf, int len)
>
> static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
> {
> - int b;
> + int b, x, y;
>
> - if (!s->mouse_grabbed) {
> - s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
> - "QEMU PenPartner tablet");
> - qemu_activate_mouse_event_handler(s->eh_entry);
> - s->mouse_grabbed = 1;
> + if (!s->hs) {
> + usb_wacom_register_input_handler(s, true);
> }
>
> b = 0;
> - if (s->buttons_state & MOUSE_EVENT_LBUTTON)
> + if (s->btns[INPUT_BUTTON_LEFT]) {
> b |= 0x01;
> - if (s->buttons_state & MOUSE_EVENT_RBUTTON)
> + }
> + if (s->btns[INPUT_BUTTON_RIGHT]) {
> b |= 0x40;
> - if (s->buttons_state & MOUSE_EVENT_MBUTTON)
> + }
> + if (s->btns[INPUT_BUTTON_MIDDLE]) {
> b |= 0x20; /* eraser */
> + }
>
> - if (len < 7)
> + if (len < 7) {
> return 0;
> + }
> +
> + x = qemu_input_scale_axis(s->axis[INPUT_AXIS_X],
> + INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
> + 0, 5040);
> + y = qemu_input_scale_axis(s->axis[INPUT_AXIS_Y],
> + INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
> + 0, 3780);
>
> buf[0] = s->mode;
> buf[5] = 0x00 | (b & 0xf0);
> - buf[1] = s->x & 0xff;
> - buf[2] = s->x >> 8;
> - buf[3] = s->y & 0xff;
> - buf[4] = s->y >> 8;
> + buf[1] = x & 0xff;
> + buf[2] = x >> 8;
> + buf[3] = y & 0xff;
> + buf[4] = y >> 8;
> if (b & 0x3f) {
> buf[6] = 0;
> } else {
> @@ -302,15 +343,13 @@ static int usb_wacom_poll(USBWacomState *s, uint8_t
> *buf, int len)
>
> static void usb_wacom_handle_reset(USBDevice *dev)
> {
> - USBWacomState *s = (USBWacomState *) dev;
> + USBWacomState *s = USB_WACOM(dev);
>
> - s->dx = 0;
> - s->dy = 0;
> + memset(s->axis, 0, sizeof(s->axis));
> + memset(s->btns, 0, sizeof(s->btns));
> s->dz = 0;
> - s->x = 0;
> - s->y = 0;
> - s->buttons_state = 0;
> s->mode = WACOM_MODE_HID;
> + g_clear_pointer(&s->hs, qemu_input_handler_unregister);
> }
>
> static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
> @@ -337,10 +376,7 @@ static void usb_wacom_handle_control(USBDevice *dev,
> USBPacket *p,
> }
> break;
> case WACOM_SET_REPORT:
> - if (s->mouse_grabbed) {
> - qemu_remove_mouse_event_handler(s->eh_entry);
> - s->mouse_grabbed = 0;
> - }
> + g_clear_pointer(&s->hs, qemu_input_handler_unregister);
> s->mode = data[0];
> break;
> case WACOM_GET_REPORT:
> @@ -400,10 +436,7 @@ static void usb_wacom_unrealize(USBDevice *dev)
> {
> USBWacomState *s = (USBWacomState *) dev;
>
> - if (s->mouse_grabbed) {
> - qemu_remove_mouse_event_handler(s->eh_entry);
> - s->mouse_grabbed = 0;
> - }
> + g_clear_pointer(&s->hs, qemu_input_handler_unregister);
> }
>
> static void usb_wacom_realize(USBDevice *dev, Error **errp)
>
> --
> 2.54.0
>
>