Windows Phone 8.1 Driver Development--How to invoke ACPI Method

Source: Internet
Author: User


Today, let's explain how to invoke the user-defined method in the ACPI configuration table in the Kmdf (Kernel-mode Driver Framework). In ACPI, any method, such as _sta, that begins with an underscore, is a system-predefined method that is called by the Windows OS itself, and the other user-defined method is called by the driver.





ACPI Method



First, let's look at a method defined in ACPI:





//Global Buffer
Name(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)
    }
	
	...
}
As you can see from the code, the test device provides 2 method:getd () and setd (). The global variable data is a 4-byte array, and the getd () method is used to read data and pass it to the driver, and setd () is used to write the data passed by the driver into data. To describe them in the form of a C expression, it can be written like this: uchar* getd (void); and void setd (uchar* data);





Ioctl_acpi_eval_method Request



The driver can invoke the ACPI Method by calling the wdfiotargetsendioctlsynchronously () function to send an IOCTL_ACPI_EVAL_METHOD request to the ACPI driver. For more detailed information on the IOCTL, please refer to the MSDN documentation:ioctl_acpi_eval_method Control Code



Before we write the Kmdf driver, we need to look at the following 4 structures:



Acpi_eval_input_buffer



Acpi_eval_input_buffer_complex



Acpi_eval_output_buffer



Acpi_method_argument






Acpi_eval_input_buffer Structural Body



The structure is defined as follows:




typedef struct _ACPI_EVAL_INPUT_BUFFER {
  ULONG Signature;
  union {
    UCHAR MethodName[4];
    ULONG MethodNameAsUlong;
  };
} ACPI_EVAL_INPUT_BUFFER, *PACPI_EVAL_INPUT_BUFFER;


 The struct is used to invoke awith no input parametersACPI method, assuming that the method to be accessed is getd (), the member variables need to be set as follows before the Ioctl_acpi_eval_method request is sent: 
    • Set SIGNATURE to acpi_eval_input_buffer_signature
    • Set MethodName to ' getd ' or set Methodnameasulong to (ULONG) (' Dteg ')
For more detailed information on this structure, please refer to the MSDN documentation: acpi_eval_input_buffer Structure





Acpi_eval_input_buffer_complex Structural Body



The structure is defined as follows:





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;
The struct is used to invoke awith input parametersACPI method, which is used to pass input parameters, assuming that the Method to be accessed is setd (), the member variables need to be set as follows before the Ioctl_acpi_eval_method request is sent:
    • Set SIGNATURE to acpi_eval_input_buffer_complex_signature
    • Set MethodName to ' setd ' or set Methodnameasulong to (ULONG) (' DTEs ')
    • Sets the value of size that represents the byte size of the entire array of Argument[anysize_array]
    • Set the value of ArgumentCount, here is 1
    • Assign values to struct member argument, set input parameters
For more detailed information on this structure, please refer to the MSDN documentation: Acpi_eval_input_buffer_complex Structure






Acpi_eval_output_buffer Structural Body



The structure is defined as follows:





typedef struct _ACPI_EVAL_OUTPUT_BUFFER {
  ULONG                Signature;
  ULONG                Length;
  ULONG                Count;
  ACPI_METHOD_ARGUMENT Argument[ANYSIZE_ARRAY];
} ACPI_EVAL_OUTPUT_BUFFER;


The struct is used to return the output parameter after the ACPI method executes, the output parameter is saved in the argument member variable, and the value of SIGNATURE must be acpi_eval_output_buffer_signature. Length indicates the byte size of the entire acpi_eval_output_buffer struct, and count records how many argument members are there. For more detailed information on this structure, please refer to the MSDN documentation:acpi_eval_output_buffer structure









Acpi_method_argument Structural Body



The structure is defined as follows:


typedef struct _ACPI_METHOD_ARGUMENT
  USHORT Type;
  USHORT DataLength;
  union {
    ULONG Argument;
    UCHAR Data[ANYSIZE_ARRAY];
  };
} ACPI_METHOD_ARGUMENT;


The structure is the place where the input and output parameters are really stored. which



Type defines the types of the parameters, which have the following values:



Acpi_method_argument_integer



Acpi_method_argument_string



Acpi_method_argument_buffer



Acpi_method_argument_package



Datalength the byte size for the array data.



For more detailed information on this structure, please refer to the MSDN documentation:acpi_method_argument structure




Sample Code


To access ACPI Method without input parameters:
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;
}





To access the ACPI Method with input parameters:





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;
}






For more detailed usage of ACPI control method, consult the MSDN official documentation:evaluating ACPI control Methods synchronously







Windows Phone 8.1 Driver Development--How to invoke ACPI Method


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.