mirror of
https://github.com/reactos/reactos.git
synced 2024-11-27 21:43:32 +08:00
[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:
parent
7af4a7cd8c
commit
1e180c788f
@ -7,6 +7,7 @@ spec2def(videoprt.sys videoprt.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
agp.c
|
||||
child.c
|
||||
ddc.c
|
||||
dispatch.c
|
||||
dma.c
|
||||
|
396
reactos/drivers/video/videoprt/child.c
Normal file
396
reactos/drivers/video/videoprt/child.c
Normal 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;
|
||||
}
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user