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


Обмен глаголами с помощью аудиокодека HD

Средство настройки Hdau.exe контактов используется IOCTL_AZALIABUS_SENDVERBS IOCTL при определении топологий звука для звуковых адаптеров. Не используйте этот IOCTL для других целей. Эти сведения о IOCTL_AZALIABUS_SENDVERBS предоставляются только для документирования его структуры и реализации. Этот IOCTL поддерживается в драйвере класса аудио в Windows 7 Hdaudio.sys.

Аудиокодеки высокой четкости (HD) могут принимать глаголы и отвечать на них. Эти глаголы и ответы кодеков на эти команды задокументированы в рамках спецификации hd audio.

В Windows 7 и более поздних версиях операционных систем Windows драйвер класса hd audio использует IOCTL IOCTL_AZALIABUS_SENDVERBS для связи глаголов с аудиокодеком. IOCTL_AZALIABUS_SENDVERBS определяется, как показано в следующем примере:

#define IOCTL_AZALIABUS_SENDVERBS CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)

Дополнительные сведения о FILE_DEVICE_UNKNOWN, METHOD_BUFFERED и FILE_ANY_ACCESS см. в файле заголовка Devioctl.h в windows SDK.

Чтобы инициировать обмен данными с аудиокодеком, драйвер класса вызывает функцию DeviceIoControl со следующими параметрами.

BOOL DeviceIoControl(
  (HANDLE) hDevice,                      // handle to device
  IOCTL_AZALIABUS_SENDVERBS,             // dwIoControlCode
  NULL,                                  // lpInBuffer
  0,                                     // nInBufferSize
  (LPVOID) lpOutBuffer,                  // output buffer
  (DWORD) nOutBufferSize,                // size of output buffer
  (LPDWORD) lpBytesReturned,             // number of bytes returned
  (LPOVERLAPPED) lpOverlapped            // OVERLAPPED structure
);

Если вызов DeviceIoControl выполнен успешно, он возвращает ненулевое значение. Если вызов завершается сбоем или находится в состоянии ожидания (не обрабатывается немедленно), DeviceIoControl возвращает нулевое значение. Драйвер класса может вызвать GetLastError для получения более подробного сообщения об ошибке.

Если звуковой драйвер должен изменить параметры конфигурации пин-кода по умолчанию, он может использовать IOCTL_AZALIABUS_SENDVERBS для отправки и получения команд Set и Get из звукового кодека. Если связь с аудиокодеком не связана с конфигурацией пин-кода, звуковой кодек отвечает только на команду Get.

В следующем примере показана функция, которая принимает структуру AzCorbeEntry и HANDLE в качестве параметров и возвращает AzRirbResponse из кодека.

AzRirbEntry SendVerb(HANDLE handle, AzCorbEntry verb)
{
  UserModeCodecCommandPacket c;
  UserModeCodecResponsePacket r;
  c.NumCommands = 1;
  c.Command[0] = verb;
  DWORD BytesReturned;

//A nonzero value is returned for a successful call and it is interpreted as TRUE  
BOOL rc = DeviceIoControl(handle, IOCTL_AZALIABUS_SENDVERBS, &c, sizeof(c), &r, sizeof(r), &BytesReturned, 0);

  if(!rc)
  {
    printf("Failed to communicate with the device!\n");
    return 0;
  }

  if(BytesReturned != sizeof(r))
  {
    printf("Wrong number of bytes returned!\n");
    return 0;
  }

  return r.Response[0];
}

Типы данных и структуры, используемые в предыдущем примере кода, определяются в следующем примере:

AzCorbEntry

struct AzCorbEntry
{
  ULONG Verb        : 20; // 0:19
  ULONG NodeId      : 7;  // 20:26
  ULONG IndirectNID : 1;  // 27
  ULONG LinkId      : 4;  // 28:31
  enum {Invalid = 0xffffffff};
  AzCorbEntry(ULONG x = 0)
  :
    Verb(x),
    NodeId(x >> 20),
    IndirectNID(x >> 27),
    LinkId(x >> 28) {}
  operator ULONG()
  {
    return Verb | NodeId << 20 | IndirectNID << 27 | LinkId << 28;
  }
};

AzRirbEntry

struct AzRirbEntry
{
  union
  {
    struct 
    {
      ULONG Response  : 21; // 0 : 20
      ULONG SubTag    : 5; // 21 : 25
      ULONG Tag       : 6; // 26 : 31
    } UnsolicitedForm;

    ULONG Response    : 32; // 0:31
  };
  ULONG Sdi         : 4;  // 32:35
  ULONG Unsolicited : 1;  // 36
  ULONG Reserved0   : 26; // 37:62
  ULONG Valid       : 1;  // 63 note this bit only exists
                          // on the "link". The fact that the response
                          // got into memory assures that it is valid
  AzRirbEntry (ULONGLONG x = 0)
  {
    Response = x & 0xffffffff;
    Sdi = x >> 32;
    Unsolicited = x >> 36;
    Reserved0 = x >> 37;
    Valid = x >> 63;
  }
  operator ULONGLONG()
  {
    return (ULONGLONG)Response | (ULONGLONG)Sdi << 32 | (ULONGLONG)Unsolicited << 36 | (ULONGLONG)Reserved0 << 37 | (ULONGLONG)Valid << 63;
  }
};

Следующие две структуры используются вместе с IOCTL для передачи команд и ответов между звуковым драйвером и кодеком HD.

UserModeCodecCommandPacket

typedef struct _UserModeCodecCommandPacket
{
  ULONG NumCommands;      // number of commands in this packet
  AzCorbEntry Command[1]; // variable length array of verbs
} UserModeCodecCommandPacket;

UserModeCodecResponsePacket

typedef struct _UserModeCodecResponsePacket
{
  ULONG NumResponses;       // on successful IOCTL, this will be updated with the number of responses.
  AzRirbEntry Response[1];  // Variable length array of responses. lpOutBuffer param to DeviceIoControl
                            // must point to sufficient space to hold this IOCTL with all its responses 
} UserModeCodecResponsePacket;