Windows Phone 8.1 驱动开发——如何调用ACPI Method
来源:互联网 发布:学java能做游戏吗 编辑:程序博客网 时间:2024/06/04 23:33
ACPI Method
首先我们来看一段在ACPI中定义的Method:
//Global BufferName(DATA, Buffer(0x4) { 0x00, 0x00, 0x00, 0x00})Device (TEST){ Name (_HID, "TEST001") Name (_UID, 1)... Method(GETD, 0x0, NotSerialized) { return (DATA) } Method(SETD, 0x1, NotSerialized) { Store(Arg0, DATA) }...}从代码中可以看到,该TEST设备提供了2个Method:GETD()和SETD()。全局变量DATA为4字节数组,GETD()方法用于读取DATA的数据并传给驱动程序,SETD()则用于将驱动程序传过来的数据写入DATA中去。用C语言的表现形式来描述它们的话,就可以写成这样:uchar* GETD(void); 和 void SETD(uchar* data);
IOCTL_ACPI_EVAL_METHOD 请求
驱动程序可以通过调用WdfIoTargetSendIoctlSynchronously()函数发送IOCTL_ACPI_EVAL_METHOD请求给ACPI驱动来调用ACPI Method。关于该IOCTL更详细的信息,请查阅MSDN文档:IOCTL_ACPI_EVAL_METHOD control code
在编写KMDF驱动之前,我们需要先了解一下以下4个结构体:
ACPI_EVAL_INPUT_BUFFER
ACPI_EVAL_INPUT_BUFFER_COMPLEX
ACPI_EVAL_OUTPUT_BUFFER
ACPI_METHOD_ARGUMENT
ACPI_EVAL_INPUT_BUFFER结构体
结构体定义如下:
typedef struct _ACPI_EVAL_INPUT_BUFFER { ULONG Signature; union { UCHAR MethodName[4]; ULONG MethodNameAsUlong; };} ACPI_EVAL_INPUT_BUFFER, *PACPI_EVAL_INPUT_BUFFER;该结构体用于调用一个不带输入参数的ACPI Method,假设要访问的Method为GETD(),在发送IOCTL_ACPI_EVAL_METHOD请求之前,需要对其成员变量进行如下设置:
- 设置Signature为ACPI_EVAL_INPUT_BUFFER_SIGNATURE
- 设置MethodName为 'GETD' 或设置MethodNameAsUlong为 (ULONG)('DTEG')
ACPI_EVAL_INPUT_BUFFER_COMPLEX结构体
结构体定义如下:
typedef struct _ACPI_EVAL_INPUT_BUFFER_COMPLEX { ULONG Signature; union { UCHAR MethodName[4]; ULONG MethodNameAsUlong; }; ULONG Size; ULONG ArgumentCount; ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];} ACPI_EVAL_INPUT_BUFFER_COMPLEX, *PACPI_EVAL_INPUT_BUFFER_COMPLEX;该结构体用于调用一个带输入参数的ACPI Method,用来传递输入参数,假设要访问的Method为SETD(),在发送IOCTL_ACPI_EVAL_METHOD请求之前,需要对其成员变量进行如下设置:
- 设置Signature为ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE
- 设置MethodName为 'SETD' 或设置MethodNameAsUlong为 (ULONG)('DTES')
- 设置Size的值,该值表示Argument[ANYSIZE_ARRAY]整个数组的字节大小
- 设置ArgumentCount的值,这里为1
- 给结构体成员Argument赋值,设置输入参数
ACPI_EVAL_OUTPUT_BUFFER结构体
结构体定义如下:
typedef struct _ACPI_EVAL_OUTPUT_BUFFER { ULONG Signature; ULONG Length; ULONG Count; ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];} ACPI_EVAL_OUTPUT_BUFFER;
该结构体用于返回ACPI Method执行后的输出参数,输出参数将被保存在Argument成员变量中,Signature的值必须为ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE,Length表示整个ACPI_EVAL_OUTPUT_BUFFER结构体的字节大小,Count记录了有多少个Argument成员。关于该结构体更详细的信息,请查阅MSDN文档:ACPI_EVAL_OUTPUT_BUFFER structure
ACPI_METHOD_ARGUMENT结构体
结构体定义如下:
typedef struct _ACPI_METHOD_ARGUMENT USHORT Type; USHORT DataLength; union { ULONG Argument; UCHAR Data[ANYSIZE_ARRAY]; };} ACPI_METHOD_ARGUMENT;
该结构体才是真正存储输入、输出参数的地方。其中
Type定义了参数的类型,它的值有以下几种:
ACPI_METHOD_ARGUMENT_INTEGER
ACPI_METHOD_ARGUMENT_STRING
ACPI_METHOD_ARGUMENT_BUFFER
ACPI_METHOD_ARGUMENT_PACKAGE
DataLength为数组Data的字节大小。
关于该结构体更详细的信息,请查阅MSDN文档:ACPI_METHOD_ARGUMENT structure
Sample Code
访问不带输入参数的ACPI Method:NTSTATUS ACPIGetData(WDFDEVICE FxDevice, void *pBuffer){ NTSTATUS Status; WDF_MEMORY_DESCRIPTOR InputDescriptor; WDF_MEMORY_DESCRIPTOR OutputDescriptor; ACPI_EVAL_INPUT_BUFFER InputBuffer; ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; WDFIOTARGET IoTarget; ULONG SizeReturned; USHORT DataLength; PAGED_CODE(); // // Signature and Method name in reverse // InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; InputBuffer.MethodNameAsUlong = (ULONG) ('DTEG'); // // 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_EVAL_INPUT_BUFFER)); RtlZeroMemory(&OutputBuffer, sizeof(OutputBuffer)); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&OutputDescriptor, (PVOID)&OutputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER)); // // Get handle for underlying ACPI layer // IoTarget = WdfDeviceGetIoTarget(FxDevice); // // Send synchronous request // Status = WdfIoTargetSendIoctlSynchronously(IoTarget, NULL, IOCTL_ACPI_EVAL_METHOD, &InputDescriptor, &OutputDescriptor, NULL, &SizeReturned); if (!NT_SUCCESS(Status)) { return Status; } // // Verify output signature and length // if ((OutputBuffer.Signature == ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) && (OutputBuffer.Argument[0].Type == ACPI_METHOD_ARGUMENT_BUFFER)) {//// Extract data from buffer//DataLength = OutputBuffer.Argument[0].DataLength;memcpy_s((UINT8*)pBuffer, (DataLength * sizeof(UINT8)), (UINT8*)OutputBuffer.Argument[0].Data, (DataLength * sizeof(UINT8))); Status = STATUS_SUCCESS; } else { Status = STATUS_ACPI_INVALID_DATA; }exit: return Status;}
访问带输入参数的ACPI Method:
NTSTATUS ACPISetData(WDFDEVICE FxDevice, void *pBuffer){ NTSTATUS Status; WDF_MEMORY_DESCRIPTOR InputDescriptor; WDF_MEMORY_DESCRIPTOR OutputDescriptor; ACPI_EVAL_INPUT_BUFFER_COMPLEX InputBuffer; ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; WDFIOTARGET IoTarget; ULONG SizeReturned; PAGED_CODE(); // // Signature and Method name in reverse // InputBuffer.MethodNameAsUlong = (ULONG)('DTES'); InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE; InputBuffer.ArgumentCount = 1; InputBuffer.Size = InputBuffer.ArgumentCount * sizeof(ACPI_METHOD_ARGUMENT); InputBuffer.Argument[0].Type = ACPI_METHOD_ARGUMENT_BUFFER; InputBuffer.Argument[0].DataLength = 4;memcpy_s(InputBuffer.Argument[0].Data, InputBuffer.Argument[0].DataLength, pBuffer, InputBuffer.Argument[0].DataLength); // // 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_EVAL_INPUT_BUFFER_COMPLEX)); RtlZeroMemory(&OutputBuffer, sizeof(OutputBuffer)); WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&OutputDescriptor, (PVOID)&OutputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER)); // // Get handle for underlying ACPI layer // IoTarget = WdfDeviceGetIoTarget(FxDevice); // // Send synchronous request // Status = WdfIoTargetSendIoctlSynchronously(IoTarget, NULL, IOCTL_ACPI_EVAL_METHOD, &InputDescriptor, &OutputDescriptor, NULL, &SizeReturned); if (!NT_SUCCESS(Status)) {goto exit; } else { // // Verify output signature and length // if ( (OutputBuffer.Signature == ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) && (OutputBuffer.Argument[0].Type == ACPI_METHOD_ARGUMENT_BUFFER)) { Status = STATUS_SUCCESS; } else { Status = STATUS_ACPI_INVALID_DATA; } }exit: return Status;}
关于ACPI Control Method更详细的用法,请查阅MSDN官方文档:Evaluating ACPI Control Methods Synchronously
- Windows Phone 8.1 驱动开发——如何调用ACPI Method
- Windows Phone 8.1 驱动开发——GPIO Device
- Windows Phone 8.1 驱动开发——注册表read/write
- Windows Phone 8.1 驱动开发——SPB 简介
- Windows Phone 8.1 驱动开发——GPIO 简介
- Windows Phone 8开发历程——Windows Phone简介
- 如何学习Windows Phone开发
- Windows phone 应用开发[14]-调用WebBrowser
- Windows Phone开发如何保存铃声?
- 如何开始学习Windows Phone开发
- Windows Phone 8初学者开发—第3部分:编写第一个Windows Phone 8应用程序
- Windows驱动开发——WDM驱动
- Windows驱动开发——WDM驱动
- Windows Phone 8.1摄像头模块的调用
- Windows驱动开发如何入门
- Windows驱动开发如何入门
- Windows驱动开发如何入门
- Windows驱动开发如何入门
- IOS学习之——地图2 跟踪用户位置变化
- Objective - C基础: 第一天 - 9.常见错误
- 一、 编译Live555
- HDU-2519-新生晚会
- JBuilder快捷键整理
- Windows Phone 8.1 驱动开发——如何调用ACPI Method
- 改造vim变成source insight
- Running Android L Developer Preview on 64-bit ARM QEMU
- Python脚本报错AttributeError: ‘module’ object has no attribute’xxx’解决方法
- 应用maven/hudson实施jmeter性能自动化
- SharePoint Workflow Trouble Shooting(二)分析log文件
- 二、Live555 基础类
- 浅谈JAVA ThreadPoolExecutor
- 献给毕业不知将向何处去的童鞋