diff options
author | Kirill Marinushkin <k.marinushkin@gmail.com> | 2018-01-29 08:37:55 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-02-22 17:43:50 +0300 |
commit | 31cb8df3f8ea21d1d33d371b160fddd903888e19 (patch) | |
tree | a6c16352334a0b5098909b4f973e6b3f1e53a45b /sound/usb | |
parent | 3dc694f4a436ec5f8017161ff8e8a8e49856014d (diff) | |
download | linux-31cb8df3f8ea21d1d33d371b160fddd903888e19.tar.xz |
ALSA: usb-audio: Fix UAC2 get_ctl request with a RANGE attribute
commit 447cae58cecd69392b74a4a42cd0ab9cabd816af upstream.
The layout of the UAC2 Control request and response varies depending on
the request type. With the current implementation, only the Layout 2
Parameter Block (with the 2-byte sized RANGE attribute) is handled
properly. For the Control requests with the 1-byte sized RANGE attribute
(Bass Control, Mid Control, Tremble Control), the response is parsed
incorrectly.
This commit:
* fixes the wLength field value in the request
* fixes parsing the range values from the response
Fixes: 23caaf19b11e ("ALSA: usb-mixer: Add support for Audio Class v2.0")
Signed-off-by: Kirill Marinushkin <k.marinushkin@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/mixer.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 08015c139116..dedf8eb4570e 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -344,17 +344,20 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) { struct snd_usb_audio *chip = cval->head.mixer->chip; - unsigned char buf[4 + 3 * sizeof(__u32)]; /* enough space for one range */ + /* enough space for one range */ + unsigned char buf[sizeof(__u16) + 3 * sizeof(__u32)]; unsigned char *val; - int idx = 0, ret, size; + int idx = 0, ret, val_size, size; __u8 bRequest; + val_size = uac2_ctl_value_size(cval->val_type); + if (request == UAC_GET_CUR) { bRequest = UAC2_CS_CUR; - size = uac2_ctl_value_size(cval->val_type); + size = val_size; } else { bRequest = UAC2_CS_RANGE; - size = sizeof(buf); + size = sizeof(__u16) + 3 * val_size; } memset(buf, 0, sizeof(buf)); @@ -387,16 +390,17 @@ error: val = buf + sizeof(__u16); break; case UAC_GET_MAX: - val = buf + sizeof(__u16) * 2; + val = buf + sizeof(__u16) + val_size; break; case UAC_GET_RES: - val = buf + sizeof(__u16) * 3; + val = buf + sizeof(__u16) + val_size * 2; break; default: return -EINVAL; } - *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); + *value_ret = convert_signed_value(cval, + snd_usb_combine_bytes(val, val_size)); return 0; } |