WDDM 子设备描述符
2021-06-30
271
0
子设备的描述信息是能过函数BddDdiQueryDeviceDescriptor实现的。
InitialData.DxgkDdiQueryDeviceDescriptor = BddDdiQueryDeviceDescriptor;
严格来说,这个DxgkDdiQueryDeviceDescriptor的回调函数是获取所有设备的描述符信息,这里的设备不仅包括display adapter的子设备,也包括外部连接设备(如连接到display adapter上的监视器monitor)。
当然获取设备描述信息的前提是显卡正常工作,当该驱动已经停止的时候,应返回失败。
NTSTATUS
BddDdiQueryDeviceDescriptor(
_In_ VOID* pDeviceContext,
_In_ ULONG ChildUid,
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
{
PAGED_CODE();
BDD_ASSERT_CHK(pDeviceContext != NULL);
BASIC_DISPLAY_DRIVER* pBDD = reinterpret_cast<BASIC_DISPLAY_DRIVER*>(pDeviceContext);
if (!pBDD->IsDriverActive())
{
// During stress testing of PnPStop, it is possible for BDD Fallback to get called to start then stop in quick succession.
// The first call queues a worker thread item indicating that it now has a child device, the second queues a worker thread
// item that it no longer has any child device. This function gets called based on the first worker thread item, but after
// the driver has been stopped. Therefore instead of asserting like other functions, we only warn.
BDD_LOG_WARNING1("BDD (0x%I64x) is being called when not active!", pBDD);
return STATUS_UNSUCCESSFUL;
}
return pBDD->QueryDeviceDescriptor(ChildUid, pDeviceDescriptor);
}
设备的描述信息主要是设备的EDID信息,这里只支持基本的EDID信息,并不支持扩展EDID信息。
关于EDID的信息,可以参考https://www.cnblogs.com/beyond-rxl/p/9266997.html
// EDID retrieval
NTSTATUS BASIC_DISPLAY_DRIVER::QueryDeviceDescriptor(_In_ ULONG ChildUid,
_Inout_ DXGK_DEVICE_DESCRIPTOR* pDeviceDescriptor)
{
PAGED_CODE();
BDD_ASSERT(pDeviceDescriptor != NULL);
BDD_ASSERT(ChildUid < MAX_CHILDREN);
// If we haven't successfully retrieved an EDID yet (invalid ones are ok, so long as it was retrieved)
if (!m_Flags.EDID_Attempted)
{
GetEdid(ChildUid);
}
if (!m_Flags.EDID_Retrieved || !m_Flags.EDID_ValidHeader || !m_Flags.EDID_ValidChecksum)
{
// Report no EDID if a valid one wasn't retrieved
return STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED;
}
else if (pDeviceDescriptor->DescriptorOffset == 0)
{
// Only the base block is supported
RtlCopyMemory(pDeviceDescriptor->DescriptorBuffer,
m_EDIDs[ChildUid],
min(pDeviceDescriptor->DescriptorLength, EDID_V1_BLOCK_SIZE));
return STATUS_SUCCESS;
}
else
{
return STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA;
}
}