This still, but less frequently, shows the behavior of having the cursor leap downwards occasionally. I may not be able to work on debugging it until next week, but I'll try to see if I can figure it out sooner. The hypothesis with the old code was that it was sending floods of mouse messages and the Sun driver was dropping a byte at some point. So that's the first thing I'll look into with this new code, but it could be something different. This is definitely better than the old code -- just not sending anything in response to mouse wheel movement helps a lot.
On Mon, Sep 2, 2024 at 2:38 PM Mark Cave-Ayland < mark.cave-ayl...@ilande.co.uk> wrote: > Update the Sun mouse implementation to use QemuInputHandler instead of the > legacy qemu_add_mouse_event_handler() function. > > Note that this conversion adds extra sunmouse_* members to ESCCChannelState > but they are not added to the migration stream (similar to the Sun keyboard > members). If this were desired in future, the Sun devices should be split > into separate devices and added to the migration stream there instead. > > Signed-off-by: Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2518 > --- > hw/char/escc.c | 79 ++++++++++++++++++++++++++++++------------ > include/hw/char/escc.h | 3 ++ > roms/seabios | 2 +- > 3 files changed, 60 insertions(+), 24 deletions(-) > > diff --git a/hw/char/escc.c b/hw/char/escc.c > index d450d70eda..6d4e3e3350 100644 > --- a/hw/char/escc.c > +++ b/hw/char/escc.c > @@ -287,6 +287,7 @@ static void escc_reset_chn(ESCCChannelState *s) > s->rxint = s->txint = 0; > s->rxint_under_svc = s->txint_under_svc = 0; > s->e0_mode = s->led_mode = s->caps_lock_mode = s->num_lock_mode = 0; > + s->sunmouse_dx = s->sunmouse_dy = s->sunmouse_buttons = 0; > clear_queue(s); > } > > @@ -952,53 +953,85 @@ static void handle_kbd_command(ESCCChannelState *s, > int val) > } > } > > -static void sunmouse_event(void *opaque, > - int dx, int dy, int dz, int buttons_state) > +static void sunmouse_handle_event(DeviceState *dev, QemuConsole *src, > + InputEvent *evt) > { > - ESCCChannelState *s = opaque; > - int ch; > + ESCCChannelState *s = (ESCCChannelState *)dev; > + InputMoveEvent *move; > + InputBtnEvent *btn; > + static const int bmap[INPUT_BUTTON__MAX] = { > + [INPUT_BUTTON_LEFT] = 0x4, > + [INPUT_BUTTON_MIDDLE] = 0x2, > + [INPUT_BUTTON_RIGHT] = 0x1, > + [INPUT_BUTTON_SIDE] = 0x0, > + [INPUT_BUTTON_EXTRA] = 0x0, > + }; > + > + switch (evt->type) { > + case INPUT_EVENT_KIND_REL: > + move = evt->u.rel.data; > + if (move->axis == INPUT_AXIS_X) { > + s->sunmouse_dx += move->value; > + } else if (move->axis == INPUT_AXIS_Y) { > + s->sunmouse_dy -= move->value; > + } > + break; > > - trace_escc_sunmouse_event(dx, dy, buttons_state); > - ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */ > + case INPUT_EVENT_KIND_BTN: > + btn = evt->u.btn.data; > + if (btn->down) { > + s->sunmouse_buttons |= bmap[btn->button]; > + } else { > + s->sunmouse_buttons &= ~bmap[btn->button]; > + } > + break; > > - if (buttons_state & MOUSE_EVENT_LBUTTON) { > - ch ^= 0x4; > - } > - if (buttons_state & MOUSE_EVENT_MBUTTON) { > - ch ^= 0x2; > - } > - if (buttons_state & MOUSE_EVENT_RBUTTON) { > - ch ^= 0x1; > + default: > + /* keep gcc happy */ > + break; > } > +} > > - put_queue(s, ch); > +static void sunmouse_sync(DeviceState *dev) > +{ > + ESCCChannelState *s = (ESCCChannelState *)dev; > + int ch; > > - ch = dx; > + trace_escc_sunmouse_event(s->sunmouse_dx, s->sunmouse_dy, 0); > + ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */ > + ch ^= s->sunmouse_buttons; > + put_queue(s, ch); > > + ch = s->sunmouse_dx; > if (ch > 127) { > ch = 127; > } else if (ch < -127) { > ch = -127; > } > - > put_queue(s, ch & 0xff); > + s->sunmouse_dx = 0; > > - ch = -dy; > - > + ch = s->sunmouse_dy; > if (ch > 127) { > ch = 127; > } else if (ch < -127) { > ch = -127; > } > - > put_queue(s, ch & 0xff); > + s->sunmouse_dy = 0; > > /* MSC protocol specifies two extra motion bytes */ > - > put_queue(s, 0); > put_queue(s, 0); > } > > +static const QemuInputHandler sunmouse_handler = { > + .name = "QEMU Sun Mouse", > + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, > + .event = sunmouse_handle_event, > + .sync = sunmouse_sync, > +}; > + > static void escc_init1(Object *obj) > { > ESCCState *s = ESCC(obj); > @@ -1036,8 +1069,8 @@ static void escc_realize(DeviceState *dev, Error > **errp) > } > > if (s->chn[0].type == escc_mouse) { > - qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, > - "QEMU Sun Mouse"); > + s->chn[0].hs = qemu_input_handler_register((DeviceState > *)(&s->chn[0]), > + &sunmouse_handler); > } > if (s->chn[1].type == escc_kbd) { > s->chn[1].hs = qemu_input_handler_register((DeviceState > *)(&s->chn[1]), > diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h > index 5669a5b811..8c4c6a7730 100644 > --- a/include/hw/char/escc.h > +++ b/include/hw/char/escc.h > @@ -46,6 +46,9 @@ typedef struct ESCCChannelState { > uint8_t rx, tx; > QemuInputHandlerState *hs; > char *sunkbd_layout; > + int sunmouse_dx; > + int sunmouse_dy; > + int sunmouse_buttons; > } ESCCChannelState; > > struct ESCCState { > diff --git a/roms/seabios b/roms/seabios > index a6ed6b701f..7d0c606870 160000 > --- a/roms/seabios > +++ b/roms/seabios > @@ -1 +1 @@ > -Subproject commit a6ed6b701f0a57db0569ab98b0661c12a6ec3ff8 > +Subproject commit 7d0c6068703eae9f2498be0c900ab95b25b4f07a > -- > 2.39.2 > > >