動詞を HD オーディオ コーデックとやり取りする
IOCTL_AZALIABUS_SENDVERBS IOCTL は、オーディオ アダプターのサウンド トポロジを定義するときに、Hdau.exe ピン構成ツールによって使用されます。 この IOCTL は他の目的には使用しないでください。 IOCTL_AZALIABUS_SENDVERBS に関するこの情報は、その設計と実装のみを文書化するために提供されます。 この IOCTL は、Windows 7 Hdaudio.sys オーディオ クラス ドライバーでサポートされています。
高解像度 (HD) オーディオ コーデックは、動詞を受信して応答できます。 これらの動詞とこれらの動詞に対するコーデックの応答は、HD オーディオ仕様 (HD Audio Specification) の一部として文書化されています。
Windows 7 以降のバージョンの Windows オペレーティング システムでは、HD オーディオ クラス ドライバーは、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 の詳細については、Windows SDK の Devioctl.h ヘッダー ファイルを参照してください。
オーディオ コーデックとの通信を開始するために、クラス ドライバーは、次のパラメーターを使用して 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 の呼び出しが成功すると、0 以外の値が返されます。 呼び出しが失敗した場合、または保留中 (すぐに処理されない) 場合、DeviceIoControl は 0 の値を返します。 クラス ドライバーは、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;
}
};
次の 2 つの構造体を動詞転送 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;