mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
New serial mouse driver, which is PnP compliant
svn path=/trunk/; revision=19100
This commit is contained in:
parent
9bfa51a8fc
commit
3f348259c3
11 changed files with 1427 additions and 0 deletions
58
reactos/drivers/input/sermouse/createclose.c
Normal file
58
reactos/drivers/input/sermouse/createclose.c
Normal 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;
|
||||
}
|
282
reactos/drivers/input/sermouse/detect.c
Normal file
282
reactos/drivers/input/sermouse/detect.c
Normal 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;
|
||||
}
|
239
reactos/drivers/input/sermouse/fdo.c
Normal file
239
reactos/drivers/input/sermouse/fdo.c
Normal 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;
|
||||
}
|
89
reactos/drivers/input/sermouse/internaldevctl.c
Normal file
89
reactos/drivers/input/sermouse/internaldevctl.c
Normal 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;
|
||||
}
|
61
reactos/drivers/input/sermouse/misc.c
Normal file
61
reactos/drivers/input/sermouse/misc.c
Normal 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);
|
||||
}
|
277
reactos/drivers/input/sermouse/readmouse.c
Normal file
277
reactos/drivers/input/sermouse/readmouse.c
Normal 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);
|
||||
}
|
167
reactos/drivers/input/sermouse/sermouse.c
Normal file
167
reactos/drivers/input/sermouse/sermouse.c
Normal 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;
|
||||
}
|
151
reactos/drivers/input/sermouse/sermouse.h
Normal file
151
reactos/drivers/input/sermouse/sermouse.h
Normal 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);
|
7
reactos/drivers/input/sermouse/sermouse.rc
Normal file
7
reactos/drivers/input/sermouse/sermouse.rc
Normal 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>
|
82
reactos/drivers/input/sermouse/sermouse.txt
Normal file
82
reactos/drivers/input/sermouse/sermouse.txt
Normal 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.
|
14
reactos/drivers/input/sermouse/sermouse.xml
Normal file
14
reactos/drivers/input/sermouse/sermouse.xml
Normal 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>
|
Loading…
Reference in a new issue