This patch adds some definitions for audio class v2.
Unfortunately, the UNIT types PROCESSING_UNIT and EXTENSION_UNIT have
different numerical representations in both standards, so there is need
for a _V1 add-on now. usbmixer.c is changed accordingly.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
#define USB_SUBCLASS_AUDIOSTREAMING 0x02
#define USB_SUBCLASS_MIDISTREAMING 0x03
+#define UAC_VERSION_1 0x00
+#define UAC_VERSION_2 0x20
+
/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
#define UAC_HEADER 0x01
#define UAC_INPUT_TERMINAL 0x02
__le16 wFormatTag; /* The Audio Data Format */
} __attribute__ ((packed));
+struct uac_as_header_descriptor_v2 {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubtype;
+ __u8 bTerminalLink;
+ __u8 bmControls;
+ __u8 bFormatType;
+ __u32 bmFormats;
+ __u8 bNrChannels;
+ __u32 bmChannelConfig;
+ __u8 iChannelNames;
+} __attribute__((packed));
+
#define UAC_DT_AS_HEADER_SIZE 7
/* Formats - A.1.1 Audio Data Format Type I Codes */
#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3))
+struct uac_format_type_i_ext_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubtype;
+ __u8 bSubslotSize;
+ __u8 bFormatType;
+ __u8 bBitResolution;
+ __u8 bHeaderLength;
+ __u8 bControlSize;
+ __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+
/* Formats - Audio Data Format Type I Codes */
struct uac_format_type_ii_discrete_descriptor {
__u8 tSamFreq[][3];
} __attribute__((packed));
+struct uac_format_type_ii_ext_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubtype;
+ __u8 bFormatType;
+ __u16 wMaxBitRate;
+ __u16 wSamplesPerFrame;
+ __u8 bHeaderLength;
+ __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+
/* Formats - A.2 Format Type Codes */
#define UAC_FORMAT_TYPE_UNDEFINED 0x0
#define UAC_FORMAT_TYPE_I 0x1
#define UAC_FORMAT_TYPE_II 0x2
#define UAC_FORMAT_TYPE_III 0x3
+#define UAC_EXT_FORMAT_TYPE_I 0x81
+#define UAC_EXT_FORMAT_TYPE_II 0x82
+#define UAC_EXT_FORMAT_TYPE_III 0x83
struct uac_iso_endpoint_descriptor {
__u8 bLength; /* in bytes: 7 */
#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02
#define UAC_EP_CS_ATTR_FILL_MAX 0x80
+/* Audio class v2.0: CLOCK_SOURCE descriptor */
+
+struct uac_clock_source_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubtype;
+ __u8 bClockID;
+ __u8 bmAttributes;
+ __u8 bmControls;
+ __u8 bAssocTerminal;
+ __u8 iClockSource;
+} __attribute__((packed));
+
/* A.10.2 Feature Unit Control Selectors */
struct uac_feature_unit_descriptor {
#define MIXER_UNIT 0x04
#define SELECTOR_UNIT 0x05
#define FEATURE_UNIT 0x06
-#define PROCESSING_UNIT 0x07
-#define EXTENSION_UNIT 0x08
+#define PROCESSING_UNIT_V1 0x07
+#define EXTENSION_UNIT_V1 0x08
+
+/* audio class v2 */
+#define EFFECT_UNIT 0x07
+#define PROCESSING_UNIT_V2 0x08
+#define EXTENSION_UNIT_V2 0x09
+#define CLOCK_SOURCE 0x0a
+#define CLOCK_SELECTOR 0x0b
+#define CLOCK_MULTIPLIER 0x0c
+#define SAMPLE_RATE_CONVERTER 0x0d
#define AS_GENERAL 0x01
#define FORMAT_TYPE 0x02
#define EP_CS_ATTR_PITCH_CONTROL 0x02
#define EP_CS_ATTR_FILL_MAX 0x80
-/* Audio Class specific Request Codes */
+/* Audio Class specific Request Codes (v1) */
#define SET_CUR 0x01
#define GET_CUR 0x81
#define GET_MEM 0x85
#define GET_STAT 0xff
+/* Audio Class specific Request Codes (v2) */
+#define CS_CUR 0x01
+#define CS_RANGE 0x02
+
/* Terminal Control Selectors */
#define COPY_PROTECT_CONTROL 0x01
p = NULL;
while ((p = snd_usb_find_desc(state->buffer, state->buflen, p,
USB_DT_CS_INTERFACE)) != NULL) {
- if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit)
+ if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT_V1 && p[3] == unit)
return p;
}
return NULL;
switch (iterm->type >> 16) {
case SELECTOR_UNIT:
strcpy(name, "Selector"); return 8;
- case PROCESSING_UNIT:
+ case PROCESSING_UNIT_V1:
strcpy(name, "Process Unit"); return 12;
- case EXTENSION_UNIT:
+ case EXTENSION_UNIT_V1:
strcpy(name, "Ext Unit"); return 8;
case MIXER_UNIT:
strcpy(name, "Mixer"); return 5;
term->id = id;
term->name = p1[9 + p1[0] - 1];
return 0;
- case PROCESSING_UNIT:
- case EXTENSION_UNIT:
+ case PROCESSING_UNIT_V1:
+ case EXTENSION_UNIT_V1:
if (p1[6] == 1) {
id = p1[7];
break; /* continue to parse */
return parse_audio_selector_unit(state, unitid, p1);
case FEATURE_UNIT:
return parse_audio_feature_unit(state, unitid, p1);
- case PROCESSING_UNIT:
+ case PROCESSING_UNIT_V1:
return parse_audio_processing_unit(state, unitid, p1);
- case EXTENSION_UNIT:
+ case EXTENSION_UNIT_V1:
return parse_audio_extension_unit(state, unitid, p1);
default:
snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);