HD 오디오 코덱과 동사 통신
IOCTL_AZALIABUS_SENDVERBS IOCTL은 오디오 어댑터에 대한 사운드 토폴로지 정의 시 Hdau.exe 핀 구성 도구에서 사용됩니다. 다른 용도로는 이 IOCTL을 사용하지 마세요. IOCTL_AZALIABUS_SENDVERBS 대한 이 정보는 디자인 및 구현만 문서화하기 위해 제공됩니다. 이 IOCTL은 Windows 7 Hdaudio.sys 오디오 클래스 드라이버에서 지원됩니다.
HD(고화질) 오디오 코덱은 동사를 수신하고 응답할 수 있습니다. 이러한 동사 및 이러한 동사에 대한 코덱의 응답은 HD 오디오 사양의 일부로 설명되어 있습니다.
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 동사를 보내고 받을 수 있습니다. 오디오 코덱과의 통신이 핀 구성에 관한 것이 아닌 경우 오디오 코덱은 동사 가져오기에만 응답합니다.
다음 예제에서는 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;