[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) 

svn path=/trunk/; revision=56128
This commit is contained in:
Cameron Gutman 2012-03-12 03:29:36 +00:00
parent 7af4a7cd8c
commit 1e180c788f
5 changed files with 596 additions and 38 deletions

View file

@ -7,6 +7,7 @@ spec2def(videoprt.sys videoprt.spec ADD_IMPORTLIB)
list(APPEND SOURCE
agp.c
child.c
ddc.c
dispatch.c
dma.c

View file

@ -0,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;
}

View file

@ -410,6 +410,51 @@ IntVideoPortForwardIrpAndWaitCompletionRoutine(
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 @@ IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
return Status;
}
NTSTATUS NTAPI
IntVideoPortDispatchPnp(
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 @@ IntVideoPortDispatchPnp(
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:
@ -495,6 +554,19 @@ IntVideoPortDispatchPnp(
return Status;
}
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,

View file

@ -250,12 +250,15 @@ IntVideoPortCreateAdapterDeviceObject(
*/
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 @@ VideoPortEnumerateChildren(
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,96 +1115,145 @@ VideoPortEnumerateChildren(
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)
else if (ChildExtension->ChildType == Other)
{
INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildDescriptor);
INFO_(VIDEOPRT, "\"Other\" device enumerated: DeviceId = %S\n", (PWSTR)ChildExtension->ChildDescriptor);
}
else
{
WARN_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildType);
ERR_(VIDEOPRT, "HwGetVideoChildDescriptor returned unsupported type: %d\n", ChildExtension->ChildType);
}
#endif /* NDEBUG */
/* 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;
}

View file

@ -78,8 +78,14 @@ typedef struct _VIDEO_PORT_DRIVER_EXTENSION
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 @@ typedef struct _VIDEO_PORT_DEVICE_EXTENSTION
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 @@ IntAgpGetInterface(
IN PVOID HwDeviceExtension,
IN OUT PINTERFACE Interface);
/* child.c */
NTSTATUS NTAPI
IntVideoPortDispatchPdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/* dispatch.c */
NTSTATUS NTAPI