diff options
author | Kirill Marinushkin | 2018-01-28 23:37:55 -0600 |
---|---|---|
committer | Greg Kroah-Hartman | 2018-02-22 08:45:01 -0600 |
commit | 4c6e8dd5d2670c74669b1627eb18f6a4226993a3 (patch) | |
tree | 9cf3590ede517a8efa689c84bff0e4730e646de7 | |
parent | bc4c681fcaff86d73fe2dbda87be835d640dfa6f (diff) | |
download | kernel-omap-4c6e8dd5d2670c74669b1627eb18f6a4226993a3.tar.gz kernel-omap-4c6e8dd5d2670c74669b1627eb18f6a4226993a3.tar.xz kernel-omap-4c6e8dd5d2670c74669b1627eb18f6a4226993a3.zip |
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>
-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 c9ae29068c7c..c5447ff078b3 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -343,17 +343,20 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, | |||
343 | int validx, int *value_ret) | 343 | int validx, int *value_ret) |
344 | { | 344 | { |
345 | struct snd_usb_audio *chip = cval->head.mixer->chip; | 345 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
346 | unsigned char buf[4 + 3 * sizeof(__u32)]; /* enough space for one range */ | 346 | /* enough space for one range */ |
347 | unsigned char buf[sizeof(__u16) + 3 * sizeof(__u32)]; | ||
347 | unsigned char *val; | 348 | unsigned char *val; |
348 | int idx = 0, ret, size; | 349 | int idx = 0, ret, val_size, size; |
349 | __u8 bRequest; | 350 | __u8 bRequest; |
350 | 351 | ||
352 | val_size = uac2_ctl_value_size(cval->val_type); | ||
353 | |||
351 | if (request == UAC_GET_CUR) { | 354 | if (request == UAC_GET_CUR) { |
352 | bRequest = UAC2_CS_CUR; | 355 | bRequest = UAC2_CS_CUR; |
353 | size = uac2_ctl_value_size(cval->val_type); | 356 | size = val_size; |
354 | } else { | 357 | } else { |
355 | bRequest = UAC2_CS_RANGE; | 358 | bRequest = UAC2_CS_RANGE; |
356 | size = sizeof(buf); | 359 | size = sizeof(__u16) + 3 * val_size; |
357 | } | 360 | } |
358 | 361 | ||
359 | memset(buf, 0, sizeof(buf)); | 362 | memset(buf, 0, sizeof(buf)); |
@@ -386,16 +389,17 @@ error: | |||
386 | val = buf + sizeof(__u16); | 389 | val = buf + sizeof(__u16); |
387 | break; | 390 | break; |
388 | case UAC_GET_MAX: | 391 | case UAC_GET_MAX: |
389 | val = buf + sizeof(__u16) * 2; | 392 | val = buf + sizeof(__u16) + val_size; |
390 | break; | 393 | break; |
391 | case UAC_GET_RES: | 394 | case UAC_GET_RES: |
392 | val = buf + sizeof(__u16) * 3; | 395 | val = buf + sizeof(__u16) + val_size * 2; |
393 | break; | 396 | break; |
394 | default: | 397 | default: |
395 | return -EINVAL; | 398 | return -EINVAL; |
396 | } | 399 | } |
397 | 400 | ||
398 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); | 401 | *value_ret = convert_signed_value(cval, |
402 | snd_usb_combine_bytes(val, val_size)); | ||
399 | 403 | ||
400 | return 0; | 404 | return 0; |
401 | } | 405 | } |