aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/uapi/linux/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-07-04 16:31:12 +0200
committerTakashi Iwai <tiwai@suse.de>2019-07-05 08:06:47 +0200
commitca95c7bf3d29716916baccdc77c3c2284b703069 (patch)
tree13a802819035ac0c628b6a8e41976ba6eed842b3 /include/uapi/linux/usb
parentALSA: hda/ca0132 - remove redundant assignment to variable 'changed' (diff)
downloadwireguard-linux-ca95c7bf3d29716916baccdc77c3c2284b703069.tar.xz
wireguard-linux-ca95c7bf3d29716916baccdc77c3c2284b703069.zip
ALSA: usb-audio: Fix parse of UAC2 Extension Units
Extension Unit (XU) is used to have a compatible layout with Processing Unit (PU) on UAC1, and the usb-audio driver code assumed it for parsing the descriptors. Meanwhile, on UAC2, XU became slightly incompatible with PU; namely, XU has a one-byte bmControls bitmap while PU has two bytes bmControls bitmap. This incompatibility results in the read of a wrong address for the last iExtension field, which ended up with an incorrect string for the mixer element name, as recently reported for Focusrite Scarlett 18i20 device. This patch corrects this misalignment by introducing a couple of new macros and calling them depending on the descriptor type. Fixes: 23caaf19b11e ("ALSA: usb-mixer: Add support for Audio Class v2.0") Reported-by: Stefan Sauer <ensonic@hora-obscura.de> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'include/uapi/linux/usb')
-rw-r--r--include/uapi/linux/usb/audio.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index ddc5396800aa..76b7c3f6cd0d 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -450,6 +450,43 @@ static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_desc
}
}
+/*
+ * Extension Unit (XU) has almost compatible layout with Processing Unit, but
+ * on UAC2, it has a different bmControls size (bControlSize); it's 1 byte for
+ * XU while 2 bytes for PU. The last iExtension field is a one-byte index as
+ * well as iProcessing field of PU.
+ */
+static inline __u8 uac_extension_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
+ int protocol)
+{
+ switch (protocol) {
+ case UAC_VERSION_1:
+ return desc->baSourceID[desc->bNrInPins + 4];
+ case UAC_VERSION_2:
+ return 1; /* in UAC2, this value is constant */
+ case UAC_VERSION_3:
+ return 4; /* in UAC3, this value is constant */
+ default:
+ return 1;
+ }
+}
+
+static inline __u8 uac_extension_unit_iExtension(struct uac_processing_unit_descriptor *desc,
+ int protocol)
+{
+ __u8 control_size = uac_extension_unit_bControlSize(desc, protocol);
+
+ switch (protocol) {
+ case UAC_VERSION_1:
+ case UAC_VERSION_2:
+ default:
+ return *(uac_processing_unit_bmControls(desc, protocol)
+ + control_size);
+ case UAC_VERSION_3:
+ return 0; /* UAC3 does not have this field */
+ }
+}
+
/* 4.5.2 Class-Specific AS Interface Descriptor */
struct uac1_as_header_descriptor {
__u8 bLength; /* in bytes: 7 */