本文介绍在Windows驱动开发中,基于KMDF开发框架,使用WdfIoTargetSendIoctlSynchronously解析设备节点中_DSD数据,详细操作流程如下
1 DSDT描述
Device (DEV0)
{
Name (_HID, "QCOM0020") // _HID: Hardware ID Settings
{
Memory32Fixed (ReadWrite,
0xa0011000, // Address Base
0x00001000, // Address Length
)
Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, )
{
0x00000074,
}
})
Name (_DSD, Package (0x02) // _DSD: Device-Specific Data
{
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301") /* Device Properties for _DSD */,
Package (0x01)
{
Package (0x02)
{
"feature",
0x05F5E100
}
}
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}
}
2 解析函数
NTSTATUS AcpiGetDeviceSpecialData(
_In_ WDFDEVICE FxDevice,
_In_ PCHAR PropertyName,
_Out_ PULONG Data)
{
NTSTATUS Status;
WDF_MEMORY_DESCRIPTOR InputDescriptor;
WDF_MEMORY_DESCRIPTOR OutputDescriptor;
ACPI_GET_DEVICE_SPECIFIC_DATA InputBuffer;
ACPI_EVAL_OUTPUT_BUFFER OutputBuffer;
WDFIOTARGET IoTarget;
ULONG_PTR SizeReturned;
PAGED_CODE();
//
// Signature and Method name in reverse
//
InputBuffer.Signature = IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA_SIGNATURE;
InputBuffer.Section.Data1 = 0xdaffd814;
InputBuffer.Section.Data2 = 0x6eba;
InputBuffer.Section.Data3 = 0x4d8c;
InputBuffer.Section.Data4[0] = 0x8a;
InputBuffer.Section.Data4[1] = 0x91;
InputBuffer.Section.Data4[2] = 0xbc;
InputBuffer.Section.Data4[3] = 0x9b;
InputBuffer.Section.Data4[4] = 0xbf;
InputBuffer.Section.Data4[5] = 0x4a;
InputBuffer.Section.Data4[6] = 0xa3;
InputBuffer.Section.Data4[7] = 0x01;
InputBuffer.PropertyNameLength = (ULONG)strlen(PropertyName) + 1;
RtlCopyMemory(InputBuffer.PropertyName, PropertyName, InputBuffer.PropertyNameLength);
//
// Use following WDF method to initialize memory descriptor
// The memory descriptor is initialized with the input buffer we have defined.
//
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&InputDescriptor,
(PVOID)&InputBuffer,
sizeof(ACPI_GET_DEVICE_SPECIFIC_DATA) + InputBuffer.PropertyNameLength);
RtlZeroMemory(&OutputBuffer, sizeof(OutputBuffer));
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&OutputDescriptor,
(PVOID)&OutputBuffer,
512);
// Get handle for underlying ACPI layer
IoTarget = WdfDeviceGetIoTarget(FxDevice);
// Send synchronous request
Status = WdfIoTargetSendIoctlSynchronously(IoTarget,
NULL,
IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA,
&InputDescriptor,
&OutputDescriptor,
NULL,
&SizeReturned);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (OutputBuffer.Argument[0].Type == ACPI_METHOD_ARGUMENT_INTEGER)
*Data = OutputBuffer.Argument[0].Argument;
return Status;
}
3 操作流程
如果要解析DSDT表中DEV0下的“feature”信息,调用如下
AcpiGetDeviceSpecialData(FxDevice, "feature", &Data);
如果操作成功,Data = 0x05F5E100