Improved mouse button handling

svn path=/trunk/; revision=4266
This commit is contained in:
Jason Filby 2003-03-09 15:00:51 +00:00
parent 098af174b6
commit 975ce25154
7 changed files with 229 additions and 192 deletions

View file

@ -12,7 +12,7 @@
*/
#include <ddk/ntddk.h>
#include "../include/mouse.h"
#include <ddk/ntddmou.h>
#include "mouclass.h"
#define NDEBUG

View file

@ -1,18 +1,21 @@
#include <ddk/ntddk.h>
#include "../include/mouse.h"
#include <ddk/ntddmou.h>
#include "controller.h"
#include "mouse.h"
#include "psaux.h"
// Have we got a PS/2 mouse port?
BOOLEAN has_mouse = FALSE;
static BOOLEAN has_mouse = FALSE;
// This buffer holds the mouse scan codes. The PS/2 protocol sends three characters for each event.
unsigned mouse_buffer[3];
int mouse_buffer_position = 0;
static unsigned mouse_buffer[3];
static int mouse_buffer_position = 0;
// The number of mouse replies expected
int mouse_replies_expected = 0;
static int mouse_replies_expected = 0;
// Previous button state
static ULONG PreviousButtons = 0;
// Handle a mouse event
@ -21,112 +24,138 @@ ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
{
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
int state_dx, state_dy, state_buttons;
PMOUSE_INPUT_DATA Input;
ULONG Queue, ButtonsDiff;
int state_dx, state_dy;
unsigned scancode;
unsigned status = controller_read_status();
scancode = controller_read_input();
/*
* Don't handle the mouse event if we aren't connected to the mouse class
* driver
*/
if (DeviceExtension->ClassInformation.CallBack == NULL)
{
return FALSE;
}
/* Don't handle the mouse event if we aren't connected to the mouse class driver */
if (DeviceExtension->ClassInformation.CallBack == NULL)
{
return FALSE;
}
if ((status & CONTROLLER_STATUS_MOUSE_OUTPUT_BUFFER_FULL) != 0)
{
// mouse_handle_event(scancode); proceed to handle it
}
{
// mouse_handle_event(scancode); proceed to handle it
}
else
{
return FALSE; // keyboard_handle_event(scancode);
}
if (mouse_replies_expected > 0)
{
if (scancode == MOUSE_ACK)
{
return FALSE; // keyboard_handle_event(scancode);
mouse_replies_expected--;
return;
}
if (mouse_replies_expected > 0)
{
if (scancode == MOUSE_ACK)
{
mouse_replies_expected--;
return;
}
mouse_replies_expected = 0;
}
mouse_replies_expected = 0;
}
/* Add this scancode to the mouse event queue. */
mouse_buffer[mouse_buffer_position] = scancode;
mouse_buffer_position++;
/* If the buffer is full, parse this event */
if (mouse_buffer_position == 3)
{
/* Set local variables for DeviceObject and DeviceExtension */
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Queue = DeviceExtension->ActiveQueue % 2;
/* Prevent buffer overflow */
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
{
mouse_buffer_position = 0;
return TRUE;
}
state_buttons = (mouse_buffer[0] & 1) * GPM_B_LEFT +
(mouse_buffer[0] & 2) * GPM_B_RIGHT +
(mouse_buffer[0] & 4) * GPM_B_MIDDLE;
/*
* Some PS/2 mice send reports with negative bit set in data[0] and zero
* for movement. I think this is a bug in the mouse, but working around
* it only causes artifacts when the actual report is -256; they'll
* be treated as zero. This should be rare if the mouse sampling rate is
* set to a reasonable value; the default of 100 Hz is plenty.
* (Stephen Tell)
*/
if (mouse_buffer[1] == 0)
{
state_dx = 0;
}
else
{
state_dx = (mouse_buffer[0] & 0x10) ?
mouse_buffer[1] - 256 :
mouse_buffer[1];
}
if (mouse_buffer[2] == 0)
{
state_dy = 0;
}
else
{
state_dy = -((mouse_buffer[0] & 0x20) ?
mouse_buffer[2] - 256 :
mouse_buffer[2]);
}
if (((state_dx!=0) || (state_dy!=0) || (state_buttons!=0)))
{
ULONG Queue;
PMOUSE_INPUT_DATA Input;
Input = &DeviceExtension->MouseInputData[Queue]
[DeviceExtension->InputDataCount[Queue]];
/* FIXME: Implement button state, see /include/ntddmous.h */
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
Queue = DeviceExtension->ActiveQueue % 2;
if (DeviceExtension->InputDataCount[Queue] == MOUSE_BUFFER_SIZE)
{
return TRUE;
}
mouse_buffer_position = 0;
Input = &DeviceExtension->MouseInputData[Queue]
[DeviceExtension->InputDataCount[Queue]];
Input->RawButtons = state_buttons;
Input->ButtonData = state_buttons;
Input->LastX = state_dx;
Input->LastY = state_dy;
DeviceExtension->InputDataCount[Queue]++;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp,
NULL);
return TRUE;
/* Determine the current state of the buttons */
Input->RawButtons = (mouse_buffer[0] & 1) * GPM_B_LEFT +
(mouse_buffer[0] & 2) * GPM_B_RIGHT +
(mouse_buffer[0] & 4) * GPM_B_MIDDLE;
/* Determine ButtonFlags */
Input->ButtonFlags = 0;
ButtonsDiff = PreviousButtons ^ Input->RawButtons;
if (ButtonsDiff & GPM_B_LEFT)
{
if (Input->RawButtons & GPM_B_LEFT)
{
Input->ButtonFlags |= MOUSE_BUTTON_1_DOWN;
} else {
Input->ButtonFlags |= MOUSE_BUTTON_1_UP;
}
}
}
if (ButtonsDiff & GPM_B_RIGHT)
{
if (Input->RawButtons & GPM_B_RIGHT)
{
Input->ButtonFlags |= MOUSE_BUTTON_2_DOWN;
} else {
Input->ButtonFlags |= MOUSE_BUTTON_2_UP;
}
}
if (ButtonsDiff & GPM_B_MIDDLE)
{
if (Input->RawButtons & GPM_B_MIDDLE)
{
Input->ButtonFlags |= MOUSE_BUTTON_3_DOWN;
} else {
Input->ButtonFlags |= MOUSE_BUTTON_3_UP;
}
}
/* Some PS/2 mice send reports with negative bit set in data[0] and zero for
* movement. I think this is a bug in the mouse, but working around it only
* causes artifacts when the actual report is -256; they'll be treated as zero.
* This should be rare if the mouse sampling rate is set to a reasonable value;
* the default of 100 Hz is plenty. (Stephen Tell) */
/* Determine LastX */
if (mouse_buffer[1] == 0)
{
Input->LastX = 0;
}
else
{
Input->LastX = (mouse_buffer[0] & 0x10) ? mouse_buffer[1] - 256
: mouse_buffer[1];
}
/* Determine LastY */
if (mouse_buffer[2] == 0)
{
Input->LastY = 0;
}
else
{
Input->LastY = -((mouse_buffer[0] & 0x20) ? mouse_buffer[2] - 256
: mouse_buffer[2]);
}
/* Send the Input data to the Mouse Class driver */
DeviceExtension->InputDataCount[Queue]++;
KeInsertQueueDpc(&DeviceExtension->IsrDpc, DeviceObject->CurrentIrp, NULL);
/* Copy RawButtons to Previous Buttons for Input */
PreviousButtons = Input->RawButtons;
return TRUE;
}
}
/* Write a PS/2 mouse command. */

View file

@ -1,47 +1,19 @@
// All or parts of this file are from CHAOS (http://www.se.chaosdev.org/).
// CHAOS is also under the GNU General Public License.
/* Mouse commands. */
/* Set resolution. */
#define MOUSE_SET_RESOLUTION 0xE8
/* Set 1:1 scaling. */
#define MOUSE_SET_SCALE11 0xE6
/* Set 2:1 scaling. */
#define MOUSE_SET_SCALE21 0xE7
/* Get scaling factor. */
#define MOUSE_GET_SCALE 0xE9
/* Set stream mode. */
#define MOUSE_SET_STREAM 0xEA
/* Set sample rate (number of times the controller will poll the port
per second). */
#define MOUSE_SET_SAMPLE_RATE 0xF3
/* Enable mouse device. */
#define MOUSE_ENABLE_DEVICE 0xF4
/* Disable mouse device. */
#define MOUSE_DISABLE_DEVICE 0xF5
/* Reset aux device. */
#define MOUSE_RESET 0xFF
/* Command byte ACK. */
#define MOUSE_ACK 0xFA
// Mouse commands
#define MOUSE_SET_RESOLUTION 0xE8 // Set resolution
#define MOUSE_SET_SCALE11 0xE6 // Set 1:1 scaling
#define MOUSE_SET_SCALE21 0xE7 // Set 2:1 scaling
#define MOUSE_GET_SCALE 0xE9 // Get scaling factor
#define MOUSE_SET_STREAM 0xEA // Set stream mode
#define MOUSE_SET_SAMPLE_RATE 0xF3 /* Set sample rate (number of times
* the controller will poll the port
* per second */
#define MOUSE_ENABLE_DEVICE 0xF4 // Enable mouse device
#define MOUSE_DISABLE_DEVICE 0xF5 // Disable mouse device
#define MOUSE_RESET 0xFF // Reset aux device
#define MOUSE_ACK 0xFA // Command byte ACK
#define MOUSE_INTERRUPTS_OFF (CONTROLLER_MODE_KCC | \
CONTROLLER_MODE_DISABLE_MOUSE | \
@ -53,18 +25,15 @@
CONTROLLER_MODE_MOUSE_INTERRUPT | \
CONTROLLER_MODE_KEYBOARD_INTERRUPT)
/* Used with mouse buttons */
// Used with mouse buttons
#define GPM_B_LEFT 4
#define GPM_B_MIDDLE 2
#define GPM_B_RIGHT 1
/* Some aux operations take long time. */
// Some aux operations take long time
#define MAX_RETRIES 60
/* Hardware defines. */
// Hardware defines
#define MOUSE_IRQ 12
#define MOUSE_WRAP_MASK 0x1F
@ -78,3 +47,4 @@ static VOID MouseDpcRoutine(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2);

View file

@ -1,14 +1,11 @@
/*
** PS/2 driver 0.0.1
** PS/2 driver 0.0.2
** Written by Jason Filby (jasonfilby@yahoo.com)
** For ReactOS (www.reactos.com)
** Handles the keyboard and mouse on the PS/2 ports
** TODO: Fix detect_ps2_port(void) so that it works under BOCHs
Implement mouse button support
*/
#include <ddk/ntddk.h>
@ -159,7 +156,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
PDEVICE_EXTENSION DeviceExtension;
if (detect_ps2_port() == TRUE) {
DbgPrint("PS2 Port Driver version 0.0.1\n");
DbgPrint("PS2 Port Driver version 0.0.2\n");
} else {
DbgPrint("PS2 port not found.\n");
return STATUS_UNSUCCESSFUL;

View file

@ -9,5 +9,6 @@ typedef struct _DEVICE_EXTENSION {
CLASS_INFORMATION ClassInformation;
PKINTERRUPT MouseInterrupt;
KDPC IsrDpc;
KDPC IsrDpc;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

View file

@ -8,6 +8,26 @@
#define IOCTL_INTERNAL_MOUSE_ENABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0200, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_INTERNAL_MOUSE_DISABLE CTL_CODE(FILE_DEVICE_MOUSE, 0x0400, METHOD_NEITHER, FILE_ANY_ACCESS)
#define MOUSE_BUTTON_1_DOWN 0x0001
#define MOUSE_BUTTON_1_UP 0x0002
#define MOUSE_BUTTON_2_DOWN 0x0004
#define MOUSE_BUTTON_2_UP 0x0008
#define MOUSE_BUTTON_3_DOWN 0x0010
#define MOUSE_BUTTON_3_UP 0x0020
#define MOUSE_BUTTON_4_DOWN 0x0040
#define MOUSE_BUTTON_4_UP 0x0080
#define MOUSE_BUTTON_5_DOWN 0x0100
#define MOUSE_BUTTON_5_UP 0x0200
#define MOUSE_WHEEL 0x0400
#define MOUSE_LEFT_BUTTON_DOWN MOUSE_BUTTON_1_DOWN
#define MOUSE_LEFT_BUTTON_UP MOUSE_BUTTON_1_UP
#define MOUSE_RIGHT_BUTTON_DOWN MOUSE_BUTTON_2_DOWN
#define MOUSE_RIGHT_BUTTON_UP MOUSE_BUTTON_2_UP
#define MOUSE_MIDDLE_BUTTON_DOWN MOUSE_BUTTON_3_DOWN
#define MOUSE_MIDDLE_BUTTON_UP MOUSE_BUTTON_3_UP
/* Mouse input data structure */
typedef struct _MOUSE_INPUT_DATA {
USHORT UnitId;
USHORT Flags;
@ -48,3 +68,4 @@ VOID
IN PVOID SystemArgument1,
IN ULONG SystemArgument2
);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mouse.c,v 1.18 2003/03/06 23:57:02 gvg Exp $
/* $Id: mouse.c,v 1.19 2003/03/09 15:00:51 jfilby Exp $
*
* PROJECT: ReactOS kernel
* PURPOSE: Mouse
@ -29,8 +29,8 @@
#include <windows.h>
#include <ddk/ntddk.h>
#include <ddk/ntddmou.h>
#include <win32k/dc.h>
#include "../../drivers/input/include/mouse.h"
#include "objects.h"
#include "include/msgqueue.h"
@ -214,9 +214,9 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
TickCount = LargeTickCount.u.LowPart;
if (hDC == 0)
{
return;
}
{
return;
}
dc = DC_HandleToPtr(hDC);
SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
@ -225,56 +225,75 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
/* Compile the total mouse movement change and dispatch button events. */
for (i = 0; i < InputCount; i++)
{
mouse_cx += Data[i].LastX;
mouse_cy += Data[i].LastY;
Msg.wParam = ButtonsDown;
Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy);
Msg.message = WM_MOUSEMOVE;
Msg.time = TickCount;
Msg.pt.x = mouse_x + mouse_cx;
Msg.pt.y = mouse_y + mouse_cy;
if ((mouse_cx > 0) || (mouse_cy > 0))
{
mouse_cx += Data[i].LastX;
mouse_cy += Data[i].LastY;
Msg.wParam = ButtonsDown;
Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy);
Msg.message = WM_MOUSEMOVE;
Msg.time = TickCount;
Msg.pt.x = mouse_x + mouse_cx;
Msg.pt.y = mouse_y + mouse_cy;
MsqInsertSystemMessage(&Msg);
for (j = 0; j < 3; j++)
{
ULONG Flag = MouseButtonFlag[j];
if (Data[i].ButtonData & (1 << j) && !(ButtonsDown & Flag))
{
ButtonsDown |= Flag;
Msg.wParam = ButtonsDown;
Msg.message = MouseButtonDownMessage[j];
MsqInsertSystemMessage(&Msg);
}
if (!(Data[i].ButtonData & (1 << j)) && (ButtonsDown & Flag))
{
ButtonsDown &= ~Flag;
Msg.wParam = ButtonsDown;
Msg.message = MouseButtonUpMessage[j];
MsqInsertSystemMessage(&Msg);
}
}
}
if (Data[i].ButtonFlags != 0)
{
if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
{
Msg.wParam = MK_LBUTTON;
Msg.message = WM_LBUTTONDOWN;
}
if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
{
Msg.wParam = MK_MBUTTON;
Msg.message = WM_MBUTTONDOWN;
}
if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
{
Msg.wParam = MK_RBUTTON;
Msg.message = WM_RBUTTONDOWN;
}
if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
{
Msg.wParam = MK_LBUTTON;
Msg.message = WM_LBUTTONUP;
}
if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
{
Msg.wParam = MK_MBUTTON;
Msg.message = WM_MBUTTONUP;
}
if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
{
Msg.wParam = MK_RBUTTON;
Msg.message = WM_RBUTTONUP;
}
MsqInsertSystemMessage(&Msg);
}
}
/* If the mouse moved then move the pointer. */
if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
{
mouse_x += mouse_cx;
mouse_y += mouse_cy;
mouse_x = max(mouse_x, 0);
mouse_y = max(mouse_y, 0);
mouse_x = min(mouse_x, 620);
mouse_y = min(mouse_y, 460);
if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
{
mouse_x += mouse_cx;
mouse_y += mouse_cy;
mouse_x = max(mouse_x, 0);
mouse_y = max(mouse_y, 0);
mouse_x = min(mouse_x, 620);
mouse_y = min(mouse_y, 460);
if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
{
SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
}
SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
}
}
}
VOID