diff options
author | Kirill Marinushkin <k.marinushkin@gmail.com> | 2018-01-29 00:37:55 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-02-12 03:07:29 -0500 |
commit | 447cae58cecd69392b74a4a42cd0ab9cabd816af (patch) | |
tree | 4654851a3c4cab88496c6d7371473f9830991358 /sound/usb | |
parent | 2bda7141b89aa35308da69aac7f486fa81db73ba (diff) |
ALSA: usb-audio: Fix UAC2 get_ctl request with a RANGE attribute
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>
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 9afb8ab524c7..06b22624ab7a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -347,17 +347,20 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, | |||
347 | int validx, int *value_ret) | 347 | int validx, int *value_ret) |
348 | { | 348 | { |
349 | struct snd_usb_audio *chip = cval->head.mixer->chip; | 349 | struct snd_usb_audio *chip = cval->head.mixer->chip; |
350 | unsigned char buf[4 + 3 * sizeof(__u32)]; /* enough space for one range */ | 350 | /* enough space for one range */ |
351 | unsigned char buf[sizeof(__u16) + 3 * sizeof(__u32)]; | ||
351 | unsigned char *val; | 352 | unsigned char *val; |
352 | int idx = 0, ret, size; | 353 | int idx = 0, ret, val_size, size; |
353 | __u8 bRequest; | 354 | __u8 bRequest; |
354 | 355 | ||
356 | val_size = uac2_ctl_value_size(cval->val_type); | ||
357 | |||
355 | if (request == UAC_GET_CUR) { | 358 | if (request == UAC_GET_CUR) { |
356 | bRequest = UAC2_CS_CUR; | 359 | bRequest = UAC2_CS_CUR; |
357 | size = uac2_ctl_value_size(cval->val_type); | 360 | size = val_size; |
358 | } else { | 361 | } else { |
359 | bRequest = UAC2_CS_RANGE; | 362 | bRequest = UAC2_CS_RANGE; |
360 | size = sizeof(buf); | 363 | size = sizeof(__u16) + 3 * val_size; |
361 | } | 364 | } |
362 | 365 | ||
363 | memset(buf, 0, sizeof(buf)); | 366 | memset(buf, 0, sizeof(buf)); |
@@ -390,16 +393,17 @@ error: | |||
390 | val = buf + sizeof(__u16); | 393 | val = buf + sizeof(__u16); |
391 | break; | 394 | break; |
392 | case UAC_GET_MAX: | 395 | case UAC_GET_MAX: |
393 | val = buf + sizeof(__u16) * 2; | 396 | val = buf + sizeof(__u16) + val_size; |
394 | break; | 397 | break; |
395 | case UAC_GET_RES: | 398 | case UAC_GET_RES: |
396 | val = buf + sizeof(__u16) * 3; | 399 | val = buf + sizeof(__u16) + val_size * 2; |
397 | break; | 400 | break; |
398 | default: | 401 | default: |
399 | return -EINVAL; | 402 | return -EINVAL; |
400 | } | 403 | } |
401 | 404 | ||
402 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(val, sizeof(__u16))); | 405 | *value_ret = convert_signed_value(cval, |
406 | snd_usb_combine_bytes(val, val_size)); | ||
403 | 407 | ||
404 | return 0; | 408 | return 0; |
405 | } | 409 | } |