Udostępnij przez


Ocenianie metody sterującej bez argumentów wejściowych

Aby synchronicznie ocenić metodę sterowania, która nie pobiera argumentów wejściowych, sterownik urządzenia wysyła żądanie IOCTL_ACPI_EVAL_METHOD lub żądanie IOCTL_ACPI_EVAL_METHOD_EX do urządzenia. Ogólna procedura używania obu tych żądań została opisana w Ocenianie metod kontroli ACPI synchronicznie. Konkretna różnica między użyciem tych dwóch żądań jest następująca:

  • Jeśli metoda sterowania jest bezpośrednim obiektem podrzędnym urządzenia, sterownik wysyła żądanie IOCTL_ACPI_EVAL_METHOD i dostarcza strukturę wejściową ACPI_EVAL_INPUT_BUFFER określoną przez .

  • Jeśli metoda sterowania jest obiektem podrzędnym w przestrzeni nazw ACPI urządzenia, ale nie jest bezpośrednim obiektem podrzędnym urządzenia, sterownik wysyła żądanie IOCTL_ACPI_EVAL_METHOD_EX i dostarcza strukturę ACPI_EVAL_INPUT_BUFFER_EX.

W przykładzie funkcji GetAbcData, która jest dostępna w tym temacie, pokazano, jak sterownik urządzenia może użyć żądania IOCTL_ACPI_EVAL_METHOD, aby ocenić metodę sterowania o nazwie "ABCD", którą obsługuje urządzenie. Metoda sterowania "ABCD" jest bezpośrednim elementem podrzędnym urządzenia w przestrzeni nazw ACPI i nie pobiera argumentów wejściowych ani zwraca argumentów wyjściowych.

Jeśli metoda sterowania "ABCD" nie była bezpośrednim obiektem podrzędnym, wymagane zmiany w tym przykładowym kodzie są następujące:

  • Wyślij żądanie IOCTL_ACPI_EVAL_METHOD_EX zamiast żądania IOCTL_ACPI_EVAL_METHOD.

  • Podaj strukturę ACPI_EVAL_INPUT_BUFFER_EX zamiast struktury ACPI_EVAL_INPUT_BUFFER.

getAbcData najpierw przydziela strukturę ACPI_EVAL_INPUT_BUFFER inputBuffer i ustawia element członkowski MethodNameAsUlong na nazwę metody kontrolki i ustawia element członkowski Signature na ACPI_EVAL_INPUT_BUFFER_SIGNATURE.

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

GetAbcData przydziela również strukturę ACPI_EVAL_OUTPUT_BUFFERoutputBuffer, ale nie ustawia żadnego z członów outputBuffer.

getAbcData następnie wywołuje funkcję dostarczaną przez sterownik o nazwie SendDownStreamIrp, która wykonuje następujące czynności:

  1. Wywołuje IoBuildDeviceIoControlRequest w celu skompilowania żądania.

  2. Wywołuje IoCallDriver, aby wysłać żądanie w dół stosu urządzenia.

  3. Czeka, aż menedżer I/O zasygnalizuje, że sterowniki niższego poziomu zakończyły realizację żądania.

SendDownStreamIrp zwraca po sygnale Menedżera We/Wy, że zakończono przetwarzanie żądania przez sterowniki niższego poziomu. Przykładowy kod, o którym wspomniano wcześniej, wykonuje następujące czynności:

  1. Sprawdza stan żądania i zwraca bez dodatkowego przetwarzania, jeśli sterowniki niższego poziomu nie zwróciły STATUS_SUCCESS.

  2. Sprawdza poprawność argumentów wyjściowych. Aby outputBuffer zawierał prawidłowe dane wyjściowe, Signature musi być ustawiona na ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE, a Count musi być większy niż zero.

  3. Przetwarza argumenty wyjściowe, które sterownik ACPI zwrócił z powrotem do sterownika.

Mimo że ten krok nie jest uwzględniony w przykładowym kodzie, sterownik powinien również wywołać IoCompleteRequest po przetworzeniu danych wyjściowych, aby zakończyć oczekujące żądanie IOCTL_ACPI_EVAL_METHOD, które sterownik wysłał w celu oceny metody sterowania.

Struktury danych ACPI i stałe używane w poniższym przykładzie są zdefiniowane w 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;
}