Поделиться через


Оценка метода элемента управления без входных аргументов

Чтобы синхронно оценить метод элемента управления, который не принимает входные аргументы, драйвер устройства отправляет на устройство запрос IOCTL_ACPI_EVAL_METHOD или запрос IOCTL_ACPI_EVAL_METHOD_EX . Общая процедура использования обоих этих запросов описана в статье Синхронная оценка методов управления ACPI. Ниже приведена конкретная разница между этими двумя запросами.

  • Если метод управления является непосредственным дочерним объектом устройства, драйвер отправляет запрос IOCTL_ACPI_EVAL_METHOD и предоставляет ACPI_EVAL_INPUT_BUFFER входную структуру.

  • Если метод управления является дочерним объектом в пространстве имен ACPI устройства, но не является непосредственным дочерним объектом устройства, драйвер отправляет запрос IOCTL_ACPI_EVAL_METHOD_EX и предоставляет ACPI_EVAL_INPUT_BUFFER_EX структуру.

В примере функции GetAbcData , приведенной в этом разделе, показано, как драйвер для устройства может использовать запрос IOCTL_ACPI_EVAL_METHOD для оценки метода управления с именем "ABCD", который поддерживает устройство. Метод элемента управления "ABCD" является непосредственным дочерним элементом устройства в пространстве имен ACPI и не принимает входные аргументы и не возвращает выходные аргументы.

Если метод элемента управления "ABCD" не был непосредственным дочерним объектом, необходимые изменения в этом примере кода будут следующими:

  • Отправка запроса IOCTL_ACPI_EVAL_METHOD_EX вместо запроса IOCTL_ACPI_EVAL_METHOD.

  • Укажите структуру ACPI_EVAL_INPUT_BUFFER_EX вместо структуры ACPI_EVAL_INPUT_BUFFER.

GetAbcData сначала выделяет ACPI_EVAL_INPUT_BUFFER структуру inputBuffer и присваивает члену MethodNameAsUlong имя метода элемента управления, а член Signature — ACPI_EVAL_INPUT_BUFFER_SIGNATURE.

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

GetAbcData также выделяет ACPI_EVAL_OUTPUT_BUFFER структуру outputBuffer, но не задает ни одного из членов outputBuffer.

Затем GetAbcData вызывает предоставленную драйвером функцию с именем SendDownStreamIrp, которая выполняет следующие действия:

  1. Вызывает IoBuildDeviceIoControlRequest для сборки запроса.

  2. Вызывает IoCallDriver для отправки запроса в стек устройств.

  3. Ожидает, пока диспетчер ввода-вывода сообщит драйверу о том, что драйвер нижнего уровня завершил запрос.

SendDownStreamIrp возвращается после того, как диспетчер ввода-вывода сообщит, что драйверы нижнего уровня завершили запрос. В приведенном выше примере кода выполняется следующее:

  1. Проверяет состояние запроса и возвращает без дополнительной обработки, если драйверы более низкого уровня не возвращали STATUS_SUCCESS.

  2. Проверяет допустимость выходных аргументов. Чтобы outputBuffer содержал допустимые выходные данные, параметр Signature должен иметь значение ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE а значение Count должно быть больше нуля.

  3. Обрабатывает выходные аргументы, переданные драйвером ACPI обратно в драйвер.

Хотя этот шаг не включен в пример кода, драйвер должен также вызвать IoCompleteRequest после обработки выходных данных для выполнения ожидающего запроса IOCTL_ACPI_EVAL_METHOD или IOCTL_ACPI_EVAL_METHOD запроса, отправленного драйвером для оценки метода управления.

Структуры данных и константы ACPI, используемые в следующем примере, определяются в acpiioct.h.

NTSTATUS
GetAbcdData(
    IN PDEVICE_OBJECT   Pdo,
    OUT PULONG          ReturnStatus
    )
/*++

Routine Description:
    Evaluates the ABCD method on the device in the ACPI namespace referenced by Pdo

Parameters
    Pdo             - PDO for the device
    ReturnStatus    - Pointer to where the status data is placed

Return Value:
    NT Status of the operation

--*/
{
    ACPI_EVAL_INPUT_BUFFER  inputBuffer;
    ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
    NTSTATUS                status;
    PACPI_METHOD_ARGUMENT   argument;

    .
    .

    ASSERT( ReturnStatus != NULL );
    *ReturnStatus = 0x0;

    // Fill in the input data
    inputBuffer.MethodNameAsUlong = (ULONG) ('DCBA');
    inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

    // Send the request along
    status = SendDownStreamIrp(
       Pdo,
       IOCTL_ACPI_EVAL_METHOD,
       &inputBuffer,
       sizeof(ACPI_EVAL_INPUT_BUFFER),
       &outputBuffer,
       sizeof(ACPI_EVAL_OUTPUT_BUFFER)
       );

    if (!NT_SUCCESS(status)) {
       return status;
    }

    // Verify the data
    if (outputBuffer != NULL) {
        if ( ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Signature != 
            ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
            ( (PACPI_EVAL_OUTPUT_BUFFER) outputBuffer->Count == 0) {
            return STATUS_ACPI_INVALID_DATA;
        } 
}

    // Retrieve the output argument
    argument = outputBuffer.Argument;
 
// Process the output argument
 .
.
.
 
    return status;
}