New serial mouse driver, which is PnP compliant Added: trunk/reactos/drivers/input/sermouse/ Added: trunk/reactos/drivers/input/sermouse/createclose.c Added: trunk/reactos/drivers/input/sermouse/detect.c Added: trunk/reactos/drivers/input/sermouse/fdo.c Added: trunk/reactos/drivers/input/sermouse/internaldevctl.c Added: trunk/reactos/drivers/input/sermouse/misc.c Added: trunk/reactos/drivers/input/sermouse/readmouse.c Added: trunk/reactos/drivers/input/sermouse/sermouse.c Added: trunk/reactos/drivers/input/sermouse/sermouse.h Added: trunk/reactos/drivers/input/sermouse/sermouse.rc Added: trunk/reactos/drivers/input/sermouse/sermouse.txt Added: trunk/reactos/drivers/input/sermouse/sermouse.xml _____
Added: trunk/reactos/drivers/input/sermouse/createclose.c --- trunk/reactos/drivers/input/sermouse/createclose.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/createclose.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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)->PnpS tate == 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; +} Property changes on: trunk/reactos/drivers/input/sermouse/createclose.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/drivers/input/sermouse/detect.c --- trunk/reactos/drivers/input/sermouse/detect.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/detect.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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; +} Property changes on: trunk/reactos/drivers/input/sermouse/detect.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/drivers/input/sermouse/fdo.c --- trunk/reactos/drivers/input/sermouse/fdo.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/fdo.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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; +} Property changes on: trunk/reactos/drivers/input/sermouse/fdo.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/drivers/input/sermouse/internaldevctl.c --- trunk/reactos/drivers/input/sermouse/internaldevctl.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/internaldevctl.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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; +} Property changes on: trunk/reactos/drivers/input/sermouse/internaldevctl.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/drivers/input/sermouse/misc.c --- trunk/reactos/drivers/input/sermouse/misc.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/misc.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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); +} Property changes on: trunk/reactos/drivers/input/sermouse/misc.c ___________________________________________________________________ Name: svn:eol-style + native _____
Added: trunk/reactos/drivers/input/sermouse/readmouse.c --- trunk/reactos/drivers/input/sermouse/readmouse.c 2005-11-09 11:54:53 UTC (rev 19099) +++ trunk/reactos/drivers/input/sermouse/readmouse.c 2005-11-09 11:57:58 UTC (rev 19100) @@ -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; + } + } [truncated at 1000 lines; 526 more skipped]