diff options
-rw-r--r-- | sound/usb/usbaudio.c | 5 | ||||
-rw-r--r-- | sound/usb/usbaudio.h | 3 | ||||
-rw-r--r-- | sound/usb/usbmixer.c | 142 |
3 files changed, 105 insertions, 45 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index e4b91045ca16..eeb09bb8cbf3 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -3091,6 +3091,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
3091 | chip->card = card; | 3091 | chip->card = card; |
3092 | INIT_LIST_HEAD(&chip->pcm_list); | 3092 | INIT_LIST_HEAD(&chip->pcm_list); |
3093 | INIT_LIST_HEAD(&chip->midi_list); | 3093 | INIT_LIST_HEAD(&chip->midi_list); |
3094 | INIT_LIST_HEAD(&chip->mixer_list); | ||
3094 | 3095 | ||
3095 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 3096 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
3096 | snd_usb_audio_free(chip); | 3097 | snd_usb_audio_free(chip); |
@@ -3290,6 +3291,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3290 | list_for_each(p, &chip->midi_list) { | 3291 | list_for_each(p, &chip->midi_list) { |
3291 | snd_usbmidi_disconnect(p); | 3292 | snd_usbmidi_disconnect(p); |
3292 | } | 3293 | } |
3294 | /* release mixer resources */ | ||
3295 | list_for_each(p, &chip->mixer_list) { | ||
3296 | snd_usb_mixer_disconnect(p); | ||
3297 | } | ||
3293 | usb_chip[chip->index] = NULL; | 3298 | usb_chip[chip->index] = NULL; |
3294 | up(®ister_mutex); | 3299 | up(®ister_mutex); |
3295 | snd_card_free(card); | 3300 | snd_card_free(card); |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 14f7cf7e363c..41d842dab3e8 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -136,7 +136,7 @@ struct snd_usb_audio { | |||
136 | struct list_head midi_list; /* list of midi interfaces */ | 136 | struct list_head midi_list; /* list of midi interfaces */ |
137 | int next_midi_device; | 137 | int next_midi_device; |
138 | 138 | ||
139 | unsigned int ignore_ctl_error; /* for mixer */ | 139 | struct list_head mixer_list; /* list of mixer interfaces */ |
140 | }; | 140 | }; |
141 | 141 | ||
142 | /* | 142 | /* |
@@ -219,6 +219,7 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub | |||
219 | int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); | 219 | int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout); |
220 | 220 | ||
221 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); | 221 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif); |
222 | void snd_usb_mixer_disconnect(struct list_head *p); | ||
222 | 223 | ||
223 | int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); | 224 | int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk); |
224 | void snd_usbmidi_input_stop(struct list_head* p); | 225 | void snd_usbmidi_input_stop(struct list_head* p); |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index e601f4ba5f2c..7bbccebd76c6 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -50,6 +50,14 @@ typedef struct usb_audio_term usb_audio_term_t; | |||
50 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; | 50 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; |
51 | 51 | ||
52 | 52 | ||
53 | struct usb_mixer_interface { | ||
54 | snd_usb_audio_t *chip; | ||
55 | unsigned int ctrlif; | ||
56 | struct list_head list; | ||
57 | unsigned int ignore_ctl_error; | ||
58 | }; | ||
59 | |||
60 | |||
53 | struct usb_audio_term { | 61 | struct usb_audio_term { |
54 | int id; | 62 | int id; |
55 | int type; | 63 | int type; |
@@ -62,9 +70,9 @@ struct usbmix_name_map; | |||
62 | 70 | ||
63 | struct usb_mixer_build { | 71 | struct usb_mixer_build { |
64 | snd_usb_audio_t *chip; | 72 | snd_usb_audio_t *chip; |
73 | struct usb_mixer_interface *mixer; | ||
65 | unsigned char *buffer; | 74 | unsigned char *buffer; |
66 | unsigned int buflen; | 75 | unsigned int buflen; |
67 | unsigned int ctrlif; | ||
68 | unsigned short vendor; | 76 | unsigned short vendor; |
69 | unsigned short product; | 77 | unsigned short product; |
70 | DECLARE_BITMAP(unitbitmap, 256); | 78 | DECLARE_BITMAP(unitbitmap, 256); |
@@ -74,8 +82,7 @@ struct usb_mixer_build { | |||
74 | }; | 82 | }; |
75 | 83 | ||
76 | struct usb_mixer_elem_info { | 84 | struct usb_mixer_elem_info { |
77 | snd_usb_audio_t *chip; | 85 | struct usb_mixer_interface *mixer; |
78 | unsigned int ctrlif; | ||
79 | unsigned int id; | 86 | unsigned int id; |
80 | unsigned int control; /* CS or ICN (high byte) */ | 87 | unsigned int control; /* CS or ICN (high byte) */ |
81 | unsigned int cmask; /* channel mask bitmap: 0 = master */ | 88 | unsigned int cmask; /* channel mask bitmap: 0 = master */ |
@@ -317,16 +324,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
317 | int timeout = 10; | 324 | int timeout = 10; |
318 | 325 | ||
319 | while (timeout-- > 0) { | 326 | while (timeout-- > 0) { |
320 | if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0), | 327 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
328 | usb_rcvctrlpipe(cval->mixer->chip->dev, 0), | ||
321 | request, | 329 | request, |
322 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 330 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
323 | validx, cval->ctrlif | (cval->id << 8), | 331 | validx, cval->mixer->ctrlif | (cval->id << 8), |
324 | buf, val_len, 100) >= 0) { | 332 | buf, val_len, 100) >= 0) { |
325 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 333 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
326 | return 0; | 334 | return 0; |
327 | } | 335 | } |
328 | } | 336 | } |
329 | snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type); | 337 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
338 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); | ||
330 | return -EINVAL; | 339 | return -EINVAL; |
331 | } | 340 | } |
332 | 341 | ||
@@ -355,13 +364,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
355 | buf[0] = value_set & 0xff; | 364 | buf[0] = value_set & 0xff; |
356 | buf[1] = (value_set >> 8) & 0xff; | 365 | buf[1] = (value_set >> 8) & 0xff; |
357 | while (timeout -- > 0) | 366 | while (timeout -- > 0) |
358 | if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0), | 367 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
368 | usb_sndctrlpipe(cval->mixer->chip->dev, 0), | ||
359 | request, | 369 | request, |
360 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 370 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
361 | validx, cval->ctrlif | (cval->id << 8), | 371 | validx, cval->mixer->ctrlif | (cval->id << 8), |
362 | buf, val_len, 100) >= 0) | 372 | buf, val_len, 100) >= 0) |
363 | return 0; | 373 | return 0; |
364 | snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 374 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
375 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); | ||
365 | return -EINVAL; | 376 | return -EINVAL; |
366 | } | 377 | } |
367 | 378 | ||
@@ -401,12 +412,13 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou | |||
401 | * if failed, give up and free the control instance. | 412 | * if failed, give up and free the control instance. |
402 | */ | 413 | */ |
403 | 414 | ||
404 | static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl) | 415 | static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl) |
405 | { | 416 | { |
406 | int err; | 417 | int err; |
407 | while (snd_ctl_find_id(card, &kctl->id)) | 418 | |
419 | while (snd_ctl_find_id(state->chip->card, &kctl->id)) | ||
408 | kctl->id.index++; | 420 | kctl->id.index++; |
409 | if ((err = snd_ctl_add(card, kctl)) < 0) { | 421 | if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { |
410 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); | 422 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); |
411 | snd_ctl_free_one(kctl); | 423 | snd_ctl_free_one(kctl); |
412 | } | 424 | } |
@@ -624,7 +636,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min) | |||
624 | } | 636 | } |
625 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 637 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
626 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 638 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
627 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id); | 639 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
640 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | ||
628 | return -EINVAL; | 641 | return -EINVAL; |
629 | } | 642 | } |
630 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 643 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
@@ -684,7 +697,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
684 | if (cval->cmask & (1 << c)) { | 697 | if (cval->cmask & (1 << c)) { |
685 | err = get_cur_mix_value(cval, c + 1, &val); | 698 | err = get_cur_mix_value(cval, c + 1, &val); |
686 | if (err < 0) { | 699 | if (err < 0) { |
687 | if (cval->chip->ignore_ctl_error) { | 700 | if (cval->mixer->ignore_ctl_error) { |
688 | ucontrol->value.integer.value[0] = cval->min; | 701 | ucontrol->value.integer.value[0] = cval->min; |
689 | return 0; | 702 | return 0; |
690 | } | 703 | } |
@@ -700,7 +713,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
700 | /* master channel */ | 713 | /* master channel */ |
701 | err = get_cur_mix_value(cval, 0, &val); | 714 | err = get_cur_mix_value(cval, 0, &val); |
702 | if (err < 0) { | 715 | if (err < 0) { |
703 | if (cval->chip->ignore_ctl_error) { | 716 | if (cval->mixer->ignore_ctl_error) { |
704 | ucontrol->value.integer.value[0] = cval->min; | 717 | ucontrol->value.integer.value[0] = cval->min; |
705 | return 0; | 718 | return 0; |
706 | } | 719 | } |
@@ -726,7 +739,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
726 | if (cval->cmask & (1 << c)) { | 739 | if (cval->cmask & (1 << c)) { |
727 | err = get_cur_mix_value(cval, c + 1, &oval); | 740 | err = get_cur_mix_value(cval, c + 1, &oval); |
728 | if (err < 0) { | 741 | if (err < 0) { |
729 | if (cval->chip->ignore_ctl_error) | 742 | if (cval->mixer->ignore_ctl_error) |
730 | return 0; | 743 | return 0; |
731 | return err; | 744 | return err; |
732 | } | 745 | } |
@@ -743,7 +756,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
743 | } else { | 756 | } else { |
744 | /* master channel */ | 757 | /* master channel */ |
745 | err = get_cur_mix_value(cval, 0, &oval); | 758 | err = get_cur_mix_value(cval, 0, &oval); |
746 | if (err < 0 && cval->chip->ignore_ctl_error) | 759 | if (err < 0 && cval->mixer->ignore_ctl_error) |
747 | return 0; | 760 | return 0; |
748 | if (err < 0) | 761 | if (err < 0) |
749 | return err; | 762 | return err; |
@@ -795,8 +808,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
795 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 808 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
796 | return; | 809 | return; |
797 | } | 810 | } |
798 | cval->chip = state->chip; | 811 | cval->mixer = state->mixer; |
799 | cval->ctrlif = state->ctrlif; | ||
800 | cval->id = unitid; | 812 | cval->id = unitid; |
801 | cval->control = control; | 813 | cval->control = control; |
802 | cval->cmask = ctl_mask; | 814 | cval->cmask = ctl_mask; |
@@ -880,7 +892,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
880 | 892 | ||
881 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 893 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
882 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 894 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
883 | add_control_to_empty(state->chip->card, kctl); | 895 | add_control_to_empty(state, kctl); |
884 | } | 896 | } |
885 | 897 | ||
886 | 898 | ||
@@ -963,8 +975,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
963 | if (! cval) | 975 | if (! cval) |
964 | return; | 976 | return; |
965 | 977 | ||
966 | cval->chip = state->chip; | 978 | cval->mixer = state->mixer; |
967 | cval->ctrlif = state->ctrlif; | ||
968 | cval->id = unitid; | 979 | cval->id = unitid; |
969 | cval->control = in_ch + 1; /* based on 1 */ | 980 | cval->control = in_ch + 1; /* based on 1 */ |
970 | cval->val_type = USB_MIXER_S16; | 981 | cval->val_type = USB_MIXER_S16; |
@@ -995,7 +1006,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
995 | 1006 | ||
996 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1007 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", |
997 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1008 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
998 | add_control_to_empty(state->chip->card, kctl); | 1009 | add_control_to_empty(state, kctl); |
999 | } | 1010 | } |
1000 | 1011 | ||
1001 | 1012 | ||
@@ -1058,7 +1069,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1058 | int err, val; | 1069 | int err, val; |
1059 | 1070 | ||
1060 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1071 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1061 | if (err < 0 && cval->chip->ignore_ctl_error) { | 1072 | if (err < 0 && cval->mixer->ignore_ctl_error) { |
1062 | ucontrol->value.integer.value[0] = cval->min; | 1073 | ucontrol->value.integer.value[0] = cval->min; |
1063 | return 0; | 1074 | return 0; |
1064 | } | 1075 | } |
@@ -1077,7 +1088,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1077 | 1088 | ||
1078 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1089 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1079 | if (err < 0) { | 1090 | if (err < 0) { |
1080 | if (cval->chip->ignore_ctl_error) | 1091 | if (cval->mixer->ignore_ctl_error) |
1081 | return 0; | 1092 | return 0; |
1082 | return err; | 1093 | return err; |
1083 | } | 1094 | } |
@@ -1215,8 +1226,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1215 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1226 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1216 | return -ENOMEM; | 1227 | return -ENOMEM; |
1217 | } | 1228 | } |
1218 | cval->chip = state->chip; | 1229 | cval->mixer = state->mixer; |
1219 | cval->ctrlif = state->ctrlif; | ||
1220 | cval->id = unitid; | 1230 | cval->id = unitid; |
1221 | cval->control = valinfo->control; | 1231 | cval->control = valinfo->control; |
1222 | cval->val_type = valinfo->val_type; | 1232 | cval->val_type = valinfo->val_type; |
@@ -1257,7 +1267,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1257 | 1267 | ||
1258 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1268 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1259 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1269 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1260 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1270 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1261 | return err; | 1271 | return err; |
1262 | } | 1272 | } |
1263 | return 0; | 1273 | return 0; |
@@ -1305,7 +1315,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1305 | 1315 | ||
1306 | err = get_cur_ctl_value(cval, 0, &val); | 1316 | err = get_cur_ctl_value(cval, 0, &val); |
1307 | if (err < 0) { | 1317 | if (err < 0) { |
1308 | if (cval->chip->ignore_ctl_error) { | 1318 | if (cval->mixer->ignore_ctl_error) { |
1309 | ucontrol->value.enumerated.item[0] = 0; | 1319 | ucontrol->value.enumerated.item[0] = 0; |
1310 | return 0; | 1320 | return 0; |
1311 | } | 1321 | } |
@@ -1324,7 +1334,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1324 | 1334 | ||
1325 | err = get_cur_ctl_value(cval, 0, &oval); | 1335 | err = get_cur_ctl_value(cval, 0, &oval); |
1326 | if (err < 0) { | 1336 | if (err < 0) { |
1327 | if (cval->chip->ignore_ctl_error) | 1337 | if (cval->mixer->ignore_ctl_error) |
1328 | return 0; | 1338 | return 0; |
1329 | return err; | 1339 | return err; |
1330 | } | 1340 | } |
@@ -1402,8 +1412,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1402 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1412 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1403 | return -ENOMEM; | 1413 | return -ENOMEM; |
1404 | } | 1414 | } |
1405 | cval->chip = state->chip; | 1415 | cval->mixer = state->mixer; |
1406 | cval->ctrlif = state->ctrlif; | ||
1407 | cval->id = unitid; | 1416 | cval->id = unitid; |
1408 | cval->val_type = USB_MIXER_U8; | 1417 | cval->val_type = USB_MIXER_U8; |
1409 | cval->channels = 1; | 1418 | cval->channels = 1; |
@@ -1468,7 +1477,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1468 | 1477 | ||
1469 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 1478 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
1470 | cval->id, kctl->id.name, num_ins); | 1479 | cval->id, kctl->id.name, num_ins); |
1471 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1480 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1472 | return err; | 1481 | return err; |
1473 | 1482 | ||
1474 | return 0; | 1483 | return 0; |
@@ -1511,27 +1520,38 @@ static int parse_audio_unit(mixer_build_t *state, int unitid) | |||
1511 | } | 1520 | } |
1512 | } | 1521 | } |
1513 | 1522 | ||
1523 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | ||
1524 | { | ||
1525 | kfree(mixer); | ||
1526 | } | ||
1527 | |||
1528 | static int snd_usb_mixer_dev_free(snd_device_t *device) | ||
1529 | { | ||
1530 | struct usb_mixer_interface *mixer = device->device_data; | ||
1531 | snd_usb_mixer_free(mixer); | ||
1532 | return 0; | ||
1533 | } | ||
1534 | |||
1514 | /* | 1535 | /* |
1515 | * create mixer controls | 1536 | * create mixer controls |
1516 | * | 1537 | * |
1517 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers | 1538 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers |
1518 | */ | 1539 | */ |
1519 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | 1540 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1520 | { | 1541 | { |
1521 | unsigned char *desc; | 1542 | unsigned char *desc; |
1522 | mixer_build_t state; | 1543 | mixer_build_t state; |
1523 | int err; | 1544 | int err; |
1524 | const struct usbmix_ctl_map *map; | 1545 | const struct usbmix_ctl_map *map; |
1525 | struct usb_device_descriptor *dev = &chip->dev->descriptor; | 1546 | struct usb_device_descriptor *dev = &mixer->chip->dev->descriptor; |
1526 | struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | 1547 | struct usb_host_interface *hostif; |
1527 | |||
1528 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1529 | 1548 | ||
1549 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1530 | memset(&state, 0, sizeof(state)); | 1550 | memset(&state, 0, sizeof(state)); |
1531 | state.chip = chip; | 1551 | state.chip = mixer->chip; |
1552 | state.mixer = mixer; | ||
1532 | state.buffer = hostif->extra; | 1553 | state.buffer = hostif->extra; |
1533 | state.buflen = hostif->extralen; | 1554 | state.buflen = hostif->extralen; |
1534 | state.ctrlif = ctrlif; | ||
1535 | state.vendor = le16_to_cpu(dev->idVendor); | 1555 | state.vendor = le16_to_cpu(dev->idVendor); |
1536 | state.product = le16_to_cpu(dev->idProduct); | 1556 | state.product = le16_to_cpu(dev->idProduct); |
1537 | 1557 | ||
@@ -1540,13 +1560,10 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | |||
1540 | if (map->vendor == state.vendor && map->product == state.product) { | 1560 | if (map->vendor == state.vendor && map->product == state.product) { |
1541 | state.map = map->map; | 1561 | state.map = map->map; |
1542 | state.selector_map = map->selector_map; | 1562 | state.selector_map = map->selector_map; |
1543 | chip->ignore_ctl_error = map->ignore_ctl_error; | 1563 | mixer->ignore_ctl_error = map->ignore_ctl_error; |
1544 | break; | 1564 | break; |
1545 | } | 1565 | } |
1546 | } | 1566 | } |
1547 | #ifdef IGNORE_CTL_ERROR | ||
1548 | chip->ignore_ctl_error = 1; | ||
1549 | #endif | ||
1550 | 1567 | ||
1551 | desc = NULL; | 1568 | desc = NULL; |
1552 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { | 1569 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { |
@@ -1562,3 +1579,40 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | |||
1562 | } | 1579 | } |
1563 | return 0; | 1580 | return 0; |
1564 | } | 1581 | } |
1582 | |||
1583 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | ||
1584 | { | ||
1585 | static snd_device_ops_t dev_ops = { | ||
1586 | .dev_free = snd_usb_mixer_dev_free | ||
1587 | }; | ||
1588 | struct usb_mixer_interface *mixer; | ||
1589 | int err; | ||
1590 | |||
1591 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1592 | |||
1593 | mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL); | ||
1594 | if (!mixer) | ||
1595 | return -ENOMEM; | ||
1596 | mixer->chip = chip; | ||
1597 | mixer->ctrlif = ctrlif; | ||
1598 | #ifdef IGNORE_CTL_ERROR | ||
1599 | mixer->ignore_ctl_error = 1; | ||
1600 | #endif | ||
1601 | |||
1602 | if ((err = snd_usb_mixer_controls(mixer)) < 0) { | ||
1603 | snd_usb_mixer_free(mixer); | ||
1604 | return err; | ||
1605 | } | ||
1606 | |||
1607 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | ||
1608 | if (err < 0) { | ||
1609 | snd_usb_mixer_free(mixer); | ||
1610 | return err; | ||
1611 | } | ||
1612 | list_add(&mixer->list, &chip->mixer_list); | ||
1613 | return 0; | ||
1614 | } | ||
1615 | |||
1616 | void snd_usb_mixer_disconnect(struct list_head *p) | ||
1617 | { | ||
1618 | } | ||