@ -123,6 +123,7 @@ typedef struct {
int mouse_dx ; /* current values, needed for 'poll' mode */
int mouse_dy ;
int mouse_dz ;
int mouse_dw ;
uint8_t mouse_buttons ;
} PS2MouseState ;
@ -715,7 +716,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */
const int needed = s - > mouse_type ? 4 : 3 ;
unsigned int b ;
int dx1 , dy1 , dz1 ;
int dx1 , dy1 , dz1 , dw1 ;
if ( PS2_QUEUE_SIZE - s - > common . queue . count < needed ) {
return 0 ;
@ -724,6 +725,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
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 ;
@ -740,6 +742,9 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* 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 ;
break ;
case 3 :
if ( dz1 > 127 )
@ -747,13 +752,41 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
else if ( dz1 < - 127 )
dz1 = - 127 ;
ps2_queue_noirq ( & s - > common , dz1 & 0xff ) ;
s - > mouse_dz - = dz1 ;
s - > mouse_dw = 0 ;
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 . Note , if you happen to
* press / release the 4 th or 5 th buttons at the same moment as a
* horizontal wheel scroll , those button presses will get lost . I ' m not
* sure what to do about that , since by this point we don ' t know
* whether those buttons actually changed state .
*/
if ( dw1 ! = 0 ) {
if ( dw1 > 31 ) {
dw1 = 31 ;
} else if ( dw1 < - 31 ) {
dw1 = - 31 ;
}
/*
* linux kernel expects first 6 bits to represent the value
* for horizontal scroll
*/
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 ;
}
ps2_queue_noirq ( & s - > common , b ) ;
break ;
}
@ -764,7 +797,6 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
/* update deltas */
s - > mouse_dx - = dx1 ;
s - > mouse_dy - = dy1 ;
s - > mouse_dz - = dz1 ;
return 1 ;
}
@ -806,6 +838,12 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
} else if ( btn - > button = = INPUT_BUTTON_WHEEL_DOWN ) {
s - > mouse_dz + + ;
}
if ( btn - > button = = INPUT_BUTTON_WHEEL_RIGHT ) {
s - > mouse_dw - - ;
} else if ( btn - > button = = INPUT_BUTTON_WHEEL_LEFT ) {
s - > mouse_dw + + ;
}
} else {
s - > mouse_buttons & = ~ bmap [ btn - > button ] ;
}
@ -833,8 +871,10 @@ static void ps2_mouse_sync(DeviceState *dev)
/* if not remote, send event. Multiple events are sent if
too big deltas */
while ( 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 ) {
break ;
}
}
}
}
@ -1036,6 +1076,7 @@ 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 ;
}