[ros-diffs] [cgutman] 56128: [VIDEOPRT] - Fix broken VIDEO_PORT_GET_DEVICE_EXTENSION macro - Add support for child devices (monitors only for now) - Monitors now show up in device manager ("Plug and Play Monit...

cgutman at svn.reactos.org cgutman at svn.reactos.org
Mon Mar 12 03:29:37 UTC 2012


Author: cgutman
Date: Mon Mar 12 03:29:36 2012
New Revision: 56128

URL: http://svn.reactos.org/svn/reactos?rev=56128&view=rev
Log:
[VIDEOPRT]
- Fix broken VIDEO_PORT_GET_DEVICE_EXTENSION macro
- Add support for child devices (monitors only for now)
- Monitors now show up in device manager ("Plug and Play Monitor" shows up if EDID data is reported, otherwise "Default Monitor" is displayed) 

Added:
    trunk/reactos/drivers/video/videoprt/child.c   (with props)
Modified:
    trunk/reactos/drivers/video/videoprt/CMakeLists.txt
    trunk/reactos/drivers/video/videoprt/dispatch.c
    trunk/reactos/drivers/video/videoprt/videoprt.c
    trunk/reactos/drivers/video/videoprt/videoprt.h

Modified: trunk/reactos/drivers/video/videoprt/CMakeLists.txt
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/video/videoprt/CMakeLists.txt?rev=56128&r1=56127&r2=56128&view=diff
==============================================================================
--- trunk/reactos/drivers/video/videoprt/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/drivers/video/videoprt/CMakeLists.txt [iso-8859-1] Mon Mar 12 03:29:36 2012
@@ -7,6 +7,7 @@
 
 list(APPEND SOURCE
     agp.c
+    child.c
     ddc.c
     dispatch.c
     dma.c

Added: trunk/reactos/drivers/video/videoprt/child.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/video/videoprt/child.c?rev=56128&view=auto
==============================================================================
--- trunk/reactos/drivers/video/videoprt/child.c (added)
+++ trunk/reactos/drivers/video/videoprt/child.c [iso-8859-1] Mon Mar 12 03:29:36 2012
@@ -1,0 +1,396 @@
+/*
+ * VideoPort driver
+ *
+ * Copyright (C) 2012 ReactOS Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "videoprt.h"
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+BOOLEAN
+NTAPI
+IntVideoPortGetMonitorId(
+    IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
+    IN OUT PWCHAR Buffer)
+{
+    USHORT Manufacturer, Model;
+    UNICODE_STRING UnicodeModelStr;
+
+    /* This must be valid to call this function */
+    ASSERT(ChildExtension->EdidValid);
+
+    /* 3 letters 5-bit ANSI manufacturer code (big endian) */
+    Manufacturer = *(PUSHORT)(&ChildExtension->ChildDescriptor[8]);
+
+    /* Letters encoded as A=1 to Z=26 */
+    Buffer[0] = (WCHAR)((Manufacturer & 0x7C00) + 'A' - 1);
+    Buffer[1] = (WCHAR)((Manufacturer & 0x03E0) + 'A' - 1);
+    Buffer[2] = (WCHAR)((Manufacturer & 0x001F) + 'A' - 1);
+
+    /* Model number (16-bit little endian) */
+    Model = *(PUSHORT)(&ChildExtension->ChildDescriptor[10]);
+
+    /* Use Rtl helper for conversion */
+    UnicodeModelStr.Buffer = &Buffer[3];
+    UnicodeModelStr.Length = 0;
+    UnicodeModelStr.MaximumLength = 4 * sizeof(WCHAR);
+    RtlIntegerToUnicodeString(Model, 16, &UnicodeModelStr);
+
+    /* Terminate it */
+    Buffer[7] = UNICODE_NULL;
+
+    /* And we're done */
+    return TRUE;
+}
+
+NTSTATUS NTAPI
+IntVideoPortChildQueryId(
+    IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
+{
+    PWCHAR Buffer = NULL, StaticBuffer;
+    UNICODE_STRING UnicodeStr;
+    ULONG Length;
+    
+    switch (IrpSp->Parameters.QueryId.IdType)
+    {
+        case BusQueryDeviceID:
+            switch (ChildExtension->ChildType)
+            {
+                case Monitor:
+                    if (ChildExtension->EdidValid)
+                    {
+                        StaticBuffer = L"DISPLAY\\";
+                        Length = 8 * sizeof(WCHAR);
+                        Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 8) * sizeof(WCHAR));
+                        if (!Buffer) return STATUS_NO_MEMORY;
+
+                        /* Write the static portion */
+                        RtlCopyMemory(Buffer, StaticBuffer, wcslen(StaticBuffer) * sizeof(WCHAR));
+
+                        /* Add the dynamic portion */
+                        IntVideoPortGetMonitorId(ChildExtension,
+                                                 &Buffer[wcslen(StaticBuffer)]);
+                    }
+                    else
+                    {
+                        StaticBuffer = L"DISPLAY\\Default_Monitor";
+                        Length = wcslen(StaticBuffer) * sizeof(WCHAR);
+                        Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+                        if (!Buffer) return STATUS_NO_MEMORY;
+
+                        /* Copy the default id */
+                        RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+                    }
+                    break;
+                default:
+                    ASSERT(FALSE);
+                    break;
+            }
+            break;
+        case BusQueryInstanceID:
+            Buffer = ExAllocatePool(PagedPool, 5 * sizeof(WCHAR));
+            if (!Buffer) return STATUS_NO_MEMORY;
+
+            UnicodeStr.Buffer = Buffer;
+            UnicodeStr.Length = 0;
+            UnicodeStr.MaximumLength = 4 * sizeof(WCHAR);
+            RtlIntegerToUnicodeString(ChildExtension->ChildId, 16, &UnicodeStr);
+            break;
+        case BusQueryHardwareIDs:
+            switch (ChildExtension->ChildType)
+            {
+                case Monitor:
+                    if (ChildExtension->EdidValid)
+                    {
+                        StaticBuffer = L"MONITOR\\";
+                        Length = 8 * sizeof(WCHAR);
+                        Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 9) * sizeof(WCHAR));
+                        if (!Buffer) return STATUS_NO_MEMORY;
+
+                        /* Write the static portion */
+                        RtlCopyMemory(Buffer, StaticBuffer, wcslen(StaticBuffer) * sizeof(WCHAR));
+
+                        /* Add the dynamic portion */
+                        IntVideoPortGetMonitorId(ChildExtension,
+                                                 &Buffer[wcslen(StaticBuffer)]);
+
+                        /* Add the second null termination char */
+                        Buffer[wcslen(StaticBuffer) + 8] = UNICODE_NULL;
+                    }
+                    else
+                    {
+                        StaticBuffer = L"MONITOR\\Default_Monitor";
+                        Length = wcslen(StaticBuffer) * sizeof(WCHAR);
+                        Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 2) * sizeof(WCHAR));
+                        if (!Buffer) return STATUS_NO_MEMORY;
+
+                        /* Copy the default id */
+                        RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+
+                        /* Add the second null terminator */
+                        Buffer[wcslen(StaticBuffer) + 1] = UNICODE_NULL;
+                    }
+                    break;
+                default:
+                    ASSERT(FALSE);
+                    break;
+            }
+            break;
+        case BusQueryCompatibleIDs:
+            switch (ChildExtension->ChildType)
+            {
+                case Monitor:
+                    if (ChildExtension->EdidValid)
+                    {
+                        StaticBuffer = L"*PNP09FF";
+                        Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 2) * sizeof(WCHAR));
+                        if (!Buffer) return STATUS_NO_MEMORY;
+
+                        RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+
+                        Buffer[wcslen(StaticBuffer)+1] = UNICODE_NULL;
+                    }
+                    else
+                    {
+                        /* No PNP ID for non-PnP monitors */
+                        return Irp->IoStatus.Status;
+                    }
+                    break;
+                default:
+                    ASSERT(FALSE);
+                    break;
+            }
+            break;
+        default:
+            return Irp->IoStatus.Status;
+    }
+
+    INFO_(VIDEOPRT, "Reporting ID: %S\n", Buffer);
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+IntVideoPortChildQueryText(
+    IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
+{
+    PWCHAR Buffer, StaticBuffer;
+
+    if (IrpSp->Parameters.QueryDeviceText.DeviceTextType != DeviceTextDescription)
+        return Irp->IoStatus.Status;
+
+    switch (ChildExtension->ChildType)
+    {
+        case Monitor:
+            /* FIXME: We can return a better description I think */
+            StaticBuffer = L"Monitor";
+            break;
+
+        case VideoChip:
+            /* FIXME: No idea what we return here */
+            StaticBuffer = L"Video chip";
+            break;
+
+        default: /* Other */
+            StaticBuffer = L"Other device";
+            break;
+    }
+
+    Buffer = ExAllocatePool(PagedPool, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+    if (!Buffer) return STATUS_NO_MEMORY;
+
+    RtlCopyMemory(Buffer, StaticBuffer, (wcslen(StaticBuffer) + 1) * sizeof(WCHAR));
+
+    INFO_(VIDEOPRT, "Reporting description: %S\n", Buffer);
+    Irp->IoStatus.Information = (ULONG_PTR)Buffer;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+IntVideoPortChildQueryRelations(
+    IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
+{
+    PDEVICE_RELATIONS DeviceRelations;
+
+    if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+    {
+        WARN_(VIDEOPRT, "Unsupported device relations type\n");
+        return Irp->IoStatus.Status;
+    }
+
+    DeviceRelations = ExAllocatePool(NonPagedPool, sizeof(DEVICE_RELATIONS));
+    if (!DeviceRelations) return STATUS_NO_MEMORY;
+
+    DeviceRelations->Count = 1;
+    DeviceRelations->Objects[0] = ChildExtension->PhysicalDeviceObject;
+
+    ObReferenceObject(DeviceRelations->Objects[0]);
+
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+IntVideoPortChildQueryCapabilities(
+    IN PVIDEO_PORT_CHILD_EXTENSION ChildExtension,
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IrpSp)
+{
+    PDEVICE_CAPABILITIES DeviceCaps = IrpSp->Parameters.DeviceCapabilities.Capabilities;
+    ULONG i;
+
+    /* Set some values */
+    DeviceCaps->LockSupported = FALSE;
+    DeviceCaps->EjectSupported = FALSE;
+    DeviceCaps->DockDevice = FALSE;
+    DeviceCaps->UniqueID = FALSE;
+    DeviceCaps->RawDeviceOK = FALSE;
+    DeviceCaps->WakeFromD0 = FALSE;
+    DeviceCaps->WakeFromD1 = FALSE;
+    DeviceCaps->WakeFromD2 = FALSE;
+    DeviceCaps->WakeFromD3 = FALSE;
+    DeviceCaps->HardwareDisabled = FALSE;
+    DeviceCaps->NoDisplayInUI = FALSE;
+
+    /* Address and UI number are set by default */
+
+    DeviceCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;
+    for (i = 1; i < POWER_SYSTEM_MAXIMUM; i++)
+    {
+        DeviceCaps->DeviceState[i] = PowerDeviceD3;
+    }
+
+    DeviceCaps->SystemWake = PowerSystemUnspecified;
+    DeviceCaps->DeviceWake = PowerDeviceUnspecified;
+
+    /* FIXME: Device power states */
+    DeviceCaps->DeviceD1 = FALSE;
+    DeviceCaps->DeviceD2 = FALSE;
+    DeviceCaps->D1Latency = 0;
+    DeviceCaps->D2Latency = 0;
+    DeviceCaps->D3Latency = 0; 
+
+    switch (ChildExtension->ChildType)
+    {
+        case VideoChip:
+            /* FIXME: Copy capabilities from parent */
+            ASSERT(FALSE);
+            break;
+
+        case NonPrimaryChip: /* Reserved */
+            ASSERT(FALSE);
+            break;
+
+        case Monitor:
+            DeviceCaps->SilentInstall = TRUE;
+            DeviceCaps->Removable = TRUE;
+            DeviceCaps->SurpriseRemovalOK = TRUE;
+            break;
+
+        default: /* Other */
+            DeviceCaps->SilentInstall = FALSE;
+            DeviceCaps->Removable = FALSE;
+            DeviceCaps->SurpriseRemovalOK = FALSE;
+            break;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+IntVideoPortDispatchPdoPnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IrpSp;
+    NTSTATUS Status = Irp->IoStatus.Status;
+
+    IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+    switch (IrpSp->MinorFunction)
+    {
+        case IRP_MN_START_DEVICE:
+        case IRP_MN_STOP_DEVICE:
+            /* Nothing to do */
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_QUERY_RESOURCES:
+        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+            /* None (keep old status) */
+            break;
+
+        case IRP_MN_QUERY_ID:
+            /* Call our helper */
+            Status = IntVideoPortChildQueryId(DeviceObject->DeviceExtension,
+                                              Irp,
+                                              IrpSp);
+            break;
+
+        case IRP_MN_QUERY_CAPABILITIES:
+            /* Call our helper */
+            Status = IntVideoPortChildQueryCapabilities(DeviceObject->DeviceExtension,
+                                                        Irp,
+                                                        IrpSp);
+            break;
+
+        case IRP_MN_SURPRISE_REMOVAL:
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+            Status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MN_REMOVE_DEVICE:
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            IoDeleteDevice(DeviceObject);
+            return STATUS_SUCCESS;
+
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+            /* Call our helper */
+            Status = IntVideoPortChildQueryRelations(DeviceObject->DeviceExtension,
+                                                     Irp,
+                                                     IrpSp);
+            break;
+
+        case IRP_MN_QUERY_DEVICE_TEXT:
+            /* Call our helper */
+            Status = IntVideoPortChildQueryText(DeviceObject->DeviceExtension,
+                                                Irp,
+                                                IrpSp);
+            break;
+
+        default:
+            break;
+    }
+
+    Irp->IoStatus.Status = Status;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return Status;
+}

Propchange: trunk/reactos/drivers/video/videoprt/child.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/drivers/video/videoprt/dispatch.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/video/videoprt/dispatch.c?rev=56128&r1=56127&r2=56128&view=diff
==============================================================================
--- trunk/reactos/drivers/video/videoprt/dispatch.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/video/videoprt/dispatch.c [iso-8859-1] Mon Mar 12 03:29:36 2012
@@ -410,6 +410,51 @@
   return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
+NTSTATUS
+NTAPI
+IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+    PDEVICE_RELATIONS DeviceRelations;
+    PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+    PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
+    ULONG i;
+    PLIST_ENTRY CurrentEntry;
+
+    /* Count the children */
+    i = 0;
+    CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
+    while (CurrentEntry != &DeviceExtension->ChildDeviceList)
+    {
+        i++;
+        CurrentEntry = CurrentEntry->Flink;
+    }
+
+    if (i == 0)
+        return Irp->IoStatus.Status;
+
+    DeviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
+    if (!DeviceRelations) return STATUS_NO_MEMORY;
+
+    DeviceRelations->Count = i;
+
+    /* Add the children */
+    i = 0;
+    CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
+    while (CurrentEntry != &DeviceExtension->ChildDeviceList)
+    {
+        ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
+
+        DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
+
+        i++;
+        CurrentEntry = CurrentEntry->Flink;
+    }
+
+    INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
+    Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+    return STATUS_SUCCESS;
+}
 
 NTSTATUS
 NTAPI
@@ -433,14 +478,14 @@
    return Status;
 }
 
-
-NTSTATUS NTAPI
-IntVideoPortDispatchPnp(
+NTSTATUS NTAPI
+IntVideoPortDispatchFdoPnp(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
 {
    PIO_STACK_LOCATION IrpSp;
    NTSTATUS Status;
+   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
 
    IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
@@ -464,6 +509,20 @@
          IoCompleteRequest(Irp, IO_NO_INCREMENT);
          break;
 
+       case IRP_MN_QUERY_DEVICE_RELATIONS:
+           if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
+           {
+               IoSkipCurrentIrpStackLocation(Irp);
+               Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
+           }
+           else
+           {
+               Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
+               Irp->IoStatus.Status = Status;
+               IoCompleteRequest(Irp, IO_NO_INCREMENT);
+           }
+           break;
+
       case IRP_MN_REMOVE_DEVICE:
       case IRP_MN_QUERY_REMOVE_DEVICE:
       case IRP_MN_CANCEL_REMOVE_DEVICE:
@@ -496,6 +555,19 @@
 }
 
 NTSTATUS NTAPI
+IntVideoPortDispatchPnp(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
+    
+    if (CommonExtension->Fdo)
+        return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
+    else
+        return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
+}
+
+NTSTATUS NTAPI
 IntVideoPortDispatchCleanup(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)

Modified: trunk/reactos/drivers/video/videoprt/videoprt.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/video/videoprt/videoprt.c?rev=56128&r1=56127&r2=56128&view=diff
==============================================================================
--- trunk/reactos/drivers/video/videoprt/videoprt.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/video/videoprt/videoprt.c [iso-8859-1] Mon Mar 12 03:29:36 2012
@@ -250,11 +250,14 @@
     */
 
    DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension);
+   DeviceExtension->Common.Fdo = TRUE;
    DeviceExtension->DeviceNumber = DeviceNumber;
    DeviceExtension->DriverObject = DriverObject;
    DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
    DeviceExtension->FunctionalDeviceObject = *DeviceObject;
    DeviceExtension->DriverExtension = DriverExtension;
+
+   InitializeListHead(&DeviceExtension->ChildDeviceList);
 
    /*
     * Get the registry path associated with this driver.
@@ -1097,14 +1100,14 @@
    PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
    ULONG Status;
    VIDEO_CHILD_ENUM_INFO ChildEnumInfo;
-   VIDEO_CHILD_TYPE ChildType;
    BOOLEAN bHaveLastMonitorID = FALSE;
    UCHAR LastMonitorID[10];
-   UCHAR ChildDescriptor[256];
-   ULONG ChildId;
    ULONG Unused;
    UINT i;
-
+   PDEVICE_OBJECT ChildDeviceObject;
+   PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
+
+   INFO_(VIDEOPRT, "Starting child device probe\n");
    DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
    if (DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor == NULL)
    {
@@ -1112,95 +1115,144 @@
       return NO_ERROR;
    }
 
-   /* Setup the ChildEnumInfo */
-   ChildEnumInfo.Size = sizeof (ChildEnumInfo);
-   ChildEnumInfo.ChildDescriptorSize = sizeof (ChildDescriptor);
-   ChildEnumInfo.ACPIHwId = 0;
-   ChildEnumInfo.ChildHwDeviceExtension = NULL; /* FIXME: must be set to
-                                                   ChildHwDeviceExtension... */
+   if (!IsListEmpty(&DeviceExtension->ChildDeviceList))
+   {
+       ERR_(VIDEOPRT, "FIXME: Support calling VideoPortEnumerateChildren again!\n");
+       return NO_ERROR;
+   }
 
    /* Enumerate the children */
    for (i = 1; ; i++)
    {
-      ChildEnumInfo.ChildIndex = i;
-      RtlZeroMemory(ChildDescriptor, sizeof(ChildDescriptor));
+       Status = IoCreateDevice(DeviceExtension->DriverObject,
+                               sizeof(VIDEO_PORT_CHILD_EXTENSION) +
+                               DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize,
+                               NULL,
+                               FILE_DEVICE_CONTROLLER,
+                               FILE_DEVICE_SECURE_OPEN,
+                               FALSE,
+                               &ChildDeviceObject);
+       if (!NT_SUCCESS(Status))
+           return Status;
+
+       ChildExtension = ChildDeviceObject->DeviceExtension;
+
+       RtlZeroMemory(ChildExtension, sizeof(VIDEO_PORT_CHILD_EXTENSION) +
+                     DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize);
+
+       ChildExtension->Common.Fdo = FALSE;
+       ChildExtension->ChildId = i;
+       ChildExtension->PhysicalDeviceObject = ChildDeviceObject;
+       ChildExtension->DriverObject = DeviceExtension->DriverObject;
+
+       /* Setup the ChildEnumInfo */
+       ChildEnumInfo.Size = sizeof(ChildEnumInfo);
+       ChildEnumInfo.ChildDescriptorSize = sizeof(ChildExtension->ChildDescriptor);
+       ChildEnumInfo.ACPIHwId = 0;
+
+       if (DeviceExtension->DriverExtension->InitializationData.HwChildDeviceExtensionSize)
+           ChildEnumInfo.ChildHwDeviceExtension = VIDEO_PORT_GET_CHILD_EXTENSION(ChildExtension);
+       else
+           ChildEnumInfo.ChildHwDeviceExtension = NULL;
+
+       ChildEnumInfo.ChildIndex = ChildExtension->ChildId;
+
+      INFO_(VIDEOPRT, "Probing child: %d\n", ChildEnumInfo.ChildIndex);
       Status = DeviceExtension->DriverExtension->InitializationData.HwGetVideoChildDescriptor(
                   HwDeviceExtension,
                   &ChildEnumInfo,
-                  &ChildType,
-                  ChildDescriptor,
-                  &ChildId,
+                  &ChildExtension->ChildType,
+                  ChildExtension->ChildDescriptor,
+                  &ChildExtension->ChildId,
                   &Unused);
       if (Status == VIDEO_ENUM_MORE_DEVICES)
       {
-         if (ChildType == Monitor)
+         if (ChildExtension->ChildType == Monitor)
          {
             // Check if the EDID is valid
-            if (ChildDescriptor[0] == 0x00 &&
-                ChildDescriptor[1] == 0xFF &&
-                ChildDescriptor[2] == 0xFF &&
-                ChildDescriptor[3] == 0xFF &&
-                ChildDescriptor[4] == 0xFF &&
-                ChildDescriptor[5] == 0xFF &&
-                ChildDescriptor[6] == 0xFF &&
-                ChildDescriptor[7] == 0x00)
+            if (ChildExtension->ChildDescriptor[0] == 0x00 &&
+                ChildExtension->ChildDescriptor[1] == 0xFF &&
+                ChildExtension->ChildDescriptor[2] == 0xFF &&
+                ChildExtension->ChildDescriptor[3] == 0xFF &&
+                ChildExtension->ChildDescriptor[4] == 0xFF &&
+                ChildExtension->ChildDescriptor[5] == 0xFF &&
+                ChildExtension->ChildDescriptor[6] == 0xFF &&
+                ChildExtension->ChildDescriptor[7] == 0x00)
             {
                if (bHaveLastMonitorID)
                {
                   // Compare the previous monitor ID with the current one, break the loop if they are identical
-                  if (RtlCompareMemory(LastMonitorID, &ChildDescriptor[8], sizeof(LastMonitorID)) == sizeof(LastMonitorID))
+                  if (RtlCompareMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID)) == sizeof(LastMonitorID))
                   {
                      INFO_(VIDEOPRT, "Found identical Monitor ID two times, stopping enumeration\n");
+                     IoDeleteDevice(ChildDeviceObject);
                      break;
                   }
                }
 
                // Copy 10 bytes from the EDID, which can be used to uniquely identify the monitor
-               RtlCopyMemory(LastMonitorID, &ChildDescriptor[8], sizeof(LastMonitorID));
+               RtlCopyMemory(LastMonitorID, &ChildExtension->ChildDescriptor[8], sizeof(LastMonitorID));
                bHaveLastMonitorID = TRUE;
+
+               /* Mark it valid */
+               ChildExtension->EdidValid = TRUE;
+            }
+            else
+            {
+                /* Mark it invalid */
+                ChildExtension->EdidValid = FALSE;
             }
          }
       }
       else if (Status == VIDEO_ENUM_INVALID_DEVICE)
       {
          WARN_(VIDEOPRT, "Child device %d is invalid!\n", ChildEnumInfo.ChildIndex);
+         IoDeleteDevice(ChildDeviceObject);
          continue;
       }
       else if (Status == VIDEO_ENUM_NO_MORE_DEVICES)
       {
          INFO_(VIDEOPRT, "End of child enumeration! (%d children enumerated)\n", i - 1);
+         IoDeleteDevice(ChildDeviceObject);
          break;
       }
       else
       {
          WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unknown status code 0x%x!\n", Status);
+         IoDeleteDevice(ChildDeviceObject);
          break;
       }
 
-#ifndef NDEBUG
-      if (ChildType == Monitor)
+      if (ChildExtension->ChildType == Monitor)
       {
          UINT j;
-         PUCHAR p = ChildDescriptor;
-         INFO_(VIDEOPRT, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildId);
-         for (j = 0; j < sizeof (ChildDescriptor); j += 8)
+         PUCHAR p = ChildExtension->ChildDescriptor;
+         INFO_(VIDEOPRT, "Monitor device enumerated! (ChildId = 0x%x)\n", ChildExtension->ChildId);
+         for (j = 0; j < sizeof (ChildExtension->ChildDescriptor); j += 8)
          {
             INFO_(VIDEOPRT, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
                    p[j+0], p[j+1], p[j+2], p[j+3],
                    p[j+4], p[j+5], p[j+6], p[j+7]);
          }
       }
-      else if (ChildType == Other)
-      {
-         INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildDescriptor);
+      else if (ChildExtension->ChildType == Other)
+      {
+         INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildExtension->ChildDescriptor);
       }
       else
       {
-         WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildType);
-      }
-#endif /* NDEBUG */
-
-   }
+         ERR_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension->ChildType);
+      }
+
+       /* Clear the init flag */
+       ChildDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+       InsertTailList(&DeviceExtension->ChildDeviceList,
+                      &ChildExtension->ListEntry);
+   }
+
+   /* Trigger reenumeration by the PnP manager */
+   IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations);
 
    return NO_ERROR;
 }

Modified: trunk/reactos/drivers/video/videoprt/videoprt.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/video/videoprt/videoprt.h?rev=56128&r1=56127&r2=56128&view=diff
==============================================================================
--- trunk/reactos/drivers/video/videoprt/videoprt.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/video/videoprt/videoprt.h [iso-8859-1] Mon Mar 12 03:29:36 2012
@@ -78,8 +78,14 @@
    UNICODE_STRING RegistryPath;
 } VIDEO_PORT_DRIVER_EXTENSION, *PVIDEO_PORT_DRIVER_EXTENSION;
 
+typedef struct _VIDEO_PORT_COMMON_EXTENSION
+{
+    BOOLEAN Fdo;
+} VIDEO_PORT_COMMON_EXTENSION, *PVIDEO_PORT_COMMON_EXTENSION;
+
 typedef struct _VIDEO_PORT_DEVICE_EXTENSTION
 {
+   VIDEO_PORT_COMMON_EXTENSION Common;
    ULONG DeviceNumber;
    PDRIVER_OBJECT DriverObject;
    PDEVICE_OBJECT PhysicalDeviceObject;
@@ -101,13 +107,37 @@
    ULONG DeviceOpened;
    AGP_BUS_INTERFACE_STANDARD AgpInterface;
    KMUTEX DeviceLock;
-   LIST_ENTRY DmaAdapterList;
+   LIST_ENTRY DmaAdapterList, ChildDeviceList;
    CHAR MiniPortDeviceExtension[1];
 } VIDEO_PORT_DEVICE_EXTENSION, *PVIDEO_PORT_DEVICE_EXTENSION;
 
+typedef struct _VIDEO_PORT_CHILD_EXTENSION
+{
+    VIDEO_PORT_COMMON_EXTENSION Common;
+
+    ULONG ChildId;
+    VIDEO_CHILD_TYPE ChildType;
+    UCHAR ChildDescriptor[256];
+
+    BOOLEAN EdidValid;
+
+    PDRIVER_OBJECT DriverObject;
+    PDEVICE_OBJECT PhysicalDeviceObject;
+
+    LIST_ENTRY ListEntry;
+
+    CHAR ChildDeviceExtension[1];
+} VIDEO_PORT_CHILD_EXTENSION, *PVIDEO_PORT_CHILD_EXTENSION;
+
+#define VIDEO_PORT_GET_CHILD_EXTENSION(MiniportExtension) \
+   CONTAINING_RECORD( \
+       MiniportExtension, \
+       VIDEO_PORT_CHILD_EXTENSION, \
+       ChildDeviceExtension)
+
 #define VIDEO_PORT_GET_DEVICE_EXTENSION(MiniportExtension) \
    CONTAINING_RECORD( \
-      HwDeviceExtension, \
+      MiniportExtension, \
       VIDEO_PORT_DEVICE_EXTENSION, \
       MiniPortDeviceExtension)
 
@@ -130,6 +160,13 @@
    IN PVOID HwDeviceExtension,
    IN OUT PINTERFACE Interface);
 
+/* child.c */
+
+NTSTATUS NTAPI
+IntVideoPortDispatchPdoPnp(
+   IN PDEVICE_OBJECT DeviceObject,
+   IN PIRP Irp);
+
 /* dispatch.c */
 
 NTSTATUS NTAPI




More information about the Ros-diffs mailing list