@samitouri / QOSamiQemu / commits / 6664746920

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)