diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /sound/usb/mixer.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r-- | sound/usb/mixer.c | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 3ed3901369ce..c22fa76e363a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include "mixer.h" | 61 | #include "mixer.h" |
62 | #include "helper.h" | 62 | #include "helper.h" |
63 | #include "mixer_quirks.h" | 63 | #include "mixer_quirks.h" |
64 | #include "power.h" | ||
64 | 65 | ||
65 | #define MAX_ID_ELEMS 256 | 66 | #define MAX_ID_ELEMS 256 |
66 | 67 | ||
@@ -85,17 +86,7 @@ struct mixer_build { | |||
85 | const struct usbmix_selector_map *selector_map; | 86 | const struct usbmix_selector_map *selector_map; |
86 | }; | 87 | }; |
87 | 88 | ||
88 | enum { | 89 | /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ |
89 | USB_MIXER_BOOLEAN, | ||
90 | USB_MIXER_INV_BOOLEAN, | ||
91 | USB_MIXER_S8, | ||
92 | USB_MIXER_U8, | ||
93 | USB_MIXER_S16, | ||
94 | USB_MIXER_U16, | ||
95 | }; | ||
96 | |||
97 | |||
98 | /*E-mu 0202(0404) eXtension Unit(XU) control*/ | ||
99 | enum { | 90 | enum { |
100 | USB_XU_CLOCK_RATE = 0xe301, | 91 | USB_XU_CLOCK_RATE = 0xe301, |
101 | USB_XU_CLOCK_SOURCE = 0xe302, | 92 | USB_XU_CLOCK_SOURCE = 0xe302, |
@@ -295,16 +286,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
295 | unsigned char buf[2]; | 286 | unsigned char buf[2]; |
296 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 287 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
297 | int timeout = 10; | 288 | int timeout = 10; |
289 | int err; | ||
298 | 290 | ||
291 | err = snd_usb_autoresume(cval->mixer->chip); | ||
292 | if (err < 0) | ||
293 | return -EIO; | ||
299 | while (timeout-- > 0) { | 294 | while (timeout-- > 0) { |
300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 295 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 296 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
302 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 297 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
303 | buf, val_len, 100) >= val_len) { | 298 | buf, val_len, 100) >= val_len) { |
304 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 299 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
300 | snd_usb_autosuspend(cval->mixer->chip); | ||
305 | return 0; | 301 | return 0; |
306 | } | 302 | } |
307 | } | 303 | } |
304 | snd_usb_autosuspend(cval->mixer->chip); | ||
308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 305 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
309 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 306 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
310 | return -EINVAL; | 307 | return -EINVAL; |
@@ -328,12 +325,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
328 | 325 | ||
329 | memset(buf, 0, sizeof(buf)); | 326 | memset(buf, 0, sizeof(buf)); |
330 | 327 | ||
328 | ret = snd_usb_autoresume(chip) ? -EIO : 0; | ||
329 | if (ret) | ||
330 | goto error; | ||
331 | |||
331 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 332 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
332 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 333 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
333 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 334 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
334 | buf, size, 1000); | 335 | buf, size, 1000); |
336 | snd_usb_autosuspend(chip); | ||
335 | 337 | ||
336 | if (ret < 0) { | 338 | if (ret < 0) { |
339 | error: | ||
337 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 340 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
338 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 341 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
339 | return ret; | 342 | return ret; |
@@ -413,7 +416,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
413 | { | 416 | { |
414 | struct snd_usb_audio *chip = cval->mixer->chip; | 417 | struct snd_usb_audio *chip = cval->mixer->chip; |
415 | unsigned char buf[2]; | 418 | unsigned char buf[2]; |
416 | int val_len, timeout = 10; | 419 | int val_len, err, timeout = 10; |
417 | 420 | ||
418 | if (cval->mixer->protocol == UAC_VERSION_1) { | 421 | if (cval->mixer->protocol == UAC_VERSION_1) { |
419 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 422 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
@@ -433,13 +436,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
433 | value_set = convert_bytes_value(cval, value_set); | 436 | value_set = convert_bytes_value(cval, value_set); |
434 | buf[0] = value_set & 0xff; | 437 | buf[0] = value_set & 0xff; |
435 | buf[1] = (value_set >> 8) & 0xff; | 438 | buf[1] = (value_set >> 8) & 0xff; |
439 | err = snd_usb_autoresume(chip); | ||
440 | if (err < 0) | ||
441 | return -EIO; | ||
436 | while (timeout-- > 0) | 442 | while (timeout-- > 0) |
437 | if (snd_usb_ctl_msg(chip->dev, | 443 | if (snd_usb_ctl_msg(chip->dev, |
438 | usb_sndctrlpipe(chip->dev, 0), request, | 444 | usb_sndctrlpipe(chip->dev, 0), request, |
439 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 445 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
440 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 446 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
441 | buf, val_len, 100) >= 0) | 447 | buf, val_len, 100) >= 0) { |
448 | snd_usb_autosuspend(chip); | ||
442 | return 0; | 449 | return 0; |
450 | } | ||
451 | snd_usb_autosuspend(chip); | ||
443 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 452 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
444 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 453 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); |
445 | return -EINVAL; | 454 | return -EINVAL; |
@@ -516,20 +525,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou | |||
516 | * if failed, give up and free the control instance. | 525 | * if failed, give up and free the control instance. |
517 | */ | 526 | */ |
518 | 527 | ||
519 | static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) | 528 | int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, |
529 | struct snd_kcontrol *kctl) | ||
520 | { | 530 | { |
521 | struct usb_mixer_elem_info *cval = kctl->private_data; | 531 | struct usb_mixer_elem_info *cval = kctl->private_data; |
522 | int err; | 532 | int err; |
523 | 533 | ||
524 | while (snd_ctl_find_id(state->chip->card, &kctl->id)) | 534 | while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) |
525 | kctl->id.index++; | 535 | kctl->id.index++; |
526 | if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { | 536 | if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { |
527 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); | 537 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); |
528 | return err; | 538 | return err; |
529 | } | 539 | } |
530 | cval->elem_id = &kctl->id; | 540 | cval->elem_id = &kctl->id; |
531 | cval->next_id_elem = state->mixer->id_elems[cval->id]; | 541 | cval->next_id_elem = mixer->id_elems[cval->id]; |
532 | state->mixer->id_elems[cval->id] = cval; | 542 | mixer->id_elems[cval->id] = cval; |
533 | return 0; | 543 | return 0; |
534 | } | 544 | } |
535 | 545 | ||
@@ -759,8 +769,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | |||
759 | */ | 769 | */ |
760 | static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | 770 | static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) |
761 | { | 771 | { |
762 | struct snd_usb_audio *chip = cval->mixer->chip; | ||
763 | |||
764 | /* for failsafe */ | 772 | /* for failsafe */ |
765 | cval->min = default_min; | 773 | cval->min = default_min; |
766 | cval->max = cval->min + 1; | 774 | cval->max = cval->min + 1; |
@@ -783,7 +791,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
783 | if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 791 | if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
784 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 792 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
785 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", | 793 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
786 | cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id); | 794 | cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id); |
787 | return -EINVAL; | 795 | return -EINVAL; |
788 | } | 796 | } |
789 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 797 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
@@ -967,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { | |||
967 | .put = NULL, | 975 | .put = NULL, |
968 | }; | 976 | }; |
969 | 977 | ||
978 | /* This symbol is exported in order to allow the mixer quirks to | ||
979 | * hook up to the standard feature unit control mechanism */ | ||
980 | struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl; | ||
970 | 981 | ||
971 | /* | 982 | /* |
972 | * build a feature control | 983 | * build a feature control |
@@ -989,6 +1000,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
989 | struct snd_kcontrol *kctl; | 1000 | struct snd_kcontrol *kctl; |
990 | struct usb_mixer_elem_info *cval; | 1001 | struct usb_mixer_elem_info *cval; |
991 | const struct usbmix_name_map *map; | 1002 | const struct usbmix_name_map *map; |
1003 | unsigned int range; | ||
992 | 1004 | ||
993 | control++; /* change from zero-based to 1-based value */ | 1005 | control++; /* change from zero-based to 1-based value */ |
994 | 1006 | ||
@@ -1079,11 +1091,13 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1079 | append_ctl_name(kctl, control == UAC_FU_MUTE ? | 1091 | append_ctl_name(kctl, control == UAC_FU_MUTE ? |
1080 | " Switch" : " Volume"); | 1092 | " Switch" : " Volume"); |
1081 | if (control == UAC_FU_VOLUME) { | 1093 | if (control == UAC_FU_VOLUME) { |
1082 | kctl->tlv.c = mixer_vol_tlv; | ||
1083 | kctl->vd[0].access |= | ||
1084 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1085 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1086 | check_mapped_dB(map, cval); | 1094 | check_mapped_dB(map, cval); |
1095 | if (cval->dBmin < cval->dBmax) { | ||
1096 | kctl->tlv.c = mixer_vol_tlv; | ||
1097 | kctl->vd[0].access |= | ||
1098 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
1099 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
1100 | } | ||
1087 | } | 1101 | } |
1088 | break; | 1102 | break; |
1089 | 1103 | ||
@@ -1123,6 +1137,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1123 | } | 1137 | } |
1124 | break; | 1138 | break; |
1125 | 1139 | ||
1140 | case USB_ID(0x046d, 0x0808): | ||
1126 | case USB_ID(0x046d, 0x0809): | 1141 | case USB_ID(0x046d, 0x0809): |
1127 | case USB_ID(0x046d, 0x0991): | 1142 | case USB_ID(0x046d, 0x0991): |
1128 | /* Most audio usb devices lie about volume resolution. | 1143 | /* Most audio usb devices lie about volume resolution. |
@@ -1138,9 +1153,24 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1138 | 1153 | ||
1139 | } | 1154 | } |
1140 | 1155 | ||
1156 | range = (cval->max - cval->min) / cval->res; | ||
1157 | /* Are there devices with volume range more than 255? I use a bit more | ||
1158 | * to be sure. 384 is a resolution magic number found on Logitech | ||
1159 | * devices. It will definitively catch all buggy Logitech devices. | ||
1160 | */ | ||
1161 | if (range > 384) { | ||
1162 | snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " | ||
1163 | "volume range (=%u), cval->res is probably wrong.", | ||
1164 | range); | ||
1165 | snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " | ||
1166 | "val = %d/%d/%d", cval->id, | ||
1167 | kctl->id.name, cval->channels, | ||
1168 | cval->min, cval->max, cval->res); | ||
1169 | } | ||
1170 | |||
1141 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1171 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
1142 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 1172 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
1143 | add_control_to_empty(state, kctl); | 1173 | snd_usb_mixer_add_control(state->mixer, kctl); |
1144 | } | 1174 | } |
1145 | 1175 | ||
1146 | 1176 | ||
@@ -1148,7 +1178,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1148 | /* | 1178 | /* |
1149 | * parse a feature unit | 1179 | * parse a feature unit |
1150 | * | 1180 | * |
1151 | * most of controlls are defined here. | 1181 | * most of controls are defined here. |
1152 | */ | 1182 | */ |
1153 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) | 1183 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) |
1154 | { | 1184 | { |
@@ -1304,7 +1334,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, | |||
1304 | 1334 | ||
1305 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1335 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", |
1306 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1336 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1307 | add_control_to_empty(state, kctl); | 1337 | snd_usb_mixer_add_control(state->mixer, kctl); |
1308 | } | 1338 | } |
1309 | 1339 | ||
1310 | 1340 | ||
@@ -1568,7 +1598,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1568 | cval->initialized = 1; | 1598 | cval->initialized = 1; |
1569 | } else { | 1599 | } else { |
1570 | if (type == USB_XU_CLOCK_RATE) { | 1600 | if (type == USB_XU_CLOCK_RATE) { |
1571 | /* E-Mu USB 0404/0202/TrackerPre | 1601 | /* E-Mu USB 0404/0202/TrackerPre/0204 |
1572 | * samplerate control quirk | 1602 | * samplerate control quirk |
1573 | */ | 1603 | */ |
1574 | cval->min = 0; | 1604 | cval->min = 0; |
@@ -1605,7 +1635,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw | |||
1605 | 1635 | ||
1606 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1636 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1607 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1637 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1608 | if ((err = add_control_to_empty(state, kctl)) < 0) | 1638 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) |
1609 | return err; | 1639 | return err; |
1610 | } | 1640 | } |
1611 | return 0; | 1641 | return 0; |
@@ -1635,17 +1665,11 @@ static int parse_audio_extension_unit(struct mixer_build *state, int unitid, voi | |||
1635 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 1665 | static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
1636 | { | 1666 | { |
1637 | struct usb_mixer_elem_info *cval = kcontrol->private_data; | 1667 | struct usb_mixer_elem_info *cval = kcontrol->private_data; |
1638 | char **itemlist = (char **)kcontrol->private_value; | 1668 | const char **itemlist = (const char **)kcontrol->private_value; |
1639 | 1669 | ||
1640 | if (snd_BUG_ON(!itemlist)) | 1670 | if (snd_BUG_ON(!itemlist)) |
1641 | return -EINVAL; | 1671 | return -EINVAL; |
1642 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1672 | return snd_ctl_enum_info(uinfo, 1, cval->max, itemlist); |
1643 | uinfo->count = 1; | ||
1644 | uinfo->value.enumerated.items = cval->max; | ||
1645 | if ((int)uinfo->value.enumerated.item >= cval->max) | ||
1646 | uinfo->value.enumerated.item = cval->max - 1; | ||
1647 | strcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item]); | ||
1648 | return 0; | ||
1649 | } | 1673 | } |
1650 | 1674 | ||
1651 | /* get callback for selector unit */ | 1675 | /* get callback for selector unit */ |
@@ -1828,7 +1852,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void | |||
1828 | 1852 | ||
1829 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 1853 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
1830 | cval->id, kctl->id.name, desc->bNrInPins); | 1854 | cval->id, kctl->id.name, desc->bNrInPins); |
1831 | if ((err = add_control_to_empty(state, kctl)) < 0) | 1855 | if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) |
1832 | return err; | 1856 | return err; |
1833 | 1857 | ||
1834 | return 0; | 1858 | return 0; |
@@ -2066,8 +2090,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2066 | { | 2090 | { |
2067 | struct usb_mixer_interface *mixer = urb->context; | 2091 | struct usb_mixer_interface *mixer = urb->context; |
2068 | int len = urb->actual_length; | 2092 | int len = urb->actual_length; |
2093 | int ustatus = urb->status; | ||
2069 | 2094 | ||
2070 | if (urb->status != 0) | 2095 | if (ustatus != 0) |
2071 | goto requeue; | 2096 | goto requeue; |
2072 | 2097 | ||
2073 | if (mixer->protocol == UAC_VERSION_1) { | 2098 | if (mixer->protocol == UAC_VERSION_1) { |
@@ -2108,12 +2133,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2108 | } | 2133 | } |
2109 | 2134 | ||
2110 | requeue: | 2135 | requeue: |
2111 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | 2136 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { |
2112 | urb->dev = mixer->chip->dev; | 2137 | urb->dev = mixer->chip->dev; |
2113 | usb_submit_urb(urb, GFP_ATOMIC); | 2138 | usb_submit_urb(urb, GFP_ATOMIC); |
2114 | } | 2139 | } |
2115 | } | 2140 | } |
2116 | 2141 | ||
2142 | /* stop any bus activity of a mixer */ | ||
2143 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) | ||
2144 | { | ||
2145 | usb_kill_urb(mixer->urb); | ||
2146 | usb_kill_urb(mixer->rc_urb); | ||
2147 | } | ||
2148 | |||
2149 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) | ||
2150 | { | ||
2151 | int err; | ||
2152 | |||
2153 | if (mixer->urb) { | ||
2154 | err = usb_submit_urb(mixer->urb, GFP_NOIO); | ||
2155 | if (err < 0) | ||
2156 | return err; | ||
2157 | } | ||
2158 | |||
2159 | return 0; | ||
2160 | } | ||
2161 | |||
2117 | /* create the handler for the optional status interrupt endpoint */ | 2162 | /* create the handler for the optional status interrupt endpoint */ |
2118 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | 2163 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) |
2119 | { | 2164 | { |