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)->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;
+}
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]