@@ -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()
}
};
Have the emulated mouse report horizontal wheel events when in exps/2 mode. Signed-off-by: Brad Jorsch <anomie@users.sourceforge.net> --- hw/ps2.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 43 insertions(+), 13 deletions(-)