Skip to content

Commit

Permalink
ALSA: usb-mixer: Add support for Audio Class v2.0
Browse files Browse the repository at this point in the history
USB Audio Class v2.0 compliant devices have different descriptors and a
different way of setting/getting min/max/res/cur properties. This patch
adds support for them.

Signed-off-by: Daniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Daniel Mack authored and Takashi Iwai committed Mar 12, 2010
1 parent 99fc864 commit 23caaf1
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 100 deletions.
47 changes: 47 additions & 0 deletions include/linux/usb/audio-v2.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,53 @@ struct uac_clock_selector_descriptor {
__u8 baCSourceID[];
} __attribute__((packed));

/* 4.7.2.4 Input terminal descriptor */

struct uac2_input_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bCSourceID;
__u8 bNrChannels;
__u32 bmChannelConfig;
__u8 iChannelNames;
__u16 bmControls;
__u8 iTerminal;
} __attribute__((packed));

/* 4.7.2.5 Output terminal descriptor */

struct uac2_output_terminal_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bTerminalID;
__u16 wTerminalType;
__u8 bAssocTerminal;
__u8 bSourceID;
__u8 bCSourceID;
__u16 bmControls;
__u8 iTerminal;
} __attribute__((packed));



/* 4.7.2.8 Feature Unit Descriptor */

struct uac2_feature_unit_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
__u8 bUnitID;
__u8 bSourceID;
/* bmaControls is actually u32,
* but u8 is needed for the hybrid parser */
__u8 bmaControls[0]; /* variable length */
} __attribute__((packed));

/* 4.9.2 Class-Specific AS Interface Descriptor */

struct uac_as_header_descriptor_v2 {
Expand Down
71 changes: 51 additions & 20 deletions include/linux/usb/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,33 @@ static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *
return desc->baSourceID[desc->bNrInPins];
}

static inline __u16 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc)
static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
desc->baSourceID[desc->bNrInPins + 1];
if (protocol == UAC_VERSION_1)
return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
desc->baSourceID[desc->bNrInPins + 1];
else
return (desc->baSourceID[desc->bNrInPins + 4] << 24) |
(desc->baSourceID[desc->bNrInPins + 3] << 16) |
(desc->baSourceID[desc->bNrInPins + 2] << 8) |
(desc->baSourceID[desc->bNrInPins + 1]);
}

static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc)
static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
return desc->baSourceID[desc->bNrInPins + 3];
return (protocol == UAC_VERSION_1) ?
desc->baSourceID[desc->bNrInPins + 3] :
desc->baSourceID[desc->bNrInPins + 5];
}

static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc)
static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
return &desc->baSourceID[desc->bNrInPins + 4];
return (protocol == UAC_VERSION_1) ?
&desc->baSourceID[desc->bNrInPins + 4] :
&desc->baSourceID[desc->bNrInPins + 6];
}

static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
Expand Down Expand Up @@ -267,36 +280,54 @@ static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_de
return desc->baSourceID[desc->bNrInPins];
}

static inline __u16 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc)
static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc,
int protocol)
{
return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
desc->baSourceID[desc->bNrInPins + 1];
if (protocol == UAC_VERSION_1)
return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
desc->baSourceID[desc->bNrInPins + 1];
else
return (desc->baSourceID[desc->bNrInPins + 4] << 24) |
(desc->baSourceID[desc->bNrInPins + 3] << 16) |
(desc->baSourceID[desc->bNrInPins + 2] << 8) |
(desc->baSourceID[desc->bNrInPins + 1]);
}

static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc)
static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc,
int protocol)
{
return desc->baSourceID[desc->bNrInPins + 3];
return (protocol == UAC_VERSION_1) ?
desc->baSourceID[desc->bNrInPins + 3] :
desc->baSourceID[desc->bNrInPins + 5];
}

static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc)
static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
int protocol)
{
return desc->baSourceID[desc->bNrInPins + 4];
return (protocol == UAC_VERSION_1) ?
desc->baSourceID[desc->bNrInPins + 4] :
desc->baSourceID[desc->bNrInPins + 6];
}

static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc)
static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
int protocol)
{
return &desc->baSourceID[desc->bNrInPins + 5];
return (protocol == UAC_VERSION_1) ?
&desc->baSourceID[desc->bNrInPins + 5] :
&desc->baSourceID[desc->bNrInPins + 7];
}

static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc)
static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
int protocol)
{
__u8 control_size = uac_processing_unit_bControlSize(desc);
__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
return desc->baSourceID[desc->bNrInPins + control_size];
}

static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc)
static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
int protocol)
{
__u8 control_size = uac_processing_unit_bControlSize(desc);
__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
return &desc->baSourceID[desc->bNrInPins + control_size + 1];
}

Expand Down
Loading

0 comments on commit 23caaf1

Please sign in to comment.