mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
Mouse driver improvements; callback between mouse class and GDI
svn path=/trunk/; revision=1917
This commit is contained in:
parent
73b9ac6994
commit
02e9af8bda
8 changed files with 512 additions and 45 deletions
|
@ -29,6 +29,10 @@ typedef struct _CLASS_INFORMATION {
|
|||
PVOID CallBack;
|
||||
} CLASS_INFORMATION, *PCLASS_INFORMATION;
|
||||
|
||||
typedef struct _GDI_INFORMATION {
|
||||
PVOID CallBack;
|
||||
} GDI_INFORMATION, *PGDI_INFORMATION;
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*PSERVICE_CALLBACK_ROUTINE) (
|
||||
|
@ -37,3 +41,10 @@ VOID
|
|||
IN PVOID SystemArgument2,
|
||||
IN OUT PVOID SystemArgument3
|
||||
);
|
||||
|
||||
typedef
|
||||
VOID
|
||||
(*PGDI_SERVICE_CALLBACK_ROUTINE) (
|
||||
IN PVOID SystemArgument1,
|
||||
IN ULONG SystemArgument2
|
||||
);
|
||||
|
|
|
@ -25,7 +25,11 @@ VOID MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA Mous
|
|||
ULONG ReadSize;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
if(ClassDeviceExtension->ReadIsPending == TRUE)
|
||||
// In classical NT, you would take the input data and pipe it through the IO system, for the GDI to read.
|
||||
// In ReactOS, however, we use a GDI callback for increased mouse responsiveness. The reason we don't
|
||||
// simply call from the port driver is so that our mouse class driver can support NT mouse port drivers.
|
||||
|
||||
/* if(ClassDeviceExtension->ReadIsPending == TRUE)
|
||||
{
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
|
@ -44,8 +48,8 @@ VOID MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA Mous
|
|||
IoStartNextPacket(ClassDeviceObject, FALSE);
|
||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
}
|
||||
if(InputCount>0)
|
||||
} */
|
||||
if(*InputCount>0)
|
||||
{
|
||||
// FIXME: If we exceed the buffer, mouse data gets thrown away.. better solution?
|
||||
|
||||
|
@ -63,7 +67,16 @@ VOID MouseClassCallBack(PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA Mous
|
|||
// Move the pointer and counter up
|
||||
ClassDeviceExtension->PortData += ReadSize;
|
||||
ClassDeviceExtension->InputCount += ReadSize;
|
||||
}
|
||||
|
||||
// Throw data up to GDI callback
|
||||
if(*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack != NULL) {
|
||||
(*(PGDI_SERVICE_CALLBACK_ROUTINE)ClassDeviceExtension->GDIInformation.CallBack)
|
||||
(ClassDeviceExtension->PortData - ReadSize, ReadSize);
|
||||
ClassDeviceExtension->PortData -= ReadSize;
|
||||
ClassDeviceExtension->InputCount -= ReadSize;
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
|
||||
|
@ -78,6 +91,8 @@ NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
|
|||
CLASS_INFORMATION ClassInformation;
|
||||
PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
|
||||
DeviceExtension->GDIInformation.CallBack = NULL;
|
||||
|
||||
// Get the port driver's DeviceObject
|
||||
// FIXME: The name might change.. find a way to be more dynamic?
|
||||
|
||||
|
@ -197,6 +212,47 @@ VOID MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
}
|
||||
|
||||
NTSTATUS MouseClassInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
// Retrieve GDI's callback
|
||||
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS status;
|
||||
|
||||
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
|
||||
DeviceExtension->GDIInformation =
|
||||
*((PGDI_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IOCTL_INTERNAL_MOUSE_DISCONNECT:
|
||||
|
||||
DeviceExtension->GDIInformation.CallBack = NULL;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
if (status == STATUS_PENDING) {
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
} else {
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
|
@ -207,9 +263,10 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|||
DbgPrint("Mouse Class Driver 0.0.1\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch;
|
||||
DriverObject->DriverStartIo = MouseClassStartIo;
|
||||
// DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch;
|
||||
// DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = MouseClassInternalDeviceControl; // to get GDI callback
|
||||
// DriverObject->DriverStartIo = MouseClassStartIo;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\MouseClass");
|
||||
IoCreateDevice(DriverObject,
|
||||
|
|
|
@ -3,4 +3,5 @@ typedef struct _DEVICE_EXTENSION {
|
|||
ULONG InputCount;
|
||||
PMOUSE_INPUT_DATA PortData;
|
||||
PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject)
|
||||
GDI_INFORMATION GDIInformation;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
|
|
@ -59,18 +59,21 @@ unsigned handle_event(void)
|
|||
void controller_wait(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
LARGE_INTEGER Millisecond_Timeout;
|
||||
|
||||
Millisecond_Timeout.QuadPart = 1;
|
||||
|
||||
for(timeout = 0; timeout < CONTROLLER_TIMEOUT; timeout++)
|
||||
{
|
||||
// "handle_keyboard_event()" will handle any incoming events
|
||||
// while we wait -- keypresses or mouse movement
|
||||
|
||||
|
||||
unsigned char status = handle_event();
|
||||
|
||||
if((status & CONTROLLER_STATUS_INPUT_BUFFER_FULL) == 0) return;
|
||||
|
||||
// Sleep for one millisecond
|
||||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
KeDelayExecutionThread (KernelMode, FALSE, &Millisecond_Timeout);
|
||||
}
|
||||
|
||||
DbgPrint("PSAUX: Keyboard timed out\n");
|
||||
|
@ -92,6 +95,7 @@ int controller_wait_for_input(void)
|
|||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
}
|
||||
|
||||
DbgPrint("PSAUX: Timed out on waiting for input from controller\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -111,7 +115,6 @@ void controller_write_output_word(unsigned data)
|
|||
controller_write_output(data);
|
||||
}
|
||||
|
||||
|
||||
/* Empty the keyboard input buffer. */
|
||||
|
||||
void keyboard_clear_input(void)
|
||||
|
|
|
@ -89,7 +89,7 @@ BOOLEAN ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|||
mouse_buffer[2]);
|
||||
}
|
||||
|
||||
if (((state_dx!=0) || (state_dy!=0) /* || (state_buttons!=0) */ ))
|
||||
if (((state_dx!=0) || (state_dy!=0) || (state_buttons!=0)))
|
||||
{
|
||||
// FIXME: Implement button state, see /include/ntddmous.h
|
||||
|
||||
|
@ -101,6 +101,8 @@ BOOLEAN ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].RawButtons = state_buttons;
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].ButtonData = state_buttons;
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastX = state_dx;
|
||||
DeviceExtension->MouseInputData[DeviceExtension->InputDataCount].LastY = state_dy;
|
||||
DeviceExtension->InputDataCount++;
|
||||
|
@ -116,9 +118,9 @@ BOOLEAN ps2_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
|||
|
||||
static void mouse_write_command (int command)
|
||||
{
|
||||
controller_wait ();
|
||||
controller_wait();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MODE);
|
||||
controller_wait ();
|
||||
controller_wait();
|
||||
controller_write_output (command);
|
||||
}
|
||||
|
||||
|
@ -126,9 +128,9 @@ static void mouse_write_command (int command)
|
|||
|
||||
static void mouse_write_ack (int value)
|
||||
{
|
||||
controller_wait ();
|
||||
controller_wait();
|
||||
controller_write_command (CONTROLLER_COMMAND_WRITE_MOUSE);
|
||||
controller_wait ();
|
||||
controller_wait();
|
||||
controller_write_output (value);
|
||||
|
||||
/* We expect an ACK in response. */
|
||||
|
@ -144,7 +146,7 @@ BOOLEAN detect_ps2_port(void)
|
|||
int loops;
|
||||
BOOLEAN return_value = FALSE;
|
||||
|
||||
return TRUE; // The rest of this code fails under BOCHs
|
||||
return TRUE; // The rest of this code fails under BOCHs
|
||||
|
||||
/* Put the value 0x5A in the output buffer using the "WriteAuxiliary Device Output Buffer" command (0xD3).
|
||||
Poll the Status Register for a while to see if the value really turns up in the Data Register. If the
|
||||
|
@ -182,17 +184,18 @@ BOOLEAN detect_ps2_port(void)
|
|||
|
||||
BOOLEAN mouse_init (PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
if (!detect_ps2_port ()) return FALSE;
|
||||
|
||||
has_mouse = TRUE;
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE);
|
||||
|
||||
if (!detect_ps2_port ()) return FALSE;
|
||||
has_mouse = TRUE;
|
||||
|
||||
// Enable the PS/2 mouse port
|
||||
controller_write_command_word (CONTROLLER_COMMAND_MOUSE_ENABLE);
|
||||
|
||||
|
|
|
@ -93,19 +93,15 @@ NTSTATUS PS2MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
|
||||
VOID PS2MouseInitializeDataQueue(PVOID Context)
|
||||
{
|
||||
/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)((PGET_DATA_POINTER_CONTEXT)Context)->DeviceExtension;
|
||||
;
|
||||
/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension;
|
||||
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->DataIn = DeviceExtension->DataIn;
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->DataOut = DeviceExtension->DataOut;
|
||||
((PGET_DATA_POINTER_CONTEXT)Context)->InputCount = DeviceExtension->InputCount; */
|
||||
|
||||
DbgPrint("PS2MouseInitializeDataQueue UNIMPLEMENTED\n");
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */
|
||||
}
|
||||
|
||||
NTSTATUS PS2MouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
// Refer to \readableMouseDriver\port\sermcmn.c line 54
|
||||
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS status;
|
||||
|
@ -161,12 +157,17 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|||
UNICODE_STRING SymlinkName;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DbgPrint("PS/2 Keyboard & Mouse Driver 0.0.1\n");
|
||||
DbgPrint("PS/2 Keyboard & Mouse Driver 0.0.2\n");
|
||||
|
||||
if(detect_ps2_port() == TRUE)
|
||||
{
|
||||
DbgPrint("PS/2 Mouse Detected\n");
|
||||
} else
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
|
||||
|
||||
DriverObject->DriverStartIo = PS2MouseStartIo;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\Mouse"); // FIXME: find correct device name
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
# $Id: makefile,v 1.3 2001/05/26 08:19:03 jfilby Exp $
|
||||
#
|
||||
#
|
||||
#
|
||||
TARGET = sermouse
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
TARGET=mouse
|
||||
OBJECTS= mouse.o ../../../ntoskrnl/ntoskrnl.a
|
||||
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
all: mouse.o
|
||||
CFLAGS = -O2 -I.
|
||||
|
||||
all: $(TARGET).sys
|
||||
|
||||
.phony: all
|
||||
|
||||
clean:
|
||||
- $(RM) mouse.o
|
||||
- $(RM) $(TARGET).o
|
||||
- $(RM) $(TARGET).coff
|
||||
- $(RM) junk.tmp
|
||||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) mouse.sys
|
||||
- $(RM) sermouse.sys
|
||||
|
||||
.phony: clean
|
||||
|
||||
|
@ -29,16 +33,33 @@ dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
|||
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
|
||||
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
|
||||
|
||||
mouse.sys: $(OBJECTS)
|
||||
$(CC) -specs=../../svc_specs -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
$(TARGET).sys: $(OBJECTS)
|
||||
$(CC) \
|
||||
-specs=../../svc_specs \
|
||||
-mdll \
|
||||
-o junk.tmp \
|
||||
-Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ \
|
||||
-Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp \
|
||||
$(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname mouse.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
$(DLLTOOL) \
|
||||
--dllname $(TARGET).sys \
|
||||
--base-file base.tmp \
|
||||
--output-exp temp.exp \
|
||||
--kill-at
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry@8 \
|
||||
-specs=../../svc_specs -mdll -o mouse.sys $(OBJECTS) -Wl,temp.exp
|
||||
$(CC) \
|
||||
--verbose \
|
||||
-Wl,--image-base,0x10000 \
|
||||
-Wl,-e,_DriverEntry@8 \
|
||||
-Wl,temp.exp \
|
||||
-specs=../../svc_specs \
|
||||
-mdll \
|
||||
-o $(TARGET).sys \
|
||||
$(OBJECTS)
|
||||
- $(RM) temp.exp
|
||||
|
||||
|
||||
include ../../../rules.mak
|
||||
|
|
370
reactos/drivers/input/sermouse/sermouse.c
Normal file
370
reactos/drivers/input/sermouse/sermouse.c
Normal file
|
@ -0,0 +1,370 @@
|
|||
/*
|
||||
|
||||
** Mouse driver 0.0.4
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.sid-dis.com/reactos)
|
||||
|
||||
** Note: The serial.o driver must be loaded before loading this driver
|
||||
|
||||
** Known Limitations:
|
||||
** Only supports mice on COM port 1
|
||||
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include "../include/mouse.h"
|
||||
#include "sermouse.h"
|
||||
|
||||
#define MOUSE_IRQ_COM1 4
|
||||
#define MOUSE_IRQ_COM2 3
|
||||
|
||||
#define COM1_PORT 0x3f8
|
||||
#define COM2_PORT 0x2f8
|
||||
|
||||
#define max_screen_x 79
|
||||
#define max_screen_y 24
|
||||
|
||||
static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1;
|
||||
static unsigned int MOUSE_COM=COM1_PORT;
|
||||
|
||||
static unsigned int bytepos=0, coordinate;
|
||||
static unsigned char mpacket[3];
|
||||
static signed int mouse_x=40, mouse_y=12;
|
||||
static unsigned char mouse_button1, mouse_button2;
|
||||
static signed int horiz_sensitivity, vert_sensitivity;
|
||||
|
||||
BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||
{
|
||||
unsigned int mbyte=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
|
||||
|
||||
// Synchronize
|
||||
if((mbyte&64)==64) { bytepos=0; }
|
||||
|
||||
mpacket[bytepos]=mbyte;
|
||||
bytepos++;
|
||||
|
||||
// Process packet
|
||||
if(bytepos==3) {
|
||||
// Retrieve change in x and y from packet
|
||||
int change_x=((mpacket[0] & 3) << 6) + mpacket[1];
|
||||
int change_y=((mpacket[0] & 12) << 4) + mpacket[2];
|
||||
|
||||
// Some mice need this
|
||||
if(coordinate==1) {
|
||||
change_x-=128;
|
||||
change_y-=128;
|
||||
}
|
||||
|
||||
// Change to signed
|
||||
if(change_x>=128) { change_x=change_x-256; }
|
||||
if(change_y>=128) { change_y=change_y-256; }
|
||||
|
||||
// Adjust mouse position according to sensitivity
|
||||
mouse_x+=change_x/horiz_sensitivity;
|
||||
mouse_y+=change_y/vert_sensitivity;
|
||||
|
||||
// Check that mouse is still in screen
|
||||
if(mouse_x<0) { mouse_x=0; }
|
||||
if(mouse_x>max_screen_x) { mouse_x=max_screen_x; }
|
||||
if(mouse_y<0) { mouse_y=0; }
|
||||
if(mouse_y>max_screen_y) { mouse_y=max_screen_y; }
|
||||
|
||||
// Retrieve mouse button status from packet
|
||||
mouse_button1=mpacket[0] & 32;
|
||||
mouse_button2=mpacket[0] & 16;
|
||||
|
||||
bytepos=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InitializeMouseHardware(unsigned int mtype)
|
||||
{
|
||||
char clear_error_bits;
|
||||
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, 0x80); // set DLAB on
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM, 0x60); // speed LO byte
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // speed HI byte
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 0); // set comm and DLAB to 0
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 1); // DR int enable
|
||||
|
||||
clear_error_bits=READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5); // clear error bits
|
||||
}
|
||||
|
||||
int DetMicrosoft(void)
|
||||
{
|
||||
char tmp, ind;
|
||||
int buttons=0, i, timeout=250;
|
||||
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 0x0b);
|
||||
tmp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
|
||||
|
||||
// Check the first four bytes for signs that this is an MS mouse
|
||||
for(i=0; i<4; i++) {
|
||||
while(((READ_PORT_UCHAR((PUCHAR)MOUSE_COM+5) & 1)==0) && (timeout>0))
|
||||
{
|
||||
KeDelayExecutionThread (KernelMode, FALSE, 1);
|
||||
timeout--;
|
||||
}
|
||||
ind=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
|
||||
if(ind==0x33) buttons=3;
|
||||
if(ind==0x4d) buttons=2;
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
int CheckMouseType(unsigned int mtype)
|
||||
{
|
||||
unsigned int retval=0;
|
||||
|
||||
InitializeMouseHardware(mtype);
|
||||
if(mtype==2) retval=DetMicrosoft();
|
||||
if(mtype==3) {
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+4, 11);
|
||||
retval=3;
|
||||
}
|
||||
WRITE_PORT_UCHAR((PUCHAR)MOUSE_COM+1, 1);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ClearMouse(void)
|
||||
{
|
||||
// Waits until the mouse calms down but also quits out after a while
|
||||
// in case some destructive user wants to keep moving the mouse
|
||||
// before we're done
|
||||
|
||||
unsigned int restarts=0, i;
|
||||
for (i=0; i<60000; i++)
|
||||
{
|
||||
unsigned temp=READ_PORT_UCHAR((PUCHAR)MOUSE_COM);
|
||||
if(temp!=0) {
|
||||
restarts++;
|
||||
if(restarts<300000) {
|
||||
i=0;
|
||||
} else
|
||||
{
|
||||
i=60000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN InitializeMouse(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
int mbuttons=0, gotmouse=0;
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
|
||||
horiz_sensitivity=2;
|
||||
vert_sensitivity=3;
|
||||
|
||||
// Check for Microsoft mouse (2 buttons)
|
||||
if(CheckMouseType(2)!=0)
|
||||
{
|
||||
gotmouse=1;
|
||||
DbgPrint("Microsoft Mouse Detected\n");
|
||||
ClearMouse();
|
||||
coordinate=0;
|
||||
}
|
||||
|
||||
// Check for Microsoft Systems mouse (3 buttons)
|
||||
if(gotmouse==0) {
|
||||
if(CheckMouseType(3)!=0)
|
||||
{
|
||||
gotmouse=1;
|
||||
DbgPrint("Microsoft Mouse Detected\n");
|
||||
ClearMouse();
|
||||
coordinate=1;
|
||||
}
|
||||
}
|
||||
|
||||
if(gotmouse==0) return FALSE;
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE);
|
||||
|
||||
MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ,
|
||||
&Dirql, &Affinity);
|
||||
|
||||
IoConnectInterrupt(&DeviceExtension->MouseInterrupt, microsoft_mouse_handler, NULL,
|
||||
NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
|
||||
Affinity, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID SerialMouseInitializeDataQueue(PVOID Context)
|
||||
{
|
||||
;
|
||||
/* PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceExtension;
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
DeviceExtension->MouseInputData = ExAllocatePool(NonPagedPool, sizeof(MOUSE_INPUT_DATA) * MOUSE_BUFFER_SIZE); */
|
||||
}
|
||||
|
||||
BOOLEAN MouseSynchronizeRoutine(PVOID Context)
|
||||
{
|
||||
PIRP Irp = (PIRP)Context;
|
||||
PMOUSE_INPUT_DATA rec = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
int i;
|
||||
|
||||
if ((stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA))==NrToRead)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
MouseDataRequired=stk->Parameters.Read.Length/sizeof(MOUSE_INPUT_DATA);
|
||||
MouseDataRead=NrToRead;
|
||||
CurrentIrp=Irp;
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
VOID SerialMouseStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
if (KeSynchronizeExecution(DeviceExtension->MouseInterrupt, MouseSynchronizeRoutine, Irp))
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS SerialMouseInternalDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS status;
|
||||
|
||||
switch(Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_INTERNAL_MOUSE_CONNECT:
|
||||
|
||||
DeviceExtension->ClassInformation =
|
||||
*((PCLASS_INFORMATION)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
|
||||
|
||||
// Reinitialize the port input data queue synchronously
|
||||
KeSynchronizeExecution(DeviceExtension->MouseInterrupt,
|
||||
(PKSYNCHRONIZE_ROUTINE)SerialMouseInitializeDataQueue, DeviceExtension);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
if (status == STATUS_PENDING) {
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
} else {
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS SerialMouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
NTSTATUS Status;
|
||||
|
||||
switch (stk->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
if (AlreadyOpened == TRUE)
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_SUCCESS;
|
||||
AlreadyOpened = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgPrint("NOT IMPLEMENTED\n");
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Status==STATUS_PENDING)
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
}
|
||||
return(Status);
|
||||
}
|
||||
|
||||
VOID SerialMouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ClassInformation.CallBack)(
|
||||
DeviceExtension->ClassInformation.DeviceObject,
|
||||
DeviceExtension->MouseInputData,
|
||||
NULL,
|
||||
&DeviceExtension->InputDataCount);
|
||||
|
||||
DeviceExtension->InputDataCount = 0;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING SymlinkName;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DbgPrint("Serial Mouse Driver 0.0.4\n");
|
||||
|
||||
if(InitializeMouse(DeviceObject) == FALSE)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialMouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialMouseDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SerialMouseInternalDeviceControl;
|
||||
DriverObject->DriverStartIo = SerialMouseStartIo;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\Mouse"); // FIXME: find correct device name
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
&DeviceName,
|
||||
FILE_DEVICE_SERIAL_MOUSE_PORT,
|
||||
0,
|
||||
TRUE,
|
||||
&DeviceObject);
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
|
||||
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\??\\Mouse"); // FIXME: find correct device name
|
||||
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
|
||||
KeInitializeDpc(&DeviceExtension->IsrDpcRetry, (PKDEFERRED_ROUTINE)SerialMouseIsrDpc, DeviceObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
Loading…
Reference in a new issue