Commit 23caaf19 authored by Daniel Mack's avatar Daniel Mack Committed by Takashi Iwai

ALSA: usb-mixer: Add support for Audio Class v2.0

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: default avatarDaniel Mack <daniel@caiaq.de>
Cc: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 99fc8645
...@@ -43,6 +43,53 @@ struct uac_clock_selector_descriptor { ...@@ -43,6 +43,53 @@ struct uac_clock_selector_descriptor {
__u8 baCSourceID[]; __u8 baCSourceID[];
} __attribute__((packed)); } __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 */ /* 4.9.2 Class-Specific AS Interface Descriptor */
struct uac_as_header_descriptor_v2 { struct uac_as_header_descriptor_v2 {
......
...@@ -196,20 +196,33 @@ static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor * ...@@ -196,20 +196,33 @@ static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *
return desc->baSourceID[desc->bNrInPins]; 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) | if (protocol == UAC_VERSION_1)
desc->baSourceID[desc->bNrInPins + 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) static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
...@@ -267,36 +280,54 @@ static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_de ...@@ -267,36 +280,54 @@ static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_de
return desc->baSourceID[desc->bNrInPins]; 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) | if (protocol == UAC_VERSION_1)
desc->baSourceID[desc->bNrInPins + 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]; 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]; return &desc->baSourceID[desc->bNrInPins + control_size + 1];
} }
......
This diff is collapsed.
...@@ -10,6 +10,9 @@ struct usb_mixer_interface { ...@@ -10,6 +10,9 @@ struct usb_mixer_interface {
/* array[MAX_ID_ELEMS], indexed by unit id */ /* array[MAX_ID_ELEMS], indexed by unit id */
struct usb_mixer_elem_info **id_elems; struct usb_mixer_elem_info **id_elems;
/* the usb audio specification version this interface complies to */
int protocol;
/* Sound Blaster remote control stuff */ /* Sound Blaster remote control stuff */
const struct rc_config *rc_cfg; const struct rc_config *rc_cfg;
u32 rc_code; u32 rc_code;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment