Have the emulated mouse report horizontal wheel events when in exps/2 mode.
Signed-off-by: Brad Jorsch <ano...@users.sourceforge.net> --- hw/ps2.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 43 insertions(+), 13 deletions(-) diff --git a/hw/ps2.c b/hw/ps2.c index db5605d..09e4365 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -105,7 +105,9 @@ typedef struct { int mouse_dx; /* current values, needed for 'poll' mode */ int mouse_dy; int mouse_dz; + int mouse_dw; uint8_t mouse_buttons; + uint8_t mouse_buttons_changed; } PS2MouseState; /* Table to convert from PC scancodes to raw scancodes. */ @@ -284,11 +286,12 @@ void ps2_keyboard_set_translation(void *opaque, int mode) static void ps2_mouse_send_packet(PS2MouseState *s) { unsigned int b; - int dx1, dy1, dz1; + int dx1, dy1, dz1, dw1; dx1 = s->mouse_dx; dy1 = s->mouse_dy; dz1 = s->mouse_dz; + dw1 = s->mouse_dw; /* XXX: increase range to 8 bits ? */ if (dx1 > 127) dx1 = 127; @@ -299,12 +302,17 @@ static void ps2_mouse_send_packet(PS2MouseState *s) else if (dy1 < -127) dy1 = -127; b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); + s->mouse_buttons_changed &= ~0x07; ps2_queue(&s->common, b); ps2_queue(&s->common, dx1 & 0xff); ps2_queue(&s->common, dy1 & 0xff); /* extra byte for IMPS/2 or IMEX */ switch(s->mouse_type) { default: + /* Just ignore the wheels if not supported */ + s->mouse_dz = 0; + s->mouse_dw = 0; + s->mouse_buttons_changed &= 0x07; break; case 3: if (dz1 > 127) @@ -312,13 +320,29 @@ static void ps2_mouse_send_packet(PS2MouseState *s) else if (dz1 < -127) dz1 = -127; ps2_queue(&s->common, dz1 & 0xff); + s->mouse_dz -= dz1; + s->mouse_dw = 0; + s->mouse_buttons_changed &= 0x07; break; case 4: - if (dz1 > 7) - dz1 = 7; - else if (dz1 < -7) - dz1 = -7; - b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); + /* This matches what the Linux kernel expects for exps/2 in + * drivers/input/mouse/psmouse-base.c. */ + if (dw1 != 0) { + if (dw1 > 31) + dw1 = 31; + else if (dw1 < -31) + dw1 = -31; + b = (dw1 & 0x3f) | 0x40; + s->mouse_dw -= dw1; + } else { + if (dz1 > 7) + dz1 = 7; + else if (dz1 < -7) + dz1 = -7; + b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); + s->mouse_dz -= dz1; + s->mouse_buttons_changed &= 0x07; + } ps2_queue(&s->common, b); break; } @@ -326,7 +350,6 @@ static void ps2_mouse_send_packet(PS2MouseState *s) /* update deltas */ s->mouse_dx -= dx1; s->mouse_dy -= dy1; - s->mouse_dz -= dz1; } static void ps2_mouse_event(void *opaque, @@ -341,11 +364,13 @@ static void ps2_mouse_event(void *opaque, s->mouse_dx += dx; s->mouse_dy -= dy; s->mouse_dz += dz; + s->mouse_dw -= dw; + s->mouse_buttons_changed |= s->mouse_buttons ^ buttons_state; + s->mouse_buttons = buttons_state; /* XXX: SDL sometimes generates nul events: we delete them */ if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && - s->mouse_buttons == buttons_state) + s->mouse_dw == 0 && s->mouse_buttons_changed == 0) return; - s->mouse_buttons = buttons_state; if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) { @@ -353,7 +378,8 @@ static void ps2_mouse_event(void *opaque, /* if not remote, send event. Multiple events are sent if too big deltas */ ps2_mouse_send_packet(s); - if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) + if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && + s->mouse_dw == 0 && s->mouse_buttons_changed == 0) break; } } @@ -525,7 +551,9 @@ static void ps2_mouse_reset(void *opaque) s->mouse_dx = 0; s->mouse_dy = 0; s->mouse_dz = 0; + s->mouse_dw = 0; s->mouse_buttons = 0; + s->mouse_buttons_changed = 0; } static const VMStateDescription vmstate_ps2_common = { @@ -569,9 +597,9 @@ static const VMStateDescription vmstate_ps2_keyboard = { static const VMStateDescription vmstate_ps2_mouse = { .name = "ps2mouse", - .version_id = 2, - .minimum_version_id = 2, - .minimum_version_id_old = 2, + .version_id = 3, + .minimum_version_id = 3, + .minimum_version_id_old = 3, .fields = (VMStateField []) { VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), VMSTATE_UINT8(mouse_status, PS2MouseState), @@ -583,7 +611,9 @@ static const VMStateDescription vmstate_ps2_mouse = { VMSTATE_INT32(mouse_dx, PS2MouseState), VMSTATE_INT32(mouse_dy, PS2MouseState), VMSTATE_INT32(mouse_dz, PS2MouseState), + VMSTATE_INT32(mouse_dw, PS2MouseState), VMSTATE_UINT8(mouse_buttons, PS2MouseState), + VMSTATE_UINT8(mouse_buttons_changed, PS2MouseState), VMSTATE_END_OF_LIST() } }; -- 1.7.1