aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Marinushkin2018-01-28 23:37:55 -0600
committerGreg Kroah-Hartman2018-02-22 08:45:01 -0600
commit4c6e8dd5d2670c74669b1627eb18f6a4226993a3 (patch)
tree9cf3590ede517a8efa689c84bff0e4730e646de7
parentbc4c681fcaff86d73fe2dbda87be835d640dfa6f (diff)
downloadkernel-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.c18
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}