Kommunizieren von Verben mit dem HD-Audiocodec

Die IOCTL_AZALIABUS_SENDVERBS IOCTL wird vom Hdau.exe Pinkonfigurationstool verwendet, wenn Sie Soundtopologien für Ihre Audioadapter definieren. Verwenden Sie diese IOCTL nicht für andere Zwecke. Diese Informationen zu IOCTL_AZALIABUS_SENDVERBS werden nur zur Dokumentation des Entwurfs und der Implementierung bereitgestellt. Dieses IOCTL wird im Windows 7 Hdaudio.sys Audioklassentreiber unterstützt.

Hd-Audiocodecs können Verben empfangen und darauf reagieren. Diese Verben und die Antworten der Codecs auf diese Verben werden im Rahmen der HD-Audiospezifikation dokumentiert.

In Windows 7 und höheren Versionen der Windows-Betriebssysteme verwendet der HD-Audioklassentreiber die IOCTL_AZALIABUS_SENDVERBS IOCTL, um Verben mit dem Audiocodec zu kommunizieren. IOCTL_AZALIABUS_SENDVERBS wird wie im folgenden Beispiel dargestellt definiert:

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

Weitere Informationen zu FILE_DEVICE_UNKNOWN, METHOD_BUFFERED und FILE_ANY_ACCESS finden Sie in der Headerdatei Devioctl.h im Windows SDK.

Um die Kommunikation mit dem Audiocodec zu initiieren, ruft der Klassentreiber die DeviceIoControl-Funktion mit den folgenden Parametern auf.

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

Wenn der Aufruf von DeviceIoControl erfolgreich ist, wird ein Nonzero-Wert zurückgegeben. Wenn der Aufruf fehlschlägt oder aussteht (nicht sofort verarbeitet), gibt DeviceIoControl einen Nullwert zurück. Der Klassentreiber kann GetLastError aufrufen, um eine ausführlichere Fehlermeldung zu erhalten.

Wenn der Audiotreiber die Pinkonfigurationsstandardeinstellungen ändern muss, kann er IOCTL_AZALIABUS_SENDVERBS verwenden, um Set- und Get-Verben aus dem Audiocodec zu senden und zu empfangen. Wenn es bei der Kommunikation mit dem Audiocodec nicht um die Pinkonfiguration geht, reagiert der Audiocodec nur auf das Verb Get.

Das folgende Beispiel zeigt eine Funktion, die eine AzCorbeEntry-Struktur und ein HANDLE als Parameter akzeptiert und azRirbResponse aus dem Codec zurückgibt.

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

Die Datentypen und Strukturen, die im vorherigen Codebeispiel verwendet werden, werden im folgenden Beispiel definiert:

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

Die folgenden beiden Strukturen werden zusammen mit der Verbübertragungs-IOCTL verwendet, um die Befehls- und Antwortübertragungen zwischen dem Audiotreiber und dem HD-Audiocodec zu ermöglichen.

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;