Serial mouse driver rewrite by Filip Navara

svn path=/trunk/; revision=5906
This commit is contained in:
Gé van Geldorp 2003-08-28 19:44:00 +00:00
parent d6a2479e6a
commit eee0086bc9
6 changed files with 698 additions and 464 deletions

View file

@ -140,7 +140,7 @@ NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject)
PDEVICE_OBJECT PortDeviceObject = NULL;
PFILE_OBJECT FileObject = NULL;
NTSTATUS status;
UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(L"\\Device\\Mouse");
UNICODE_STRING PortName = UNICODE_STRING_INITIALIZER(L"\\Device\\PointerClass0");
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PIRP irp;

View file

@ -147,6 +147,80 @@ VOID PS2MouseIsrDpc(PKDPC Dpc, PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Cont
DeviceExtension->InputDataCount[Queue] = 0;
}
/* Maximum value plus one for \Device\PointerClass* device name */
#define POINTER_PORTS_MAXIMUM 8
/* Letter count for POINTER_PORTS_MAXIMUM variable * sizeof(WCHAR) */
#define SUFFIX_MAXIMUM_SIZE (1 * sizeof(WCHAR))
/* This is almost the same routine as in sermouse.c. */
STATIC PDEVICE_OBJECT
AllocatePointerDevice(PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName;
UNICODE_STRING SuffixString;
UNICODE_STRING SymlinkName;
PDEVICE_EXTENSION DeviceExtension;
ULONG Suffix;
NTSTATUS Status;
/* Allocate buffer for full device name */
RtlInitUnicodeString(&DeviceName, NULL);
DeviceName.MaximumLength = sizeof(DD_MOUSE_DEVICE_NAME_U) + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
DeviceName.Buffer = ExAllocatePool(PagedPool, DeviceName.MaximumLength);
RtlAppendUnicodeToString(&DeviceName, DD_MOUSE_DEVICE_NAME_U);
/* Allocate buffer for device name suffix */
RtlInitUnicodeString(&SuffixString, NULL);
SuffixString.MaximumLength = SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
SuffixString.Buffer = ExAllocatePool(PagedPool, SuffixString.MaximumLength);
/* Generate full qualified name with suffix */
for (Suffix = 0; Suffix < POINTER_PORTS_MAXIMUM; ++Suffix)
{
ANSI_STRING DebugString;
RtlIntegerToUnicodeString(Suffix, 10, &SuffixString);
RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
// FIXME: this isn't really a serial mouse port driver
Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
&DeviceName, FILE_DEVICE_SERIAL_MOUSE_PORT, 0, TRUE, &DeviceObject);
RtlUnicodeStringToAnsiString(&DebugString, &DeviceName, TRUE);
DbgPrint(DebugString.Buffer);
DbgPrint("\n");
RtlFreeAnsiString(&DebugString);
/* Device successfully created, leave the cyclus */
if (NT_SUCCESS(Status))
break;
DeviceName.Length -= SuffixString.Length;
}
ExFreePool(DeviceName.Buffer);
/* Couldn't create device */
if (!NT_SUCCESS(Status))
{
ExFreePool(SuffixString.Buffer);
return NULL;
}
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
/* Create symlink */
RtlInitUnicodeString(&SymlinkName, NULL);
SymlinkName.MaximumLength = sizeof(L"\\??\\Mouse") + SUFFIX_MAXIMUM_SIZE + sizeof(UNICODE_NULL);
SymlinkName.Buffer = ExAllocatePool(PagedPool, SymlinkName.MaximumLength);
RtlAppendUnicodeToString(&SymlinkName, L"\\??\\Mouse");
RtlAppendUnicodeToString(&DeviceName, SuffixString.Buffer);
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
ExFreePool(SuffixString.Buffer);
DeviceExtension = DeviceObject->DeviceExtension;
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
return DeviceObject;
}
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
@ -162,28 +236,12 @@ DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
return STATUS_UNSUCCESSFUL;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = PS2MouseDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PS2MouseDispatch;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = PS2MouseInternalDeviceControl;
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)PS2MouseDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)PS2MouseDispatch;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)PS2MouseInternalDeviceControl;
DriverObject->DriverStartIo = PS2MouseStartIo;
RtlInitUnicodeStringFromLiteral(&DeviceName,
L"\\Device\\Mouse"); // FIXME: find correct device name
IoCreateDevice(DriverObject,
sizeof(DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_SERIAL_MOUSE_PORT, // FIXME: this isn't really a serial mouse port driver
0,
TRUE,
&DeviceObject);
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
RtlInitUnicodeStringFromLiteral(&SymlinkName,
L"\\??\\Mouse"); // FIXME: find correct device name
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
DeviceExtension = DeviceObject->DeviceExtension;
KeInitializeDpc(&DeviceExtension->IsrDpc, (PKDEFERRED_ROUTINE)PS2MouseIsrDpc, DeviceObject);
DeviceObject = AllocatePointerDevice(DriverObject);
mouse_init(DeviceObject);

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,7 @@ BEGIN
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "Serial Mouse Device Driver\0"
VALUE "FileVersion", "0.0.1\0"
VALUE "FileVersion", "0.0.8\0"
VALUE "InternalName", "sermouse\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "sermouse.sys\0"

View file

@ -0,0 +1,82 @@
Following information obtained from Tomi Engdahl (then@delta.hut.fi),
http://www.hut.fi/~then/mytexts/mouse.html
Microsoft serial mouse
Serial data parameters:
1200bps, 7 databits, 1 stop-bit
Data packet format:
Data packet is 3 byte packet. It is send to the computer every time mouse
state changes (mouse moves or keys are pressed/released).
D7 D6 D5 D4 D3 D2 D1 D0
1. X 1 LB RB Y7 Y6 X7 X6
2. X 0 X5 X4 X3 X2 X1 X0
3. X 0 Y5 Y4 Y3 Y2 Y1 Y0
Note: The bit marked with X is 0 if the mouse received with 7 databits
and 2 stop bits format. It is also possible to use 8 databits and 1 stop
bit format for receiving. In this case X gets value 1. The safest thing
to get everything working is to use 7 databits and 1 stopbit when
receiving mouse information (and if you are making mouse then send out
7 databits and 2 stop bits).
The byte marked with 1. is send first, then the others. The bit D6 in
the first byte is used for syncronizing the software to mouse packets
if it goes out of sync.
LB is the state of the left button (1 means pressed down)
RB is the state of the right button (1 means pressed down)
X7-X0 movement in X direction since last packet (signed byte)
Y7-Y0 movement in Y direction since last packet (signed byte)
Mouse identification
When DTR line is toggled, mouse should send one data byte containing
letter 'M' (ascii 77).
Logitech serial mouse
Logitech uses the Microsoft serial mouse protocol in their mouses (for
example Logitech Pilot mouse and others). The origianal protocol supports
only two buttons, but logitech as added third button to some of their
mouse models. To make this possible logitech has made one extension to
the protocol.
I have not seen any documentation about the exact documents, but here is
what I have found out: The information of the third button state is sent
using one extra byte which is send after the normal packet when needed.
Value 32 (dec) is sent every time when the center button is pressed down.
It is also sent every time with the data packet when center button is kept
down and the mouse data packet is sent for other reasons. When center
button is released, the mouse sends the normal data packet followed by
data bythe which has value 0 (dec). As you can see the extra data byte
is sent only when you mess with the center button.
Mouse systems mouse
Serial data parameters:
1200bps, 8 databits, 1 stop-bit
Data packet format:
D7 D6 D5 D4 D3 D2 D1 D0
1. 1 0 0 0 0 LB CB RB
2. X7 X6 X5 X4 X3 X2 X1 X0
3. Y7 Y6 Y5 Y4 Y3 Y4 Y1 Y0
4. X7' X6' X5' X4' X3' X2' X1' X0'
5. Y7' Y6' Y5' Y4' Y3' Y4' Y1' Y0'
LB is left button state (0 = pressed, 1 = released)
CB is center button state (0 = pressed, 1 = released)
RB is right button state (0 = pressed, 1 = released)
X7-X0 movement in X direction since last packet in signed byte
format (-128..+127), positive direction right
Y7-Y0 movement in Y direction since last packet in signed byte
format (-128..+127), positive direction up
X7'-X0' movement in X direction since sending of X7-X0 packet in
signed byte format (-128..+127), positive direction right
Y7'-Y0' movement in Y direction since sending of Y7-Y0 packet in
signed byte format (-128..+127), positive direction up
The last two bytes in the packet (bytes 4 and 5) contains information
about movement data changes which have occured after data bytes 2 and 3
have been sent.

View file

@ -1,5 +1,8 @@
/* Mouse definitions common to both mouse class and port drivers */
#define DD_MOUSE_DEVICE_NAME "\\Device\\PointerClass"
#define DD_MOUSE_DEVICE_NAME_U L"\\Device\\PointerClass"
#define IO_MOUSE_INCREMENT 6
#define MOUSE_BUFFER_SIZE 32
@ -8,6 +11,8 @@
#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 IOCTL_MOUSE_QUERY_ATTRIBUTES CTL_CODE(FILE_DEVICE_MOUSE, 0x0000, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define MOUSE_BUTTON_1_DOWN 0x0001
#define MOUSE_BUTTON_1_UP 0x0002
#define MOUSE_BUTTON_2_DOWN 0x0004
@ -27,6 +32,16 @@
#define MOUSE_MIDDLE_BUTTON_DOWN MOUSE_BUTTON_3_DOWN
#define MOUSE_MIDDLE_BUTTON_UP MOUSE_BUTTON_3_UP
#define MOUSE_SERIAL_HARDWARE 0x0004
#define WHEELMOUSE_SERIAL_HARDWARE 0x0040
typedef struct _MOUSE_ATTRIBUTES {
USHORT MouseIdentifier;
USHORT NumberOfButtons;
USHORT SampleRate;
ULONG InputDataQueueLength;
} MOUSE_ATTRIBUTES, *PMOUSE_ATTRIBUTES;
/* Mouse input data structure */
typedef struct _MOUSE_INPUT_DATA {
USHORT UnitId;