| From 447cae58cecd69392b74a4a42cd0ab9cabd816af Mon Sep 17 00:00:00 2001 |
| From: Kirill Marinushkin <k.marinushkin@gmail.com> |
| Date: Mon, 29 Jan 2018 06:37:55 +0100 |
| Subject: ALSA: usb-audio: Fix UAC2 get_ctl request with a RANGE attribute |
| |
| From: Kirill Marinushkin <k.marinushkin@gmail.com> |
| |
| 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> |
| |
| --- |
| sound/usb/mixer.c | 18 +++++++++++------- |
| 1 file changed, 11 insertions(+), 7 deletions(-) |
| |
| --- a/sound/usb/mixer.c |
| +++ b/sound/usb/mixer.c |
| @@ -343,17 +343,20 @@ static int get_ctl_value_v2(struct usb_m |
| 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)); |
| @@ -386,16 +389,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; |
| } |