Rewrite mouclass, so it can now handle more than one mouse. win32k: try to open the keyboard/mouse in a loop, as they can not be present at startup Modified: trunk/reactos/bootdata/hivesys.inf Added: trunk/reactos/drivers/input/mouclass/misc.c Modified: trunk/reactos/drivers/input/mouclass/mouclass.c Modified: trunk/reactos/drivers/input/mouclass/mouclass.h Modified: trunk/reactos/drivers/input/mouclass/mouclass.xml Modified: trunk/reactos/subsys/win32k/ntuser/input.c _____
Modified: trunk/reactos/bootdata/hivesys.inf --- trunk/reactos/bootdata/hivesys.inf 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/bootdata/hivesys.inf 2005-10-31 00:14:45 UTC (rev 18906) @@ -532,7 +532,7 @@
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass","Type",0x00010001,0x00 000001
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","ConnectMul tiplePorts",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","MouseDataQ ueueSize",0x00010001,0x00000064 -HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDe viceBaseName",0x00000000,"PointerClass" +HKLM,"SYSTEM\CurrentControlSet\Services\mouclass\Parameters","PointerDe viceBaseName",0x00000000,"PointerClassPnp"
HKLM,"SYSTEM\CurrentControlSet\Control\Class{4D36E96F-E325-11CE-BFC1-08 002BE10318}","UpperFilters",0x00010000,"mouclass"
; Mailslot filesystem driver _____
Added: trunk/reactos/drivers/input/mouclass/misc.c --- trunk/reactos/drivers/input/mouclass/misc.c 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/drivers/input/mouclass/misc.c 2005-10-31 00:14:45 UTC (rev 18906) @@ -0,0 +1,61 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Mouse class driver + * FILE: drivers/input/mouclass/misc.c + * PURPOSE: Misceallenous operations + * + * PROGRAMMERS: HervÚ Poussineau (hpoussin@reactos.org) + */ + +#define NDEBUG +#include <debug.h> + +#include "mouclass.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 = ((PMOUCLASS_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 = ((PMOUCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice ; + + IoSkipCurrentIrpStackLocation(Irp); + return IoCallDriver(LowerDevice, Irp); +} Property changes on: trunk/reactos/drivers/input/mouclass/misc.c ___________________________________________________________________ Name: svn:eol-style + native _____
Modified: trunk/reactos/drivers/input/mouclass/mouclass.c --- trunk/reactos/drivers/input/mouclass/mouclass.c 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/drivers/input/mouclass/mouclass.c 2005-10-31 00:14:45 UTC (rev 18906) @@ -1,277 +1,599 @@
-/* +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Mouse class driver + * FILE: drivers/mouclass/mouclass.c + * PURPOSE: Mouse class driver + * + * PROGRAMMERS: HervÚ Poussineau (hpoussin@reactos.org) + */
- ** Mouse class driver 0.0.1 - ** Written by Jason Filby (jasonfilby@yahoo.com) - ** For ReactOS (www.reactos.com) +#define NDEBUG +#include <debug.h>
- ** The class driver between win32k and the various mouse port drivers +#define INITGUID +#include "mouclass.h"
- ** FIXME: Support IRP cancellation properly. -*/ +static VOID NTAPI +DriverUnload(IN PDRIVER_OBJECT DriverObject) +{ + // nothing to do here yet +}
-#include <ddk/ntddk.h> -#include <ddk/ntddmou.h> -#include <ddk/kbdmou.h> -#include "mouclass.h" +static NTSTATUS NTAPI +MouclassCreate( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CREATE\n");
-#define NDEBUG -#include <debug.h> + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp);
-NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); + /* FIXME: open all associated Port devices */ + return STATUS_SUCCESS; +}
-PDEVICE_OBJECT MouclassDeviceObject; +static NTSTATUS NTAPI +MouclassClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + DPRINT("IRP_MJ_CLOSE\n");
-static BOOLEAN MouseClassCallBack( - PDEVICE_OBJECT ClassDeviceObject, PMOUSE_INPUT_DATA MouseDataStart, - PMOUSE_INPUT_DATA MouseDataEnd, PULONG ConsumedCount) + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp); + + /* FIXME: close all associated Port devices */ + return STATUS_SUCCESS; +} + +static NTSTATUS NTAPI +MouclassRead( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - PDEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension; - PIRP Irp = NULL; - KIRQL OldIrql; - PIO_STACK_LOCATION Stack; - ULONG InputCount = MouseDataEnd - MouseDataStart; - ULONG ReadSize; + DPRINT("IRP_MJ_READ\n");
- DPRINT("Entering MouseClassCallBack\n"); - /* A filter driver might have consumed all the data already; I'm - * not sure if they are supposed to move the packets when they - * consume them though. - */ - if (ClassDeviceExtension->ReadIsPending == TRUE && - InputCount) - { - Irp = ClassDeviceObject->CurrentIrp; - ClassDeviceObject->CurrentIrp = NULL; - Stack = IoGetCurrentIrpStackLocation(Irp); + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + return ForwardIrpAndForget(DeviceObject, Irp);
- /* A read request is waiting for input, so go straight to it */ - RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, MouseDataStart, - sizeof(MOUSE_INPUT_DATA)); + if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA)) + { + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT);
- /* Go to next packet and complete this request with STATUS_SUCCESS */ - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA); - Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA); + return STATUS_BUFFER_TOO_SMALL; + }
- ClassDeviceExtension->ReadIsPending = FALSE; + IoMarkIrpPending(Irp); + IoStartPacket(DeviceObject, Irp, NULL, NULL); + return STATUS_PENDING; +}
- /* Skip the packet we just sent away */ - MouseDataStart++; - (*ConsumedCount)++; - InputCount--; - } +static NTSTATUS NTAPI +IrpStub( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status = STATUS_NOT_SUPPORTED;
- /* If we have data from the port driver and a higher service to send the data to */ - if (InputCount != 0) - { - KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql); + if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO) + { + /* Forward some IRPs to lower device */ + switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) + { + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + return ForwardIrpAndForget(DeviceObject, Irp); + default: + { + DPRINT1("Port DO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + ASSERT(FALSE); + Status = Irp->IoStatus.Status; + } + } + } + else if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) /* HACK FOR I8042PRT */ + { + Status = STATUS_SUCCESS; + } + else + { + DPRINT1("Class DO stub for major function 0x%lx\n", + IoGetCurrentIrpStackLocation(Irp)->MajorFunction); + ASSERT(FALSE); + Status = Irp->IoStatus.Status; + }
- if (ClassDeviceExtension->InputCount + InputCount > MOUSE_BUFFER_SIZE) - { - ReadSize = MOUSE_BUFFER_SIZE - ClassDeviceExtension->InputCount; - } else { - ReadSize = InputCount; - } + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +}
- /* - * FIXME: If we exceed the buffer, mouse data gets thrown away.. better - * solution? - */ +static NTSTATUS +ReadRegistryEntries( + IN PUNICODE_STRING RegistryPath, + IN PMOUCLASS_DRIVER_EXTENSION DriverExtension) +{ + RTL_QUERY_REGISTRY_TABLE Parameters[4]; + NTSTATUS Status;
- /* - * Move the mouse input data from the port data queue to our class data - * queue. - */ - RtlMoveMemory(ClassDeviceExtension->PortData, (PCHAR)MouseDataStart, - sizeof(MOUSE_INPUT_DATA) * ReadSize); + ULONG DefaultConnectMultiplePorts = 1; + ULONG DefaultMouseDataQueueSize = 0x64; + UNICODE_STRING DefaultPointerDeviceBaseName = RTL_CONSTANT_STRING(L"PointerClassPnp");
- /* Move the pointer and counter up */ - ClassDeviceExtension->PortData += ReadSize; - ClassDeviceExtension->InputCount += ReadSize; + RtlZeroMemory(Parameters, sizeof(Parameters));
- KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql); - (*ConsumedCount) += ReadSize; - } else { - DPRINT("MouseClassCallBack() entered, InputCount = %d - DOING NOTHING\n", InputCount); - } + Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[0].Name = L"ConnectMultiplePorts"; + Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts; + Parameters[0].DefaultType = REG_DWORD; + Parameters[0].DefaultData = &DefaultConnectMultiplePorts; + Parameters[0].DefaultLength = sizeof(ULONG); + + Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL; + Parameters[1].Name = L"MouseDataQueueSize"; + Parameters[1].EntryContext = &DriverExtension->MouseDataQueueSize; + Parameters[1].DefaultType = REG_DWORD; + Parameters[1].DefaultData = &DefaultMouseDataQueueSize; + 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 = sizeof(ULONG);
- if (Irp != NULL) - { - IoStartNextPacket(ClassDeviceObject, FALSE); - IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); - } + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + RegistryPath->Buffer, + Parameters, + NULL, + NULL);
- DPRINT("Leaving MouseClassCallBack\n"); - return TRUE; + if (NT_SUCCESS(Status)) + { + /* Check values */ + if (DriverExtension->ConnectMultiplePorts != 0 + && DriverExtension->ConnectMultiplePorts != 1) + { + DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts; + } + if (DriverExtension->MouseDataQueueSize == 0) + { + DriverExtension->MouseDataQueueSize = DefaultMouseDataQueueSize; + } + } + + return Status; }
-static NTSTATUS ConnectMousePortDriver(PDEVICE_OBJECT ClassDeviceObject) +static NTSTATUS +CreatePointerClassDeviceObject( + IN PDRIVER_OBJECT DriverObject, + OUT PDEVICE_OBJECT *ClassDO OPTIONAL) { - PDEVICE_OBJECT PortDeviceObject = NULL; - PFILE_OBJECT FileObject = NULL; - NTSTATUS status; - UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\Device\PointerClass0"); - IO_STATUS_BLOCK ioStatus; - KEVENT event; - PIRP irp; - CONNECT_DATA ClassInformation; - PDEVICE_EXTENSION DeviceExtension = ClassDeviceObject->DeviceExtension; + PMOUCLASS_DRIVER_EXTENSION DriverExtension; + ULONG DeviceId = 0; + ULONG PrefixLength; + UNICODE_STRING DeviceNameU; + PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */ + PDEVICE_OBJECT Fdo; + PMOUCLASS_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status;
- // Get the port driver's DeviceObject - // FIXME: The name might change.. find a way to be more dynamic? + DPRINT("CreatePointerClassDeviceObject(0x%p)\n", DriverObject);
- status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject); + /* Create new device object */ + DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); + DeviceNameU.Length = 0; + DeviceNameU.MaximumLength = + wcslen(L"\Device\") * sizeof(WCHAR) /* "\Device" */ + + DriverExtension->PointerDeviceBaseName.Length /* "PointerClass" */ + + 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"%ld", DeviceId) * sizeof(WCHAR); + Status = IoCreateDevice( + DriverObject, + sizeof(MOUCLASS_DEVICE_EXTENSION), + &DeviceNameU, + FILE_DEVICE_MOUSE, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &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: + ExFreePool(DeviceNameU.Buffer); + if (!NT_SUCCESS(Status)) + return Status;
- if(status != STATUS_SUCCESS) - { - DPRINT("MOUCLASS: Could not connect to mouse port driver\n"); - DPRINT("Status: %x\n", status); - return status; - } + DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION)); + DeviceExtension->Common.IsClassDO = TRUE; + DeviceExtension->DriverExtension = DriverExtension; + DeviceExtension->PnpState = dsStopped; + KeInitializeSpinLock(&(DeviceExtension->SpinLock)); + DeviceExtension->ReadIsPending = FALSE; + DeviceExtension->InputCount = 0; + DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->MouseDataQueueSize * sizeof(MOUSE_INPUT_DATA)); + Fdo->Flags |= DO_POWER_PAGABLE; + Fdo->Flags |= DO_BUFFERED_IO; + Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- DeviceExtension->PortDeviceObject = PortDeviceObject; - DeviceExtension->PortData = ExAllocatePool(NonPagedPool, MOUSE_BUFFER_SIZE * sizeof(MOUSE_INPUT_DATA)); - DeviceExtension->InputCount = 0; - DeviceExtension->ReadIsPending = FALSE; - DeviceExtension->WorkItem = NULL; - KeInitializeSpinLock(&(DeviceExtension->SpinLock)); - DeviceExtension->PassiveCallbackQueued = FALSE; + /* FIXME: create registry entry in HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
- // Connect our callback to the port driver + if (ClassDO) + *ClassDO = Fdo;
- KeInitializeEvent(&event, NotificationEvent, FALSE); + return STATUS_SUCCESS; +}
- ClassInformation.ClassDeviceObject = ClassDeviceObject; - ClassInformation.ClassService = MouseClassCallBack; +static BOOLEAN +MouclassCallback( + IN PDEVICE_OBJECT ClassDeviceObject, + IN OUT PMOUSE_INPUT_DATA MouseDataStart, + IN PMOUSE_INPUT_DATA MouseDataEnd, + IN OUT PULONG ConsumedCount) +{ + PMOUCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension; + PIRP Irp = NULL; + KIRQL OldIrql; + PIO_STACK_LOCATION Stack; + ULONG InputCount = MouseDataEnd - MouseDataStart; + ULONG ReadSize;
- irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT, - PortDeviceObject, &ClassInformation, sizeof(CONNECT_DATA), NULL, 0, TRUE, &event, &ioStatus); + ASSERT(ClassDeviceExtension->Common.IsClassDO);
- status = IoCallDriver(DeviceExtension->PortDeviceObject, irp); + DPRINT("MouclassCallback()\n"); + /* A filter driver might have consumed all the data already; I'm + * not sure if they are supposed to move the packets when they + * consume them though. + */ + if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount) + { + Irp = ClassDeviceObject->CurrentIrp; + ClassDeviceObject->CurrentIrp = NULL; + Stack = IoGetCurrentIrpStackLocation(Irp);
- if (status == STATUS_PENDING) { - KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL); - } else { - ioStatus.Status = status; - } + /* A read request is waiting for input, so go straight to it */ + RtlMoveMemory( + Irp->AssociatedIrp.SystemBuffer, + MouseDataStart, + sizeof(MOUSE_INPUT_DATA));
- return ioStatus.Status; + /* Go to next packet and complete this request with STATUS_SUCCESS */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA); + Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA); + + ClassDeviceExtension->ReadIsPending = FALSE; + + /* Skip the packet we just sent away */ + MouseDataStart++; + (*ConsumedCount)++; + InputCount--; + } + + /* If we have data from the port driver and a higher service to send the data to */ + if (InputCount != 0) + { + KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql); + + if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->MouseDataQueueSize) + ReadSize = ClassDeviceExtension->DriverExtension->MouseDataQueueSize - ClassDeviceExtension->InputCount; + else + ReadSize = InputCount; + + /* + * FIXME: If we exceed the buffer, mouse data gets thrown away.. better + * solution? + */ + + /* + * Move the mouse input data from the port data queue to our class data + * queue. + */ + RtlMoveMemory( + ClassDeviceExtension->PortData, + (PCHAR)MouseDataStart, + sizeof(MOUSE_INPUT_DATA) * ReadSize); + + /* Move the pointer and counter up */ + ClassDeviceExtension->PortData += ReadSize; + ClassDeviceExtension->InputCount += ReadSize; + + KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql); + (*ConsumedCount) += ReadSize; + } + else + { + DPRINT("MouclassCallBack() entered, InputCount = %lu - DOING NOTHING\n", InputCount); + } + + if (Irp != NULL) + { + IoStartNextPacket(ClassDeviceObject, FALSE); + IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); + } + + DPRINT("Leaving MouclassCallback()\n"); + return TRUE; }
-static NTSTATUS STDCALL MouseClassDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) +/* Send IOCTL_INTERNAL_MOUSE_CONNECT to pointer port */ +static NTSTATUS +ConnectMousePortDriver( + IN PDEVICE_OBJECT PointerPortDO, + IN PDEVICE_OBJECT PointerClassDO) { - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); - NTSTATUS Status; + KEVENT Event; + PIRP Irp; + IO_STATUS_BLOCK IoStatus; + CONNECT_DATA ConnectData; + NTSTATUS Status;
- switch (Stack->MajorFunction) - { - case IRP_MJ_CREATE: - Status = ConnectMousePortDriver(MouclassDeviceObject); - break; + KeInitializeEvent(&Event, NotificationEvent, FALSE);
- case IRP_MJ_CLOSE: - Status = STATUS_SUCCESS; - break; + ConnectData.ClassDeviceObject = PointerClassDO; + ConnectData.ClassService = MouclassCallback;
- case IRP_MJ_READ: - if (Stack->Parameters.Read.Length < sizeof(MOUSE_INPUT_DATA)) - { - Status = STATUS_BUFFER_TOO_SMALL; - break; - } - IoMarkIrpPending(Irp); - IoStartPacket(DeviceObject, Irp, NULL, NULL); - return STATUS_PENDING; + Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT, + PointerPortDO, + &ConnectData, sizeof(CONNECT_DATA), + NULL, 0, + TRUE, &Event, &IoStatus);
- default: - DPRINT1("NOT IMPLEMENTED\n"); - Status = STATUS_NOT_IMPLEMENTED; - break; - } + Status = IoCallDriver(PointerPortDO, Irp);
- Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (Status == STATUS_PENDING) + KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); + else + IoStatus.Status = Status;
- return Status; + return IoStatus.Status; }
-static VOID STDCALL -MouseClassStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp) +static NTSTATUS NTAPI +MouclassAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT Pdo) { - PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; - PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); + PMOUCLASS_DRIVER_EXTENSION DriverExtension; + PDEVICE_OBJECT Fdo; + PMOUCLASS_DEVICE_EXTENSION DeviceExtension; + NTSTATUS Status;
- if (DeviceExtension->InputCount > 0) - { - KIRQL oldIrql; + DPRINT("MouclassAddDevice called. Pdo = 0x%p\n", Pdo);
- KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql); + DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
- RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, - DeviceExtension->PortData - DeviceExtension->InputCount, - sizeof(MOUSE_INPUT_DATA)); + /* Create new device object */ + Status = IoCreateDevice( + DriverObject, + sizeof(MOUCLASS_DEVICE_EXTENSION), + NULL, + Pdo->DeviceType, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &Fdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); + return Status; + }
- if (DeviceExtension->InputCount > 1) - { - RtlMoveMemory( - DeviceExtension->PortData - DeviceExtension->InputCount, - DeviceExtension->PortData - DeviceExtension->InputCount + 1, - (DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA)); - } - DeviceExtension->PortData--; - DeviceExtension->InputCount--; - DeviceExtension->ReadIsPending = FALSE; + DeviceExtension = (PMOUCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension; + RtlZeroMemory(DeviceExtension, sizeof(MOUCLASS_DEVICE_EXTENSION)); + DeviceExtension->Common.IsClassDO = FALSE; + DeviceExtension->PnpState = dsStopped; + Fdo->Flags |= DO_POWER_PAGABLE; + Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); + IoDeleteDevice(Fdo); + return Status; + } + Fdo->Flags |= DO_BUFFERED_IO; + Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- /* Go to next packet and complete this request with STATUS_SUCCESS */ - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA); - Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA); - IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); + if (DriverExtension->ConnectMultiplePorts) + Status = ConnectMousePortDriver(Fdo, DriverExtension->MainMouclassDeviceObject); + else + Status = ConnectMousePortDriver(Fdo, Fdo); + if (!NT_SUCCESS(Status)) + { + DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status); + /* FIXME: why can't I cleanup without error? */ + //IoDetachDevice(Fdo); + //IoDeleteDevice(Fdo); + return Status; + }
- IoStartNextPacket(DeviceObject, FALSE); - KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql); - } else { - DeviceExtension->ReadIsPending = TRUE; - } + /* Register GUID_DEVINTERFACE_MOUSE interface */ + Status = IoRegisterDeviceInterface( + Pdo, + &GUID_DEVINTERFACE_MOUSE, + NULL, + &DeviceExtension->MouseInterfaceName); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status); + return Status; + } + + return STATUS_SUCCESS; }
-NTSTATUS STDCALL -DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) +static VOID NTAPI +MouclassStartIo( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { - PDEVICE_OBJECT DeviceObject; - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\Device\Mouse"); - UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\??\Mouse"); - NTSTATUS Status; + PMOUCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
- DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassDispatch; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassDispatch; - DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassDispatch; - DriverObject->DriverStartIo = MouseClassStartIo; + ASSERT(DeviceExtension->Common.IsClassDO);
- Status = IoCreateDevice(DriverObject, - sizeof(DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_MOUSE, - 0, - TRUE, - &DeviceObject); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + if (DeviceExtension->InputCount > 0) + { + KIRQL oldIrql;
- DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO; + KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
- Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName); - if (!NT_SUCCESS(Status)) - { - IoDeleteDevice(DeviceObject); - return Status; - } + RtlMoveMemory( + Irp->AssociatedIrp.SystemBuffer, + DeviceExtension->PortData - DeviceExtension->InputCount, + sizeof(MOUSE_INPUT_DATA));
- MouclassDeviceObject = DeviceObject; + if (DeviceExtension->InputCount > 1) + { + RtlMoveMemory( + DeviceExtension->PortData - DeviceExtension->InputCount, + DeviceExtension->PortData - DeviceExtension->InputCount + 1, + (DeviceExtension->InputCount - 1) * sizeof(MOUSE_INPUT_DATA)); + } + DeviceExtension->PortData--; + DeviceExtension->InputCount--; + DeviceExtension->ReadIsPending = FALSE;
- return STATUS_SUCCESS; + /* Go to next packet and complete this request with STATUS_SUCCESS */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(MOUSE_INPUT_DATA); + Stack->Parameters.Read.Length = sizeof(MOUSE_INPUT_DATA); + IoCompleteRequest(Irp, IO_MOUSE_INCREMENT); + + IoStartNextPacket(DeviceObject, FALSE); + KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql); + } + else + { + DeviceExtension->ReadIsPending = TRUE; + } } + +static NTSTATUS +SearchForLegacyDrivers( + IN PMOUCLASS_DRIVER_EXTENSION DriverExtension) +{ + PDEVICE_OBJECT PortDeviceObject = NULL; + PFILE_OBJECT FileObject = NULL; + UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\Device\PointerClass0"); + NTSTATUS Status; + + /* FIXME: search for more than once legacy driver */ + + Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject); + if(Status != STATUS_SUCCESS) + { + DPRINT("Could not open old device object (Status 0x%08lx)\n", Status); + return Status; + } + + if (DriverExtension->ConnectMultiplePorts) + Status = ConnectMousePortDriver(PortDeviceObject, DriverExtension->MainMouclassDeviceObject); + else + { + /* What to do */ + KEBUGCHECK(0); + } + if (!NT_SUCCESS(Status)) + { + DPRINT("ConnectMousePortDriver() failed with status 0x%08lx\n", Status); + return Status; + } + return STATUS_SUCCESS; +} + +/* + * Standard DriverEntry method. + */ +NTSTATUS NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + PMOUCLASS_DRIVER_EXTENSION DriverExtension; + ULONG i; + NTSTATUS Status; + + Status = IoAllocateDriverObjectExtension( + DriverObject, + DriverObject, + sizeof(MOUCLASS_DRIVER_EXTENSION), + (PVOID*)&DriverExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT("IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status); + return Status; + } + RtlZeroMemory(DriverExtension, sizeof(MOUCLASS_DRIVER_EXTENSION)); + + Status = ReadRegistryEntries(RegistryPath, DriverExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT("ReadRegistryEntries() failed with status 0x%08lx\n", Status); + return Status; + } + + if (DriverExtension->ConnectMultiplePorts == 1) + { + Status = CreatePointerClassDeviceObject( + DriverObject, + &DriverExtension->MainMouclassDeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status); + return Status; + } + } + + DriverObject->DriverExtension->AddDevice = MouclassAddDevice; + DriverObject->DriverUnload = DriverUnload; + + for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) + DriverObject->MajorFunction[i] = IrpStub; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = MouclassCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouclassClose; + DriverObject->MajorFunction[IRP_MJ_READ] = MouclassRead; + DriverObject->DriverStartIo = MouclassStartIo; + + SearchForLegacyDrivers(DriverExtension); + + return STATUS_SUCCESS; +} _____
Modified: trunk/reactos/drivers/input/mouclass/mouclass.h --- trunk/reactos/drivers/input/mouclass/mouclass.h 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/drivers/input/mouclass/mouclass.h 2005-10-31 00:14:45 UTC (rev 18906) @@ -1,11 +1,65 @@
-#define MOUSE_BUFFER_SIZE 100 +#include <ntddk.h> +#include <kbdmou.h> +#include <ntddmou.h> +#include <stdio.h>
-typedef struct _DEVICE_EXTENSION { - PIO_WORKITEM WorkItem; - KSPIN_LOCK SpinLock; - BOOLEAN PassiveCallbackQueued; - BOOLEAN ReadIsPending; - ULONG InputCount; - PMOUSE_INPUT_DATA PortData; - PDEVICE_OBJECT PortDeviceObject; // FIXME: Expand this to handle multiple port drivers (make *PortDeviceObject) -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; +#if defined(__GNUC__) + 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 +} MOUCLASS_DEVICE_STATE; + +typedef struct _MOUCLASS_DRIVER_EXTENSION +{ + /* Registry settings */ + ULONG ConnectMultiplePorts; + ULONG MouseDataQueueSize; + UNICODE_STRING PointerDeviceBaseName; + + PDEVICE_OBJECT MainMouclassDeviceObject; +} MOUCLASS_DRIVER_EXTENSION, *PMOUCLASS_DRIVER_EXTENSION; + +typedef struct _COMMON_DEVICE_EXTENSION +{ + BOOLEAN IsClassDO; +} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; + +typedef struct _MOUPORT_DEVICE_EXTENSION +{ + COMMON_DEVICE_EXTENSION Common; +} MOUPORT_DEVICE_EXTENSION, *PMOUPORT_DEVICE_EXTENSION; + +typedef struct _MOUCLASS_DEVICE_EXTENSION +{ + COMMON_DEVICE_EXTENSION Common; + + MOUCLASS_DEVICE_STATE PnpState; + PMOUCLASS_DRIVER_EXTENSION DriverExtension; + PDEVICE_OBJECT LowerDevice; + UNICODE_STRING MouseInterfaceName; + + KSPIN_LOCK SpinLock; + BOOLEAN ReadIsPending; + ULONG InputCount; + PMOUSE_INPUT_DATA PortData; +} MOUCLASS_DEVICE_EXTENSION, *PMOUCLASS_DEVICE_EXTENSION; + +/* misc.c */ + +NTSTATUS NTAPI +ForwardIrpAndForget( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); _____
Modified: trunk/reactos/drivers/input/mouclass/mouclass.xml --- trunk/reactos/drivers/input/mouclass/mouclass.xml 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/drivers/input/mouclass/mouclass.xml 2005-10-31 00:14:45 UTC (rev 18906) @@ -3,6 +3,7 @@
<define name="__USE_W32API" /> <library>ntoskrnl</library> <library>hal</library> + <file>misc.c</file> <file>mouclass.c</file> <file>mouclass.rc</file> </module> _____
Modified: trunk/reactos/subsys/win32k/ntuser/input.c --- trunk/reactos/subsys/win32k/ntuser/input.c 2005-10-31 00:10:32 UTC (rev 18905) +++ trunk/reactos/subsys/win32k/ntuser/input.c 2005-10-31 00:14:45 UTC (rev 18906) @@ -151,7 +151,7 @@
VOID STDCALL MouseThreadMain(PVOID StartContext) { [truncated at 1000 lines; 59 more skipped]