ALSA: usbaudio: introduce new types for audio class v2
Daniel Mack [Mon, 22 Feb 2010 22:49:10 +0000 (23:49 +0100)]
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>

include/linux/usb/audio.h
sound/usb/usbaudio.h
sound/usb/usbmixer.c

index 44f82d8..fb1a97b 100644 (file)
@@ -25,6 +25,9 @@
 #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
@@ -180,6 +183,19 @@ struct uac_as_header_descriptor_v1 {
        __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 */
@@ -232,6 +248,19 @@ struct uac_format_type_i_discrete_descriptor_##n {         \
 
 #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 {
@@ -245,11 +274,26 @@ 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 */
@@ -265,6 +309,19 @@ struct uac_iso_endpoint_descriptor {
 #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 {
index 9d8cea4..4f48293 100644 (file)
 #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
@@ -60,7 +69,7 @@
 #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
index 11636a6..ca79495 100644 (file)
@@ -286,7 +286,7 @@ static void *find_audio_control_unit(struct mixer_build *state, unsigned char un
        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;
@@ -607,9 +607,9 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
                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;
@@ -673,8 +673,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                        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 */
@@ -1747,9 +1747,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
                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]);