diff mbox

[v1,3/6] ALSA: usb: UAC3. Add initial mixer support.

Message ID 20171219091411.16267-4-jorge.sanjuan@codethink.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Jorge Sanjuan Dec. 19, 2017, 9:14 a.m. UTC
Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 include/uapi/linux/usb/audio.h | 13 ++++++++++---
 sound/usb/mixer.c              | 24 ++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)
diff mbox

Patch

diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index ca33f47a2fd4..24a41afe6bae 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -292,9 +292,16 @@  static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor
 static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
 					      int protocol)
 {
-	return (protocol == UAC_VERSION_1) ?
-		&desc->baSourceID[desc->bNrInPins + 4] :
-		&desc->baSourceID[desc->bNrInPins + 6];
+	switch (protocol) {
+	case UAC_VERSION_1:
+		return &desc->baSourceID[desc->bNrInPins + 4];
+	case UAC_VERSION_2:
+		return &desc->baSourceID[desc->bNrInPins + 6];
+	case UAC_VERSION_3:
+		return &desc->baSourceID[desc->bNrInPins + 2];
+	default:
+		return NULL;
+	}
 }
 
 static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index c34a1f74ea56..4158be9ef43f 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -847,6 +847,30 @@  static int check_input_term(struct mixer_build *state, int id,
 				term->name = le16_to_cpu(d->wClockSourceStr);
 				return 0;
 			}
+			case UAC3_MIXER_UNIT: {
+				struct uac_mixer_unit_descriptor *d = p1;
+				struct uac3_cluster_header_descriptor c_header;
+				u16 cluster_id;
+
+				cluster_id = le16_to_cpu(d->baSourceID[d->bNrInPins]);
+
+				err = snd_usb_ctl_msg(state->chip->dev,
+						usb_rcvctrlpipe(state->chip->dev, 0),
+						UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
+						USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+						cluster_id,
+						snd_usb_ctrl_intf(state->chip),
+						&c_header, sizeof(c_header));
+				if (err < 0)
+					return err;
+				else if (err != sizeof(c_header))
+					return -EIO;
+
+				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->channels = c_header.bNrChannels;
+
+				return 0;
+			}
 			default:
 				return -ENODEV;
 			}