hw/usb/dev-wacom: convert to modern QemuInputHandler API
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 <marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Marc-André Lureau committed
Jun 8, 2026 at 13:21 UTC
666474692075ac27683e766c46578879455c1bdc
1 file changed
+94
-61
hw/usb/dev-wacom.c
+94
-61
@@ -42,10 +42,10 @@
42
struct USBWacomState {
43
USBDevice dev;
44
USBEndpoint *intr;
45
- QEMUPutMouseEntry *eh_entry;
46
- int dx, dy, dz, buttons_state;
47
- int x, y;
48
- int mouse_grabbed;
45
+ QemuInputHandlerState *hs;
46
+ int axis[INPUT_AXIS__MAX];
47
+ int dz;
48
+ bool btns[INPUT_BUTTON__MAX];
49
enum {
50
WACOM_MODE_HID = 1,
51
WACOM_MODE_WACOM = 2,
@@ -188,29 +188,37 @@ static const USBDesc desc_wacom = {
188
.str = desc_strings,
189
};
190
191
-static void usb_mouse_event(void *opaque,
192
- int dx1, int dy1, int dz1, int buttons_state)
191
+static void usb_wacom_input_event(DeviceState *dev, QemuConsole *src,
192
+ QemuInputEvent *evt)
193
{
194
- USBWacomState *s = opaque;
194
+ USBWacomState *s = USB_WACOM(dev);
195
196
- s->dx += dx1;
197
- s->dy += dy1;
198
- s->dz += dz1;
199
- s->buttons_state = buttons_state;
200
- s->changed = 1;
201
- usb_wakeup(s->intr, 0);
196
+ switch (evt->type) {
197
+ case INPUT_EVENT_KIND_BTN:
198
+ if (evt->btn.down) {
199
+ if (evt->btn.button == INPUT_BUTTON_WHEEL_UP) {
200
+ s->dz--;
201
+ } else if (evt->btn.button == INPUT_BUTTON_WHEEL_DOWN) {
202
+ s->dz++;
203
+ }
204
+ }
205
+ s->btns[evt->btn.button] = evt->btn.down;
206
+ break;
207
+ case INPUT_EVENT_KIND_ABS:
208
+ s->axis[evt->abs.axis] = evt->abs.value;
209
+ break;
210
+ case INPUT_EVENT_KIND_REL:
211
+ s->axis[evt->rel.axis] += evt->rel.value;
212
+ break;
213
+ default:
214
+ break;
215
+ }
216
}
217
204
-static void usb_wacom_event(void *opaque,
205
- int x, int y, int dz, int buttons_state)
218
+static void usb_wacom_input_sync(DeviceState *dev)
219
{
207
- USBWacomState *s = opaque;
220
+ USBWacomState *s = USB_WACOM(dev);
221
209
- /* scale to Penpartner resolution */
210
- s->x = (x * 5040 / 0x7FFF);
211
- s->y = (y * 3780 / 0x7FFF);
212
- s->dz += dz;
213
- s->buttons_state = buttons_state;
222
s->changed = 1;
223
usb_wakeup(s->intr, 0);
224
}
@@ -225,32 +233,57 @@ static inline int int_clamp(int val, int vmin, int vmax)
233
return val;
234
}
235
236
+static void usb_wacom_register_input_handler(USBWacomState *s, bool absolute)
237
+{
238
+ static const QemuInputHandler usb_wacom_abs_handler = {
239
+ .name = "QEMU PenPartner tablet",
240
+ .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_ABS,
241
+ .event = usb_wacom_input_event,
242
+ .sync = usb_wacom_input_sync,
243
+ };
244
+
245
+ static const QemuInputHandler usb_wacom_rel_handler = {
246
+ .name = "QEMU PenPartner tablet",
247
+ .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
248
+ .event = usb_wacom_input_event,
249
+ .sync = usb_wacom_input_sync,
250
+ };
251
+
252
+ const QemuInputHandler *h = absolute ?
253
+ &usb_wacom_abs_handler : &usb_wacom_rel_handler;
254
+
255
+ g_clear_pointer(&s->hs, qemu_input_handler_unregister);
256
+
257
+ s->hs = qemu_input_handler_register(DEVICE(s), h);
258
+ qemu_input_handler_activate(s->hs);
259
+}
260
+
261
static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
262
{
263
int dx, dy, dz, b, l;
264
232
- if (!s->mouse_grabbed) {
233
- s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
234
- "QEMU PenPartner tablet");
235
- qemu_activate_mouse_event_handler(s->eh_entry);
236
- s->mouse_grabbed = 1;
265
+ if (!s->hs) {
266
+ usb_wacom_register_input_handler(s, false);
267
}
268
239
- dx = int_clamp(s->dx, -128, 127);
240
- dy = int_clamp(s->dy, -128, 127);
269
+ dx = int_clamp(s->axis[INPUT_AXIS_X], -128, 127);
270
+ dy = int_clamp(s->axis[INPUT_AXIS_Y], -128, 127);
271
dz = int_clamp(s->dz, -128, 127);
272
243
- s->dx -= dx;
244
- s->dy -= dy;
273
+ s->axis[INPUT_AXIS_X] -= dx;
274
+ s->axis[INPUT_AXIS_Y] -= dy;
275
s->dz -= dz;
276
277
b = 0;
248
- if (s->buttons_state & MOUSE_EVENT_LBUTTON)
278
+ if (s->btns[INPUT_BUTTON_LEFT]) {
279
b |= 0x01;
250
- if (s->buttons_state & MOUSE_EVENT_RBUTTON)
280
+ }
281
+ if (s->btns[INPUT_BUTTON_RIGHT]) {
282
b |= 0x02;
252
- if (s->buttons_state & MOUSE_EVENT_MBUTTON)
283
+ }
284
+ if (s->btns[INPUT_BUTTON_MIDDLE]) {
285
b |= 0x04;
286
+ }
287
288
buf[0] = b;
289
buf[1] = dx;
@@ -265,32 +298,40 @@ static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
298
299
static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
300
{
268
- int b;
301
+ int b, x, y;
302
270
- if (!s->mouse_grabbed) {
271
- s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
272
- "QEMU PenPartner tablet");
273
- qemu_activate_mouse_event_handler(s->eh_entry);
274
- s->mouse_grabbed = 1;
303
+ if (!s->hs) {
304
+ usb_wacom_register_input_handler(s, true);
305
}
306
307
b = 0;
278
- if (s->buttons_state & MOUSE_EVENT_LBUTTON)
308
+ if (s->btns[INPUT_BUTTON_LEFT]) {
309
b |= 0x01;
280
- if (s->buttons_state & MOUSE_EVENT_RBUTTON)
310
+ }
311
+ if (s->btns[INPUT_BUTTON_RIGHT]) {
312
b |= 0x40;
282
- if (s->buttons_state & MOUSE_EVENT_MBUTTON)
313
+ }
314
+ if (s->btns[INPUT_BUTTON_MIDDLE]) {
315
b |= 0x20; /* eraser */
316
+ }
317
285
- if (len < 7)
318
+ if (len < 7) {
319
return 0;
320
+ }
321
+
322
+ x = qemu_input_scale_axis(s->axis[INPUT_AXIS_X],
323
+ INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
324
+ 0, 5040);
325
+ y = qemu_input_scale_axis(s->axis[INPUT_AXIS_Y],
326
+ INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
327
+ 0, 3780);
328
329
buf[0] = s->mode;
330
buf[5] = 0x00 | (b & 0xf0);
290
- buf[1] = s->x & 0xff;
291
- buf[2] = s->x >> 8;
292
- buf[3] = s->y & 0xff;
293
- buf[4] = s->y >> 8;
331
+ buf[1] = x & 0xff;
332
+ buf[2] = x >> 8;
333
+ buf[3] = y & 0xff;
334
+ buf[4] = y >> 8;
335
if (b & 0x3f) {
336
buf[6] = 0;
337
} else {
@@ -302,15 +343,13 @@ static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
343
344
static void usb_wacom_handle_reset(USBDevice *dev)
345
{
305
- USBWacomState *s = (USBWacomState *) dev;
346
+ USBWacomState *s = USB_WACOM(dev);
347
307
- s->dx = 0;
308
- s->dy = 0;
348
+ memset(s->axis, 0, sizeof(s->axis));
349
+ memset(s->btns, 0, sizeof(s->btns));
350
s->dz = 0;
310
- s->x = 0;
311
- s->y = 0;
312
- s->buttons_state = 0;
351
s->mode = WACOM_MODE_HID;
352
+ g_clear_pointer(&s->hs, qemu_input_handler_unregister);
353
}
354
355
static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
@@ -337,10 +376,7 @@ static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p,
376
}
377
break;
378
case WACOM_SET_REPORT:
340
- if (s->mouse_grabbed) {
341
- qemu_remove_mouse_event_handler(s->eh_entry);
342
- s->mouse_grabbed = 0;
343
- }
379
+ g_clear_pointer(&s->hs, qemu_input_handler_unregister);
380
s->mode = data[0];
381
break;
382
case WACOM_GET_REPORT:
@@ -400,10 +436,7 @@ static void usb_wacom_unrealize(USBDevice *dev)
436
{
437
USBWacomState *s = (USBWacomState *) dev;
438
403
- if (s->mouse_grabbed) {
404
- qemu_remove_mouse_event_handler(s->eh_entry);
405
- s->mouse_grabbed = 0;
406
- }
439
+ g_clear_pointer(&s->hs, qemu_input_handler_unregister);
440
}
441
442
static void usb_wacom_realize(USBDevice *dev, Error **errp)