Send IOCTL_* to the port device objects. Keyboard LEDs should now work
authorHervé Poussineau <hpoussin@reactos.org>
Fri, 24 Feb 2006 13:38:14 +0000 (13:38 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Fri, 24 Feb 2006 13:38:14 +0000 (13:38 +0000)
Simplify code in SearchForLegacyDrivers

svn path=/trunk/; revision=21188

reactos/drivers/input/kbdclass/kbdclass.c
reactos/drivers/input/kbdclass/kbdclass.h
reactos/drivers/input/mouclass/mouclass.c
reactos/drivers/input/mouclass/mouclass.h

index 716c96e..7308264 100644 (file)
@@ -96,7 +96,7 @@ ClassDeviceControl(
        IN PIRP Irp)
 {
        PCLASS_DEVICE_EXTENSION DeviceExtension;
-       NTSTATUS Status;
+       NTSTATUS Status = Irp->IoStatus.Status;
 
        DPRINT("IRP_MJ_DEVICE_CONTROL\n");
 
@@ -111,15 +111,44 @@ ClassDeviceControl(
                case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
                case IOCTL_KEYBOARD_QUERY_INDICATORS:
                case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
+               {
+                       /* FIXME: We hope that all devices will return the same result.
+                        * Ask only the first one */
+                       PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
+                       if (Head->Flink != Head)
+                       {
+                               /* We have at least one keyboard */
+                               PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
+                               IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+                               IoSkipCurrentIrpStackLocation(Irp);
+                               return IoCallDriver(DevExt->DeviceObject, Irp);
+                       }
+                       break;
+               }
                case IOCTL_KEYBOARD_SET_INDICATORS:
                case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */
-                       /* FIXME: send it to all associated Port devices */
-                       Status = STATUS_NOT_SUPPORTED;
+               {
+                       /* Send it to all associated Port devices */
+                       PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
+                       PLIST_ENTRY Entry = Head->Flink;
+                       Status = STATUS_SUCCESS;
+                       while (Entry != Head)
+                       {
+                               PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry);
+                               NTSTATUS IntermediateStatus;
+
+                               IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+                               IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp);
+                               if (!NT_SUCCESS(IntermediateStatus))
+                                       Status = IntermediateStatus;
+                               Entry = Entry->Flink;
+                       }
                        break;
+               }
                default:
                        DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
                                IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
-                       Status = STATUS_NOT_SUPPORTED;
+                       break;
        }
 
        Irp->IoStatus.Status = Status;
@@ -141,6 +170,7 @@ IrpStub(
                /* Forward some IRPs to lower device */
                switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
                {
+                       case IRP_MJ_PNP:
                        case IRP_MJ_INTERNAL_DEVICE_CONTROL:
                                return ForwardIrpAndForget(DeviceObject, Irp);
                        default:
@@ -325,7 +355,9 @@ cleanup:
        RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
        DeviceExtension->Common.IsClassDO = TRUE;
        DeviceExtension->DriverExtension = DriverExtension;
-       KeInitializeSpinLock(&(DeviceExtension->SpinLock));
+       InitializeListHead(&DeviceExtension->ListHead);
+       KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
+       KeInitializeSpinLock(&DeviceExtension->SpinLock);
        DeviceExtension->ReadIsPending = FALSE;
        DeviceExtension->InputCount = 0;
        DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA));
@@ -478,7 +510,20 @@ ConnectPortDriver(
                IoStatus.Status = Status;
 
        if (NT_SUCCESS(IoStatus.Status))
+       {
                ObReferenceObject(PortDO);
+               ExInterlockedInsertTailList(
+                       &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead,
+                       &((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry,
+                       &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock);
+               if (ClassDO->StackSize <= PortDO->StackSize)
+               {
+                       /* Increase the stack size, in case we have to
+                        * forward some IRPs to the port device object
+                        */
+                       ClassDO->StackSize = PortDO->StackSize + 1;
+               }
+       }
 
        return IoStatus.Status;
 }
@@ -520,6 +565,7 @@ ClassAddDevice(
        DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
        RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
        DeviceExtension->Common.IsClassDO = FALSE;
+       DeviceExtension->DeviceObject = Fdo;
        DeviceExtension->PnpState = dsStopped;
        Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
        if (!NT_SUCCESS(Status))
@@ -541,8 +587,8 @@ ClassAddDevice(
        {
                DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
                IoDetachDevice(DeviceExtension->LowerDevice);
-               /* FIXME: why can't I cleanup without error? */
-               //IoDeleteDevice(Fdo);
+               ObDereferenceObject(Fdo);
+               IoDeleteDevice(Fdo);
                return Status;
        }
        Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
@@ -698,35 +744,14 @@ SearchForLegacyDrivers(
                if (!NT_SUCCESS(Status))
                {
                        DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
+                       continue;
                }
 
-               /* Connect the port device object */
-               if (DriverExtension->ConnectMultiplePorts)
-               {
-                       Status = ConnectPortDriver(PortDeviceObject, DriverExtension->MainClassDeviceObject);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
-                       }
-               }
-               else
+               Status = ClassAddDevice(DriverObject, PortDeviceObject);
+               if (!NT_SUCCESS(Status))
                {
-                       PDEVICE_OBJECT ClassDO;
-                       Status = CreateClassDeviceObject(DriverObject, &ClassDO);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
-                               continue;
-                       }
-                       Status = ConnectPortDriver(PortDeviceObject, ClassDO);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
-                               IoDeleteDevice(ClassDO);
-                       }
+                       /* FIXME: Log the error */
+                       DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
                }
        }
        if (Status == STATUS_NO_MORE_ENTRIES)
@@ -806,6 +831,7 @@ DriverEntry(
        DriverObject->MajorFunction[IRP_MJ_CLEANUP]        = ClassCleanup;
        DriverObject->MajorFunction[IRP_MJ_READ]           = ClassRead;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
+       DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
        DriverObject->DriverStartIo                        = ClassStartIo;
 
        return STATUS_SUCCESS;
index 4428076..b0fc210 100644 (file)
@@ -35,6 +35,8 @@ typedef struct _PORT_DEVICE_EXTENSION
 {
        COMMON_DEVICE_EXTENSION Common;
 
+       LIST_ENTRY ListEntry;
+       PDEVICE_OBJECT DeviceObject;
        PORT_DEVICE_STATE PnpState;
        PDEVICE_OBJECT LowerDevice;
        UNICODE_STRING InterfaceName;
@@ -46,6 +48,8 @@ typedef struct _CLASS_DEVICE_EXTENSION
 
        PCLASS_DRIVER_EXTENSION DriverExtension;
 
+       LIST_ENTRY ListHead;
+       KSPIN_LOCK ListSpinLock;
        KSPIN_LOCK SpinLock;
        BOOLEAN ReadIsPending;
        ULONG InputCount;
@@ -54,6 +58,11 @@ typedef struct _CLASS_DEVICE_EXTENSION
 
 /* misc.c */
 
+NTSTATUS
+ForwardIrpAndWait(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
 NTSTATUS NTAPI
 ForwardIrpAndForget(
        IN PDEVICE_OBJECT DeviceObject,
index a50b103..4441468 100644 (file)
@@ -96,7 +96,7 @@ ClassDeviceControl(
        IN PIRP Irp)
 {
        PCLASS_DEVICE_EXTENSION DeviceExtension;
-       NTSTATUS Status;
+       NTSTATUS Status = Irp->IoStatus.Status;
 
        DPRINT("IRP_MJ_DEVICE_CONTROL\n");
 
@@ -108,13 +108,24 @@ ClassDeviceControl(
        switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
        {
                case IOCTL_MOUSE_QUERY_ATTRIBUTES:
-                       /* FIXME */
-                       Status = STATUS_NOT_SUPPORTED;
+               {
+                       /* FIXME: We hope that all devices will return the same result.
+                        * Ask only the first one */
+                       PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
+                       if (Head->Flink != Head)
+                       {
+                               /* We have at least one keyboard */
+                               PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
+                               IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+                               IoSkipCurrentIrpStackLocation(Irp);
+                               return IoCallDriver(DevExt->DeviceObject, Irp);
+                       }
                        break;
+               }
                default:
                        DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
                                IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
-                       Status = STATUS_NOT_SUPPORTED;
+                       break;
        }
 
        Irp->IoStatus.Status = Status;
@@ -320,7 +331,9 @@ cleanup:
        RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
        DeviceExtension->Common.IsClassDO = TRUE;
        DeviceExtension->DriverExtension = DriverExtension;
-       KeInitializeSpinLock(&(DeviceExtension->SpinLock));
+       InitializeListHead(&DeviceExtension->ListHead);
+       KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
+       KeInitializeSpinLock(&DeviceExtension->SpinLock);
        DeviceExtension->ReadIsPending = FALSE;
        DeviceExtension->InputCount = 0;
        DeviceExtension->PortData = ExAllocatePool(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(MOUSE_INPUT_DATA));
@@ -469,7 +482,20 @@ ConnectPortDriver(
                IoStatus.Status = Status;
 
        if (NT_SUCCESS(IoStatus.Status))
+       {
                ObReferenceObject(PortDO);
+               ExInterlockedInsertTailList(
+                       &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead,
+                       &((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry,
+                       &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock);
+               if (ClassDO->StackSize <= PortDO->StackSize)
+               {
+                       /* Increase the stack size, in case we have to
+                        * forward some IRPs to the port device object
+                        */
+                       ClassDO->StackSize = PortDO->StackSize + 1;
+               }
+       }
 
        return IoStatus.Status;
 }
@@ -511,6 +537,7 @@ ClassAddDevice(
        DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
        RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
        DeviceExtension->Common.IsClassDO = FALSE;
+       DeviceExtension->DeviceObject = Fdo;
        DeviceExtension->PnpState = dsStopped;
        Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
        if (!NT_SUCCESS(Status))
@@ -532,8 +559,8 @@ ClassAddDevice(
        {
                DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
                IoDetachDevice(DeviceExtension->LowerDevice);
-               /* FIXME: why can't I cleanup without error? */
-               //IoDeleteDevice(Fdo);
+               ObDereferenceObject(Fdo);
+               IoDeleteDevice(Fdo);
                return Status;
        }
        Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
@@ -689,35 +716,14 @@ SearchForLegacyDrivers(
                if (!NT_SUCCESS(Status))
                {
                        DPRINT("IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", Status);
+                       continue;
                }
 
-               /* Connect the port device object */
-               if (DriverExtension->ConnectMultiplePorts)
-               {
-                       Status = ConnectPortDriver(PortDeviceObject, DriverExtension->MainClassDeviceObject);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
-                       }
-               }
-               else
+               Status = ClassAddDevice(DriverObject, PortDeviceObject);
+               if (!NT_SUCCESS(Status))
                {
-                       PDEVICE_OBJECT ClassDO;
-                       Status = CreateClassDeviceObject(DriverObject, &ClassDO);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("CreatePointerClassDeviceObject() failed with status 0x%08lx\n", Status);
-                               continue;
-                       }
-                       Status = ConnectPortDriver(PortDeviceObject, ClassDO);
-                       if (!NT_SUCCESS(Status))
-                       {
-                               /* FIXME: Log the error */
-                               DPRINT("ConnectPortDriver() failed with status 0x%08lx\n", Status);
-                               IoDeleteDevice(ClassDO);
-                       }
+                       /* FIXME: Log the error */
+                       DPRINT("ClassAddDevice() failed with status 0x%08lx\n", Status);
                }
        }
        if (Status == STATUS_NO_MORE_ENTRIES)
@@ -797,6 +803,7 @@ DriverEntry(
        DriverObject->MajorFunction[IRP_MJ_CLEANUP]        = ClassCleanup;
        DriverObject->MajorFunction[IRP_MJ_READ]           = ClassRead;
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
+       DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
        DriverObject->DriverStartIo                        = ClassStartIo;
 
        return STATUS_SUCCESS;
index dd76369..c9e35eb 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdio.h>
 
 #define MAX_PATH 260
+
 typedef enum
 {
        dsStopped,
@@ -34,6 +35,8 @@ typedef struct _PORT_DEVICE_EXTENSION
 {
        COMMON_DEVICE_EXTENSION Common;
 
+       LIST_ENTRY ListEntry;
+       PDEVICE_OBJECT DeviceObject;
        PORT_DEVICE_STATE PnpState;
        PDEVICE_OBJECT LowerDevice;
        UNICODE_STRING InterfaceName;
@@ -45,6 +48,8 @@ typedef struct _CLASS_DEVICE_EXTENSION
 
        PCLASS_DRIVER_EXTENSION DriverExtension;
 
+       LIST_ENTRY ListHead;
+       KSPIN_LOCK ListSpinLock;
        KSPIN_LOCK SpinLock;
        BOOLEAN ReadIsPending;
        ULONG InputCount;
@@ -53,6 +58,11 @@ typedef struct _CLASS_DEVICE_EXTENSION
 
 /* misc.c */
 
+NTSTATUS
+ForwardIrpAndWait(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
 NTSTATUS NTAPI
 ForwardIrpAndForget(
        IN PDEVICE_OBJECT DeviceObject,