aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c71
1 files changed, 53 insertions, 18 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 696de5ac69be..c5447ff078b3 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -203,6 +203,10 @@ static int snd_usb_copy_string_desc(struct mixer_build *state,
203 int index, char *buf, int maxlen) 203 int index, char *buf, int maxlen)
204{ 204{
205 int len = usb_string(state->chip->dev, index, buf, maxlen - 1); 205 int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
206
207 if (len < 0)
208 return 0;
209
206 buf[len] = 0; 210 buf[len] = 0;
207 return len; 211 return len;
208} 212}
@@ -339,17 +343,20 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
339 int validx, int *value_ret) 343 int validx, int *value_ret)
340{ 344{
341 struct snd_usb_audio *chip = cval->head.mixer->chip; 345 struct snd_usb_audio *chip = cval->head.mixer->chip;
342 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)];
343 unsigned char *val; 348 unsigned char *val;
344 int idx = 0, ret, size; 349 int idx = 0, ret, val_size, size;
345 __u8 bRequest; 350 __u8 bRequest;
346 351
352 val_size = uac2_ctl_value_size(cval->val_type);
353
347 if (request == UAC_GET_CUR) { 354 if (request == UAC_GET_CUR) {
348 bRequest = UAC2_CS_CUR; 355 bRequest = UAC2_CS_CUR;
349 size = uac2_ctl_value_size(cval->val_type); 356 size = val_size;
350 } else { 357 } else {
351 bRequest = UAC2_CS_RANGE; 358 bRequest = UAC2_CS_RANGE;
352 size = sizeof(buf); 359 size = sizeof(__u16) + 3 * val_size;
353 } 360 }
354 361
355 memset(buf, 0, sizeof(buf)); 362 memset(buf, 0, sizeof(buf));
@@ -382,16 +389,17 @@ error:
382 val = buf + sizeof(__u16); 389 val = buf + sizeof(__u16);
383 break; 390 break;
384 case UAC_GET_MAX: 391 case UAC_GET_MAX:
385 val = buf + sizeof(__u16) * 2; 392 val = buf + sizeof(__u16) + val_size;
386 break; 393 break;
387 case UAC_GET_RES: 394 case UAC_GET_RES:
388 val = buf + sizeof(__u16) * 3; 395 val = buf + sizeof(__u16) + val_size * 2;
389 break; 396 break;
390 default: 397 default:
391 return -EINVAL; 398 return -EINVAL;
392 } 399 }
393 400
394 *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));
395 403
396 return 0; 404 return 0;
397} 405}
@@ -1397,6 +1405,12 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
1397 __u8 *bmaControls; 1405 __u8 *bmaControls;
1398 1406
1399 if (state->mixer->protocol == UAC_VERSION_1) { 1407 if (state->mixer->protocol == UAC_VERSION_1) {
1408 if (hdr->bLength < 7) {
1409 usb_audio_err(state->chip,
1410 "unit %u: invalid UAC_FEATURE_UNIT descriptor\n",
1411 unitid);
1412 return -EINVAL;
1413 }
1400 csize = hdr->bControlSize; 1414 csize = hdr->bControlSize;
1401 if (!csize) { 1415 if (!csize) {
1402 usb_audio_dbg(state->chip, 1416 usb_audio_dbg(state->chip,
@@ -1414,6 +1428,12 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
1414 } 1428 }
1415 } else { 1429 } else {
1416 struct uac2_feature_unit_descriptor *ftr = _ftr; 1430 struct uac2_feature_unit_descriptor *ftr = _ftr;
1431 if (hdr->bLength < 6) {
1432 usb_audio_err(state->chip,
1433 "unit %u: invalid UAC_FEATURE_UNIT descriptor\n",
1434 unitid);
1435 return -EINVAL;
1436 }
1417 csize = 4; 1437 csize = 4;
1418 channels = (hdr->bLength - 6) / 4 - 1; 1438 channels = (hdr->bLength - 6) / 4 - 1;
1419 bmaControls = ftr->bmaControls; 1439 bmaControls = ftr->bmaControls;
@@ -2014,7 +2034,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
2014 const struct usbmix_name_map *map; 2034 const struct usbmix_name_map *map;
2015 char **namelist; 2035 char **namelist;
2016 2036
2017 if (!desc->bNrInPins || desc->bLength < 5 + desc->bNrInPins) { 2037 if (desc->bLength < 5 || !desc->bNrInPins ||
2038 desc->bLength < 5 + desc->bNrInPins) {
2018 usb_audio_err(state->chip, 2039 usb_audio_err(state->chip,
2019 "invalid SELECTOR UNIT descriptor %d\n", unitid); 2040 "invalid SELECTOR UNIT descriptor %d\n", unitid);
2020 return -EINVAL; 2041 return -EINVAL;
@@ -2084,19 +2105,25 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
2084 kctl->private_value = (unsigned long)namelist; 2105 kctl->private_value = (unsigned long)namelist;
2085 kctl->private_free = usb_mixer_selector_elem_free; 2106 kctl->private_free = usb_mixer_selector_elem_free;
2086 2107
2087 nameid = uac_selector_unit_iSelector(desc); 2108 /* check the static mapping table at first */
2088 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); 2109 len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
2089 if (len) 2110 if (!len) {
2090 ; 2111 /* no mapping ? */
2091 else if (nameid) 2112 /* if iSelector is given, use it */
2092 snd_usb_copy_string_desc(state, nameid, kctl->id.name, 2113 nameid = uac_selector_unit_iSelector(desc);
2093 sizeof(kctl->id.name)); 2114 if (nameid)
2094 else { 2115 len = snd_usb_copy_string_desc(state, nameid,
2095 len = get_term_name(state, &state->oterm, 2116 kctl->id.name,
2117 sizeof(kctl->id.name));
2118 /* ... or pick up the terminal name at next */
2119 if (!len)
2120 len = get_term_name(state, &state->oterm,
2096 kctl->id.name, sizeof(kctl->id.name), 0); 2121 kctl->id.name, sizeof(kctl->id.name), 0);
2122 /* ... or use the fixed string "USB" as the last resort */
2097 if (!len) 2123 if (!len)
2098 strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); 2124 strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
2099 2125
2126 /* and add the proper suffix */
2100 if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) 2127 if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
2101 append_ctl_name(kctl, " Clock Source"); 2128 append_ctl_name(kctl, " Clock Source");
2102 else if ((state->oterm.type & 0xff00) == 0x0100) 2129 else if ((state->oterm.type & 0xff00) == 0x0100)
@@ -2161,6 +2188,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
2161 2188
2162static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) 2189static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
2163{ 2190{
2191 /* kill pending URBs */
2192 snd_usb_mixer_disconnect(mixer);
2193
2164 kfree(mixer->id_elems); 2194 kfree(mixer->id_elems);
2165 if (mixer->urb) { 2195 if (mixer->urb) {
2166 kfree(mixer->urb->transfer_buffer); 2196 kfree(mixer->urb->transfer_buffer);
@@ -2504,8 +2534,13 @@ _error:
2504 2534
2505void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) 2535void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer)
2506{ 2536{
2507 usb_kill_urb(mixer->urb); 2537 if (mixer->disconnected)
2508 usb_kill_urb(mixer->rc_urb); 2538 return;
2539 if (mixer->urb)
2540 usb_kill_urb(mixer->urb);
2541 if (mixer->rc_urb)
2542 usb_kill_urb(mixer->rc_urb);
2543 mixer->disconnected = true;
2509} 2544}
2510 2545
2511#ifdef CONFIG_PM 2546#ifdef CONFIG_PM