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


Обмен данными с аудиокодеком HD

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

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

В Windows 7 и более поздних версиях операционных систем Windows драйвер класса HD Audio использует IOCTL_AZALIABUS_SENDVERBS IOCTL для передачи глаголов в аудиокодек. 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 в пакете SDK для Windows.

Чтобы инициировать взаимодействие с аудиокодеком, драйвер класса вызывает функцию 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 и дескриптор в качестве параметров и возвращает 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;