Windows Phone 8.1 驅動開發——如何調用ACPI Method

來源:互聯網
上載者:User

標籤:windows phone 8   acpi   wdf   windows驅動開發   

今天給大家講解一下,在KMDF(Kernel-Mode Driver Framework)中是如何調用ACPI配置表中使用者定義的Method。在ACPI中,凡是以底線開頭的Method(如_STA)都系統預定義的Method,它們都由Windows OS自己調用,其他使用者自訂Method則由驅動程式調用。


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‘)
關於該結構體更詳細的資訊,請查閱MSDN文檔: ACPI_EVAL_INPUT_BUFFER structure 


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賦值,設定輸入參數
關於該結構體更詳細的資訊,請查閱MSDN文檔: ACPI_EVAL_INPUT_BUFFER_COMPLEX structure 


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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.