New serial mouse driver, which is PnP compliant

svn path=/trunk/; revision=19100
This commit is contained in:
Hervé Poussineau 2005-11-09 11:57:58 +00:00
parent 9bfa51a8fc
commit 3f348259c3
11 changed files with 1427 additions and 0 deletions

View file

@ -0,0 +1,58 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/fdo.c
* PURPOSE: IRP_MJ_CREATE and IRP_MJ_CLOSE operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
NTSTATUS NTAPI
SermouseStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp); /* FIXME: remove the declaration */
NTSTATUS NTAPI
SermouseCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("IRP_MJ_CREATE\n");
ASSERT(((PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState == dsStarted);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
SermouseClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("IRP_MJ_CLOSE\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
SermouseCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("IRP_MJ_CLEANUP\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,282 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/detect.c
* PURPOSE: Detect serial mouse type
*
* PROGRAMMERS: Jason Filby (jasonfilby@yahoo.com)
* Filip Navara (xnavara@volny.cz)
* Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
/* Most of this file is ripped from reactos/drivers/bus/serenum/detect.c */
static NTSTATUS
SermouseDeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer OPTIONAL,
IN OUT PULONG OutputBufferSize)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
KeInitializeEvent (&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(CtlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
(OutputBufferSize) ? *OutputBufferSize : 0,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = IoStatus.Information;
}
return Status;
}
static NTSTATUS
SermouseSendIrp(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG MajorFunction)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
MajorFunction,
DeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildSynchronousFsdRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
static NTSTATUS
ReadBytes(
IN PDEVICE_OBJECT LowerDevice,
OUT PUCHAR Buffer,
IN ULONG BufferSize,
OUT PULONG FilledBytes)
{
PIRP Irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
LARGE_INTEGER zero;
NTSTATUS Status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
zero.QuadPart = 0;
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
LowerDevice,
Buffer, BufferSize,
&zero,
&event,
&ioStatus);
if (!Irp)
return FALSE;
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
Status = ioStatus.Status;
}
DPRINT("Bytes received: %lu/%lu\n",
ioStatus.Information, BufferSize);
*FilledBytes = ioStatus.Information;
return Status;
}
static NTSTATUS
SermouseWait(ULONG milliseconds)
{
KTIMER Timer;
LARGE_INTEGER DueTime;
DueTime.QuadPart = milliseconds * -10;
KeInitializeTimer(&Timer);
KeSetTimer(&Timer, DueTime, NULL);
return KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);
}
SERMOUSE_MOUSE_TYPE
SermouseDetectLegacyDevice(
IN PDEVICE_OBJECT LowerDevice)
{
ULONG Fcr, Mcr;
ULONG BaudRate;
ULONG Command;
SERIAL_TIMEOUTS Timeouts;
SERIAL_LINE_CONTROL LCR;
ULONG i, Count;
UCHAR Buffer[16];
SERMOUSE_MOUSE_TYPE MouseType = mtNone;
NTSTATUS Status;
RtlZeroMemory(Buffer, sizeof(Buffer));
/* Open port */
Status = SermouseSendIrp(LowerDevice, IRP_MJ_CREATE);
if (!NT_SUCCESS(Status)) return mtNone;
/* Reset UART */
CHECKPOINT;
Mcr = 0; /* MCR: DTR/RTS/OUT2 off */
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
&Mcr, sizeof(Mcr), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set communications parameters */
CHECKPOINT;
/* DLAB off */
Fcr = 0;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
&Fcr, sizeof(Fcr), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set serial port speed */
BaudRate = SERIAL_BAUD_1200;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set LCR */
LCR.WordLength = 7;
LCR.Parity = NO_PARITY;
LCR.StopBits = STOP_BITS_2;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&LCR, sizeof(LCR), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Disable DTR/RTS */
CHECKPOINT;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Flush receive buffer */
CHECKPOINT;
Command = SERIAL_PURGE_RXCLEAR;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
&Command, sizeof(Command), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Wait 100 ms */
SermouseWait(100);
/* Enable DTR/RTS */
CHECKPOINT;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
SermouseWait(200);
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Set timeout to 500 microseconds */
CHECKPOINT;
Timeouts.ReadIntervalTimeout = 0;
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 500;
Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
&Timeouts, sizeof(Timeouts), NULL, NULL);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Fill the read buffer */
CHECKPOINT;
Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), &Count);
if (!NT_SUCCESS(Status)) goto ByeBye;
for (i = 0; i < Count; i++)
{
if (Buffer[i] == 'B')
{
/* Sign for Microsoft Ballpoint */
DPRINT1("Microsoft Ballpoint device detected. THIS DEVICE IS NOT YET SUPPORTED");
MouseType = mtNone;
goto ByeBye;
}
else if (Buffer[i] == 'M')
{
/* Sign for Microsoft Mouse protocol followed by button specifier */
if (i == sizeof(Buffer) - 1)
{
/* Overflow Error */
goto ByeBye;
}
switch (Buffer[i + 1])
{
case '3':
DPRINT("Microsoft Mouse with 3-buttons detected\n");
MouseType = mtLogitech;
case 'Z':
DPRINT("Microsoft Wheel Mouse detected\n");
MouseType = mtWheelZ;
default:
DPRINT("Microsoft Mouse with 2-buttons detected\n");
MouseType = mtMicrosoft;
}
goto ByeBye;
}
}
ByeBye:
/* Close port */
SermouseSendIrp(LowerDevice, IRP_MJ_CLOSE);
SermouseSendIrp(LowerDevice, IRP_MJ_CLEANUP);
return MouseType;
}

View file

@ -0,0 +1,239 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/fdo.c
* PURPOSE: IRP_MJ_PNP operations for FDOs
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
NTSTATUS NTAPI
SermouseAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
PSERMOUSE_DRIVER_EXTENSION DriverExtension;
ULONG DeviceId = 0;
ULONG PrefixLength;
UNICODE_STRING DeviceNameU;
PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
PDEVICE_OBJECT Fdo;
PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("SermouseAddDevice called. Pdo = 0x%p\n", Pdo);
/* Create new device object */
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
DeviceNameU.Length = 0;
DeviceNameU.MaximumLength =
wcslen(L"\\Device\\") * sizeof(WCHAR) /* "\Device\" */
+ DriverExtension->PointerDeviceBaseName.Length /* "PointerPort" */
+ 4 * sizeof(WCHAR) /* Id between 0 and 9999 */
+ sizeof(UNICODE_NULL); /* Final NULL char */
DeviceNameU.Buffer = ExAllocatePool(PagedPool, DeviceNameU.MaximumLength);
if (!DeviceNameU.Buffer)
{
DPRINT("ExAllocatePool() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
if (!NT_SUCCESS(Status))
{
DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
goto cleanup;
}
Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->PointerDeviceBaseName);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
goto cleanup;
}
PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
while (DeviceId < 9999)
{
DeviceNameU.Length = PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR);
Status = IoCreateDevice(
DriverObject,
sizeof(SERMOUSE_DEVICE_EXTENSION),
&DeviceNameU,
FILE_DEVICE_SERIAL_MOUSE_PORT,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&Fdo);
if (NT_SUCCESS(Status))
goto cleanup;
else if (Status != STATUS_OBJECT_NAME_COLLISION)
{
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
goto cleanup;
}
DeviceId++;
}
DPRINT("Too much devices starting with '\\Device\\%wZ'\n", &DriverExtension->PointerDeviceBaseName);
Status = STATUS_UNSUCCESSFUL;
cleanup:
if (!NT_SUCCESS(Status))
{
ExFreePool(DeviceNameU.Buffer);
return Status;
}
DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(SERMOUSE_DEVICE_EXTENSION));
DeviceExtension->MouseType = mtNone;
DeviceExtension->PnpState = dsStopped;
DeviceExtension->DriverExtension = DriverExtension;
KeInitializeEvent(&DeviceExtension->StopWorkerThreadEvent, NotificationEvent, FALSE);
DeviceExtension->MouseInputData[0] = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
if (!DeviceExtension->MouseInputData[0])
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanupFDO;
}
DeviceExtension->MouseInputData[1] = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA));
if (!DeviceExtension->MouseInputData[1])
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanupFDO;
}
Fdo->Flags |= DO_POWER_PAGABLE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
goto cleanupFDO;
}
Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
/* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
ExFreePool(DeviceNameU.Buffer);
return STATUS_SUCCESS;
cleanupFDO:
if (DeviceExtension)
{
ExFreePool(DeviceExtension->MouseInputData[0]);
ExFreePool(DeviceExtension->MouseInputData[1]);
}
if (Fdo)
{
IoDeleteDevice(Fdo);
}
return Status;
}
NTSTATUS NTAPI
SermouseStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
SERMOUSE_MOUSE_TYPE MouseType;
DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->PnpState == dsStopped);
ASSERT(DeviceExtension->LowerDevice);
MouseType = SermouseDetectLegacyDevice(DeviceExtension->LowerDevice);
if (MouseType == mtNone)
{
DPRINT("No mouse connected to Fdo %p\n",
DeviceExtension->LowerDevice);
return STATUS_DEVICE_NOT_CONNECTED;
}
switch (MouseType)
{
case mtMicrosoft:
DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 2;
break;
case mtLogitech:
DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 3;
break;
case mtWheelZ:
DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE;
DeviceExtension->AttributesInformation.NumberOfButtons = 3;
break;
default:
CHECKPOINT;
return STATUS_UNSUCCESSFUL;
}
if (DeviceExtension->DriverExtension->NumberOfButtons != 0)
/* Override the number of buttons */
DeviceExtension->AttributesInformation.NumberOfButtons = DeviceExtension->DriverExtension->NumberOfButtons;
DeviceExtension->AttributesInformation.SampleRate = 1200 / 8;
DeviceExtension->AttributesInformation.InputDataQueueLength = DeviceExtension->DriverExtension->MouseDataQueueSize;
DeviceExtension->MouseType = MouseType;
DeviceExtension->PnpState = dsStarted;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
SermousePnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG Information = 0;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
/* FIXME: do all these minor functions
IRP_MN_QUERY_REMOVE_DEVICE 0x1
IRP_MN_REMOVE_DEVICE 0x2
IRP_MN_CANCEL_REMOVE_DEVICE 0x3
IRP_MN_STOP_DEVICE 0x4
IRP_MN_QUERY_STOP_DEVICE 0x5
IRP_MN_CANCEL_STOP_DEVICE 0x6
IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) 0x7
IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
IRP_MN_QUERY_INTERFACE (optional) 0x8
IRP_MN_QUERY_CAPABILITIES (optional) 0x9
IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xd
IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
IRP_MN_SURPRISE_REMOVAL 0x17
*/
case IRP_MN_START_DEVICE: /* 0x0 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
Status = SermouseStartDevice(DeviceObject, Irp);
break;
}
default:
{
DPRINT1("IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -0,0 +1,89 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/internaldevctl.c
* PURPOSE: IRP_MJ_INTERNAL_DEVICE_CONTROL operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
NTSTATUS NTAPI
SermouseInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
NTSTATUS Status;
DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_MOUSE_CONNECT:
{
DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_MOUSE_CONNECT\n");
DeviceExtension->ConnectData =
*((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer);
/* Start read loop */
Status = PsCreateSystemThread(
&DeviceExtension->WorkerThreadHandle,
(ACCESS_MASK)0L,
NULL,
NULL,
NULL,
SermouseDeviceWorker,
DeviceObject);
break;
}
case IOCTL_INTERNAL_MOUSE_DISCONNECT:
{
DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_MOUSE_DISCONNECT\n");
/* Ask read loop to end */
KeSetEvent(&DeviceExtension->StopWorkerThreadEvent, (KPRIORITY)0, FALSE);
break;
}
case IOCTL_MOUSE_QUERY_ATTRIBUTES:
{
DPRINT("IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_MOUSE_QUERY_ATTRIBUTES\n");
if (Stack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(MOUSE_ATTRIBUTES))
{
*(PMOUSE_ATTRIBUTES)Irp->AssociatedIrp.SystemBuffer =
DeviceExtension->AttributesInformation;
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_BUFFER_TOO_SMALL;
}
break;
}
default:
{
DPRINT1("IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
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;
}

View file

@ -0,0 +1,61 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/misc.c
* PURPOSE: Misceallenous operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
static NTSTATUS NTAPI
ForwardIrpAndWaitCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned)
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice = ((PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
KEVENT Event;
NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
if (NT_SUCCESS(Status))
Status = Irp->IoStatus.Status;
}
return Status;
}
NTSTATUS NTAPI
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice = ((PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(LowerDevice, Irp);
}

View file

@ -0,0 +1,277 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/readmouse.c
* PURPOSE: Read mouse moves and send them to mouclass
*
* PROGRAMMERS: Jason Filby (jasonfilby@yahoo.com)
* Filip Navara (xnavara@volny.cz)
* Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#include "sermouse.h"
static NTSTATUS
SermouseDeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer OPTIONAL,
IN OUT PULONG OutputBufferSize)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(CtlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
(OutputBufferSize) ? *OutputBufferSize : 0,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = IoStatus.Information;
}
return Status;
}
VOID NTAPI
SermouseDeviceWorker(
PVOID Context)
{
PSERMOUSE_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT LowerDevice;
UCHAR Buffer[PACKET_BUFFER_SIZE];
PIRP Irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PUCHAR PacketBuffer;
UCHAR ReceivedByte;
ULONG Queue;
PMOUSE_INPUT_DATA Input;
ULONG ButtonsDifference;
KIRQL OldIrql;
ULONG i;
ULONG Fcr;
ULONG BaudRate;
SERIAL_TIMEOUTS Timeouts;
SERIAL_LINE_CONTROL LCR;
LARGE_INTEGER Zero;
NTSTATUS Status;
DPRINT("SermouseDeviceWorker() called\n");
DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
LowerDevice = DeviceExtension->LowerDevice;
Zero.QuadPart = 0;
PacketBuffer = DeviceExtension->PacketBuffer;
ASSERT(LowerDevice);
/* Initialize device extension */
DeviceExtension->ActiveQueue = 0;
DeviceExtension->PacketBufferPosition = 0;
DeviceExtension->PreviousButtons = 0;
/* Initialize serial port */
Fcr = 0;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
&Fcr, sizeof(Fcr), NULL, NULL);
if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* Set serial port speed */
BaudRate = DeviceExtension->DriverExtension->SampleRate;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, NULL);
if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* Set LCR */
LCR.WordLength = 7;
LCR.Parity = NO_PARITY;
LCR.StopBits = STOP_BIT_1;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&LCR, sizeof(LCR), NULL, NULL);
if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* Set timeouts */
Timeouts.ReadTotalTimeoutConstant = Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadIntervalTimeout = 100;
Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
Status = SermouseDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
&Timeouts, sizeof(Timeouts), NULL, NULL);
if (!NT_SUCCESS(Status)) PsTerminateSystemThread(Status);
/* main read loop */
while (TRUE)
{
Status = KeWaitForSingleObject(
&DeviceExtension->StopWorkerThreadEvent,
Executive,
KernelMode,
TRUE,
&Zero);
if (Status != STATUS_TIMEOUT)
{
/* we need to stop the worker thread */
KeResetEvent(&DeviceExtension->StopWorkerThreadEvent);
break;
}
KeInitializeEvent(&event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
LowerDevice,
Buffer, PACKET_BUFFER_SIZE,
&Zero,
&event,
&ioStatus);
if (!Irp)
{
/* no memory actually, try later */
CHECKPOINT;
KeStallExecutionProcessor(10);
continue;
}
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
Status = ioStatus.Status;
}
if (!NT_SUCCESS(Status))
continue;
/* Read all available data and process */
for (i = 0; i < ioStatus.Information; i++)
{
ReceivedByte = Buffer[i];
DPRINT1("ReceivedByte 0x%02x\n", ReceivedByte);
/* Synchronize */
if ((ReceivedByte & 0x40) == 0x40)
DeviceExtension->PacketBufferPosition = 0;
PacketBuffer[DeviceExtension->PacketBufferPosition] = ReceivedByte & 0x7f;
DeviceExtension->PacketBufferPosition++;
/* Process packet if complete */
if (DeviceExtension->PacketBufferPosition >= 3)
{
Queue = DeviceExtension->ActiveQueue % 2;
/* Prevent buffer overflow */
if (DeviceExtension->InputDataCount[Queue] == DeviceExtension->DriverExtension->MouseDataQueueSize)
continue;
Input = &DeviceExtension->MouseInputData[Queue][DeviceExtension->InputDataCount[Queue]];
if (DeviceExtension->PacketBufferPosition == 3)
{
/* Retrieve change in x and y from packet */
Input->LastX = (signed char)(PacketBuffer[1] | ((PacketBuffer[0] & 0x03) << 6));
Input->LastY = (signed char)(PacketBuffer[2] | ((PacketBuffer[0] & 0x0c) << 4));
/* Determine the current state of the buttons */
Input->RawButtons = (DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE) |
((UCHAR)(PacketBuffer[0] & LEFT_BUTTON_MASK) >> LEFT_BUTTON_SHIFT) |
((UCHAR)(PacketBuffer[0] & RIGHT_BUTTON_MASK) >> RIGHT_BUTTON_SHIFT);
}
else if (DeviceExtension->PacketBufferPosition == 4)
{
DeviceExtension->PacketBufferPosition = 0;
/* If middle button state changed than report event */
if (((UCHAR)(PacketBuffer[3] & MIDDLE_BUTTON_MASK) >> MIDDLE_BUTTON_SHIFT) ^
(DeviceExtension->PreviousButtons & MOUSE_BUTTON_MIDDLE))
{
Input->RawButtons ^= MOUSE_BUTTON_MIDDLE;
Input->LastX = 0;
Input->LastY = 0;
}
else
{
continue;
}
}
/* Determine ButtonFlags */
Input->ButtonFlags = 0;
ButtonsDifference = DeviceExtension->PreviousButtons ^ Input->RawButtons;
if (ButtonsDifference != 0)
{
if (ButtonsDifference & MOUSE_BUTTON_LEFT
&& DeviceExtension->AttributesInformation.NumberOfButtons >= 1)
{
if (Input->RawButtons & MOUSE_BUTTON_LEFT)
Input->ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_LEFT_BUTTON_UP;
}
if (ButtonsDifference & MOUSE_BUTTON_RIGHT
&& DeviceExtension->AttributesInformation.NumberOfButtons >= 2)
{
if (Input->RawButtons & MOUSE_BUTTON_RIGHT)
Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_RIGHT_BUTTON_UP;
}
if (ButtonsDifference & MOUSE_BUTTON_MIDDLE
&& DeviceExtension->AttributesInformation.NumberOfButtons >= 3)
{
if (Input->RawButtons & MOUSE_BUTTON_MIDDLE)
Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN;
else
Input->ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP;
}
}
/* Send the Input data to the Mouse Class driver */
DeviceExtension->InputDataCount[Queue]++;
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
InterlockedIncrement((PLONG)&DeviceExtension->ActiveQueue);
(*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)(
DeviceExtension->ConnectData.ClassDeviceObject,
DeviceExtension->MouseInputData[Queue],
DeviceExtension->MouseInputData[Queue] + 1,
&DeviceExtension->InputDataCount[Queue]);
KeLowerIrql(OldIrql);
DeviceExtension->InputDataCount[Queue] = 0;
/* Copy RawButtons to Previous Buttons for Input */
DeviceExtension->PreviousButtons = Input->RawButtons;
}
}
}
PsTerminateSystemThread(STATUS_SUCCESS);
}

View file

@ -0,0 +1,167 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial mouse driver
* FILE: drivers/input/sermouse/sermouse.c
* PURPOSE: Serial mouse driver entry point
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
*/
#define NDEBUG
#include <debug.h>
#define INITGUID
#include "sermouse.h"
VOID NTAPI
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
// nothing to do here yet
}
NTSTATUS NTAPI
IrpStub(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("Irp stub for major function 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
static NTSTATUS
ReadRegistryEntries(
IN PUNICODE_STRING RegistryPath,
IN PSERMOUSE_DRIVER_EXTENSION DriverExtension)
{
UNICODE_STRING ParametersRegistryKey;
RTL_QUERY_REGISTRY_TABLE Parameters[5];
NTSTATUS Status;
ULONG DefaultMouseDataQueueSize = 0x64;
ULONG DefaultNumberOfButtons = 0;
UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerPort");
ULONG DefaultSampleRate = SERIAL_BAUD_1200;
ParametersRegistryKey.Length = 0;
ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
ParametersRegistryKey.Buffer = ExAllocatePool(PagedPool, ParametersRegistryKey.MaximumLength);
if (!ParametersRegistryKey.Buffer)
{
DPRINT("ExAllocatePool() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
RtlZeroMemory(Parameters, sizeof(Parameters));
Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[0].Name = L"MouseDataQueueSize";
Parameters[0].EntryContext = &DriverExtension->MouseDataQueueSize;
Parameters[0].DefaultType = REG_DWORD;
Parameters[0].DefaultData = &DefaultMouseDataQueueSize;
Parameters[0].DefaultLength = sizeof(ULONG);
Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[1].Name = L"NumberOfButtons";
Parameters[1].EntryContext = &DriverExtension->NumberOfButtons;
Parameters[1].DefaultType = REG_DWORD;
Parameters[1].DefaultData = &DefaultNumberOfButtons;
Parameters[1].DefaultLength = sizeof(ULONG);
Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[2].Name = L"PointerDeviceBaseName";
Parameters[2].EntryContext = &DriverExtension->PointerDeviceBaseName;
Parameters[2].DefaultType = REG_SZ;
Parameters[2].DefaultData = &DefaultPointerDeviceBaseName;
Parameters[2].DefaultLength = 0;
Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
Parameters[3].Name = L"SampleRate";
Parameters[3].EntryContext = &DriverExtension->SampleRate;
Parameters[3].DefaultType = REG_DWORD;
Parameters[3].DefaultData = &DefaultSampleRate;
Parameters[3].DefaultLength = sizeof(ULONG);
Status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
ParametersRegistryKey.Buffer,
Parameters,
NULL,
NULL);
if (NT_SUCCESS(Status))
{
/* Check values */
if (DriverExtension->MouseDataQueueSize == 0)
{
DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize;
}
}
else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
/* Registry path doesn't exist. Set defaults */
DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize;
DriverExtension->NumberOfButtons = DefaultNumberOfButtons;
Status = RtlDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&DefaultPointerDeviceBaseName,
&DriverExtension->PointerDeviceBaseName);
DriverExtension->SampleRate = DefaultSampleRate;
}
return Status;
}
/*
* Standard DriverEntry method.
*/
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
PSERMOUSE_DRIVER_EXTENSION DriverExtension;
ULONG i;
NTSTATUS Status;
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
sizeof(SERMOUSE_DRIVER_EXTENSION),
(PVOID*)&DriverExtension);
if (!NT_SUCCESS(Status))
{
DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
return Status;
}
RtlZeroMemory(DriverExtension, sizeof(SERMOUSE_DRIVER_EXTENSION));
Status = ReadRegistryEntries(RegistryPath, DriverExtension);
if (!NT_SUCCESS(Status))
{
DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status);
return Status;
}
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = SermouseAddDevice;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = IrpStub;
DriverObject->MajorFunction[IRP_MJ_CREATE] = SermouseCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SermouseClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SermouseCleanup;
//DriverObject->MajorFunction[IRP_MJ_READ] = SermouseRead;
//DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SermouseDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = SermouseInternalDeviceControl;
//DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SermouseQueryInformation;
DriverObject->MajorFunction[IRP_MJ_PNP] = SermousePnp;
//DriverObject->MajorFunction[IRP_MJ_POWER] = SermousePower;
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,151 @@
#include <ntifs.h>
#include <kbdmou.h>
#include <ntddser.h>
#include <ntddmou.h>
#if defined(__GNUC__)
#include <stdio.h>
/* FIXME: these prototypes MUST NOT be here! */
NTSTATUS NTAPI
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#elif defined(_MSC_VER)
NTSTATUS NTAPI
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#else
#error Unknown compiler!
#endif
typedef enum
{
dsStopped,
dsStarted,
dsPaused,
dsRemoved,
dsSurpriseRemoved
} SERMOUSE_DEVICE_STATE;
typedef enum
{
mtNone, /* No Mouse */
mtMicrosoft, /* Microsoft Mouse with 2 buttons */
mtLogitech, /* Logitech Mouse with 3 buttons */
mtWheelZ /* Microsoft Wheel Mouse (aka Z Mouse) */
} SERMOUSE_MOUSE_TYPE;
/* Size for packet buffer used in interrupt routine */
#define PACKET_BUFFER_SIZE 4
/* Hardware byte mask for left button */
#define LEFT_BUTTON_MASK 0x20
/* Hardware to Microsoft specific code byte shift for left button */
#define LEFT_BUTTON_SHIFT 5
/* Hardware byte mask for right button */
#define RIGHT_BUTTON_MASK 0x10
/* Hardware to Microsoft specific code byte shift for right button */
#define RIGHT_BUTTON_SHIFT 3
/* Hardware byte mask for middle button */
#define MIDDLE_BUTTON_MASK 0x20
/* Hardware to Microsoft specific code byte shift for middle button */
#define MIDDLE_BUTTON_SHIFT 3
/* Microsoft byte mask for left button */
#define MOUSE_BUTTON_LEFT 0x01
/* Microsoft byte mask for right button */
#define MOUSE_BUTTON_RIGHT 0x02
/* Microsoft byte mask for middle button */
#define MOUSE_BUTTON_MIDDLE 0x04
typedef struct _SERMOUSE_DRIVER_EXTENSION
{
ULONG MouseDataQueueSize;
ULONG NumberOfButtons;
UNICODE_STRING PointerDeviceBaseName;
ULONG SampleRate;
} SERMOUSE_DRIVER_EXTENSION, *PSERMOUSE_DRIVER_EXTENSION;
typedef struct _SERMOUSE_DEVICE_EXTENSION
{
PDEVICE_OBJECT LowerDevice;
SERMOUSE_DEVICE_STATE PnpState;
SERMOUSE_MOUSE_TYPE MouseType;
PSERMOUSE_DRIVER_EXTENSION DriverExtension;
HANDLE WorkerThreadHandle;
KEVENT StopWorkerThreadEvent;
ULONG ActiveQueue;
ULONG InputDataCount[2];
CONNECT_DATA ConnectData;
MOUSE_INPUT_DATA* MouseInputData[2];
UCHAR PacketBuffer[PACKET_BUFFER_SIZE];
ULONG PacketBufferPosition;
ULONG PreviousButtons;
MOUSE_ATTRIBUTES AttributesInformation;
} SERMOUSE_DEVICE_EXTENSION, *PSERMOUSE_DEVICE_EXTENSION;
/************************************ createclose.c */
NTSTATUS NTAPI
SermouseCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NTAPI
SermouseClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NTAPI
SermouseCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ detect.c */
SERMOUSE_MOUSE_TYPE
SermouseDetectLegacyDevice(
IN PDEVICE_OBJECT LowerDevice);
/************************************ fdo.c */
NTSTATUS NTAPI
SermouseAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo);
NTSTATUS NTAPI
SermousePnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ internaldevctl.c */
NTSTATUS NTAPI
SermouseInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ misc.c */
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS NTAPI
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ readmouse.c */
VOID NTAPI
SermouseDeviceWorker(
PVOID Context);

View file

@ -0,0 +1,7 @@
/* $Id$ */
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Serial mouse device driver\0"
#define REACTOS_STR_INTERNAL_NAME "sermouse\0"
#define REACTOS_STR_ORIGINAL_FILENAME "sermouse.sys\0"
#include <reactos/version.rc>

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

@ -0,0 +1,14 @@
<module name="sermouse" type="kernelmodedriver" installbase="system32/drivers" installname="sermouse.sys">
<include base="sermouse">.</include>
<define name="__USE_W32API" />
<library>ntoskrnl</library>
<library>hal</library>
<file>createclose.c</file>
<file>detect.c</file>
<file>fdo.c</file>
<file>internaldevctl.c</file>
<file>misc.c</file>
<file>readmouse.c</file>
<file>sermouse.c</file>
<file>sermouse.rc</file>
</module>