Condividi tramite


Comunicazione di verbi con il codec audio HD

Il IOCTL_AZALIABUS_SENDVERBS IOCTL viene usato dallo strumento di configurazione dei pin Hdau.exe quando si definiscono topologie audio per le schede audio. Non usare questo IOCTL per altri scopi. Queste informazioni sulle IOCTL_AZALIABUS_SENDVERBS vengono fornite solo per documentarne la progettazione e l'implementazione. Questo IOCTL è supportato nel driver di classe audio di Windows 7 Hdaudio.sys.

I codec audio HD (High Definition) sono in grado di ricevere e rispondere ai verbi. Questi verbi e le risposte dei codec a questi verbi sono documentati come parte di HD Audio Specification.

In Windows 7 e versioni successive dei sistemi operativi Windows, il driver della classe audio HD usa il IOCTL_AZALIABUS_SENDVERBS IOCTL per comunicare verbi con il codec audio. IOCTL_AZALIABUS_SENDVERBS è definito come illustrato nell'esempio seguente:

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

Per ulteriori informazioni su FILE_DEVICE_UNKNOWN, METHOD_BUFFERED e FILE_ANY_ACCESS, consultare il file header Devioctl.h nel Windows SDK.

Per avviare la comunicazione con il codec audio, il driver di classe chiama la funzione DeviceIoControl con i parametri seguenti.

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

Se la chiamata a DeviceIoControl ha esito positivo, restituisce un valore diverso da zero. Se la chiamata ha esito negativo o è in sospeso (non elaborata immediatamente), DeviceIoControl restituisce un valore zero. Il driver di classe può chiamare GetLastError per un messaggio di errore più dettagliato.

Quando il driver audio deve modificare le impostazioni predefinite di configurazione dei pin, può usare IOCTL_AZALIABUS_SENDVERBS per inviare e ricevere set e ottenere verbi dal codec audio. Se la comunicazione con il codec audio non riguarda la configurazione dei pin, il codec audio risponde solo al verbo Get.

L'esempio seguente mostra una funzione che accetta una struttura AzCorbeEntry e un handle come parametri e restituisce AzRirbResponse dal codec.

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

I tipi di dati e le strutture usati nell'esempio di codice precedente sono definiti nell'esempio seguente:

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

Le due strutture seguenti vengono usate insieme al verbo di trasferimento IOCTL per abilitare i trasferimenti di comandi e risposte tra il driver audio e il codec audio 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;