diff options
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r-- | sound/usb/usbmixer.c | 588 |
1 files changed, 521 insertions, 67 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 5f1906915aa6..e73c1c9d3e73 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -35,10 +35,11 @@ | |||
35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
36 | #include <sound/core.h> | 36 | #include <sound/core.h> |
37 | #include <sound/control.h> | 37 | #include <sound/control.h> |
38 | #include <sound/hwdep.h> | ||
39 | #include <sound/info.h> | ||
38 | 40 | ||
39 | #include "usbaudio.h" | 41 | #include "usbaudio.h" |
40 | 42 | ||
41 | |||
42 | /* | 43 | /* |
43 | */ | 44 | */ |
44 | 45 | ||
@@ -50,6 +51,31 @@ typedef struct usb_audio_term usb_audio_term_t; | |||
50 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; | 51 | typedef struct usb_mixer_elem_info usb_mixer_elem_info_t; |
51 | 52 | ||
52 | 53 | ||
54 | struct usb_mixer_interface { | ||
55 | snd_usb_audio_t *chip; | ||
56 | unsigned int ctrlif; | ||
57 | struct list_head list; | ||
58 | unsigned int ignore_ctl_error; | ||
59 | struct urb *urb; | ||
60 | usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */ | ||
61 | |||
62 | /* Sound Blaster remote control stuff */ | ||
63 | enum { | ||
64 | RC_NONE, | ||
65 | RC_EXTIGY, | ||
66 | RC_AUDIGY2NX, | ||
67 | } rc_type; | ||
68 | unsigned long rc_hwdep_open; | ||
69 | u32 rc_code; | ||
70 | wait_queue_head_t rc_waitq; | ||
71 | struct urb *rc_urb; | ||
72 | struct usb_ctrlrequest *rc_setup_packet; | ||
73 | u8 rc_buffer[6]; | ||
74 | |||
75 | u8 audigy2nx_leds[3]; | ||
76 | }; | ||
77 | |||
78 | |||
53 | struct usb_audio_term { | 79 | struct usb_audio_term { |
54 | int id; | 80 | int id; |
55 | int type; | 81 | int type; |
@@ -62,26 +88,26 @@ struct usbmix_name_map; | |||
62 | 88 | ||
63 | struct usb_mixer_build { | 89 | struct usb_mixer_build { |
64 | snd_usb_audio_t *chip; | 90 | snd_usb_audio_t *chip; |
91 | struct usb_mixer_interface *mixer; | ||
65 | unsigned char *buffer; | 92 | unsigned char *buffer; |
66 | unsigned int buflen; | 93 | unsigned int buflen; |
67 | unsigned int ctrlif; | 94 | DECLARE_BITMAP(unitbitmap, 256); |
68 | unsigned short vendor; | ||
69 | unsigned short product; | ||
70 | DECLARE_BITMAP(unitbitmap, 32*32); | ||
71 | usb_audio_term_t oterm; | 95 | usb_audio_term_t oterm; |
72 | const struct usbmix_name_map *map; | 96 | const struct usbmix_name_map *map; |
97 | const struct usbmix_selector_map *selector_map; | ||
73 | }; | 98 | }; |
74 | 99 | ||
75 | struct usb_mixer_elem_info { | 100 | struct usb_mixer_elem_info { |
76 | snd_usb_audio_t *chip; | 101 | struct usb_mixer_interface *mixer; |
77 | unsigned int ctrlif; | 102 | usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */ |
103 | snd_ctl_elem_id_t *elem_id; | ||
78 | unsigned int id; | 104 | unsigned int id; |
79 | unsigned int control; /* CS or ICN (high byte) */ | 105 | unsigned int control; /* CS or ICN (high byte) */ |
80 | unsigned int cmask; /* channel mask bitmap: 0 = master */ | 106 | unsigned int cmask; /* channel mask bitmap: 0 = master */ |
81 | int channels; | 107 | int channels; |
82 | int val_type; | 108 | int val_type; |
83 | int min, max, res; | 109 | int min, max, res; |
84 | unsigned int initialized: 1; | 110 | u8 initialized; |
85 | }; | 111 | }; |
86 | 112 | ||
87 | 113 | ||
@@ -187,6 +213,21 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control) | |||
187 | return 0; | 213 | return 0; |
188 | } | 214 | } |
189 | 215 | ||
216 | /* get the mapped selector source name */ | ||
217 | static int check_mapped_selector_name(mixer_build_t *state, int unitid, | ||
218 | int index, char *buf, int buflen) | ||
219 | { | ||
220 | const struct usbmix_selector_map *p; | ||
221 | |||
222 | if (! state->selector_map) | ||
223 | return 0; | ||
224 | for (p = state->selector_map; p->id; p++) { | ||
225 | if (p->id == unitid && index < p->count) | ||
226 | return strlcpy(buf, p->names[index], buflen); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
190 | /* | 231 | /* |
191 | * find an audio control unit with the given unit id | 232 | * find an audio control unit with the given unit id |
192 | */ | 233 | */ |
@@ -301,16 +342,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
301 | int timeout = 10; | 342 | int timeout = 10; |
302 | 343 | ||
303 | while (timeout-- > 0) { | 344 | while (timeout-- > 0) { |
304 | if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0), | 345 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
346 | usb_rcvctrlpipe(cval->mixer->chip->dev, 0), | ||
305 | request, | 347 | request, |
306 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 348 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
307 | validx, cval->ctrlif | (cval->id << 8), | 349 | validx, cval->mixer->ctrlif | (cval->id << 8), |
308 | buf, val_len, 100) >= 0) { | 350 | buf, val_len, 100) >= 0) { |
309 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 351 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
310 | return 0; | 352 | return 0; |
311 | } | 353 | } |
312 | } | 354 | } |
313 | 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); | 355 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
356 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type); | ||
314 | return -EINVAL; | 357 | return -EINVAL; |
315 | } | 358 | } |
316 | 359 | ||
@@ -339,13 +382,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i | |||
339 | buf[0] = value_set & 0xff; | 382 | buf[0] = value_set & 0xff; |
340 | buf[1] = (value_set >> 8) & 0xff; | 383 | buf[1] = (value_set >> 8) & 0xff; |
341 | while (timeout -- > 0) | 384 | while (timeout -- > 0) |
342 | if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0), | 385 | if (snd_usb_ctl_msg(cval->mixer->chip->dev, |
386 | usb_sndctrlpipe(cval->mixer->chip->dev, 0), | ||
343 | request, | 387 | request, |
344 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 388 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
345 | validx, cval->ctrlif | (cval->id << 8), | 389 | validx, cval->mixer->ctrlif | (cval->id << 8), |
346 | buf, val_len, 100) >= 0) | 390 | buf, val_len, 100) >= 0) |
347 | return 0; | 391 | return 0; |
348 | 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]); | 392 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
393 | request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]); | ||
349 | return -EINVAL; | 394 | return -EINVAL; |
350 | } | 395 | } |
351 | 396 | ||
@@ -385,16 +430,22 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou | |||
385 | * if failed, give up and free the control instance. | 430 | * if failed, give up and free the control instance. |
386 | */ | 431 | */ |
387 | 432 | ||
388 | static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl) | 433 | static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl) |
389 | { | 434 | { |
435 | usb_mixer_elem_info_t *cval = kctl->private_data; | ||
390 | int err; | 436 | int err; |
391 | while (snd_ctl_find_id(card, &kctl->id)) | 437 | |
438 | while (snd_ctl_find_id(state->chip->card, &kctl->id)) | ||
392 | kctl->id.index++; | 439 | kctl->id.index++; |
393 | if ((err = snd_ctl_add(card, kctl)) < 0) { | 440 | if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { |
394 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); | 441 | snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); |
395 | snd_ctl_free_one(kctl); | 442 | snd_ctl_free_one(kctl); |
443 | return err; | ||
396 | } | 444 | } |
397 | return err; | 445 | cval->elem_id = &kctl->id; |
446 | cval->next_id_elem = state->mixer->id_elems[cval->id]; | ||
447 | state->mixer->id_elems[cval->id] = cval; | ||
448 | return 0; | ||
398 | } | 449 | } |
399 | 450 | ||
400 | 451 | ||
@@ -572,10 +623,8 @@ static struct usb_feature_control_info audio_feature_info[] = { | |||
572 | /* private_free callback */ | 623 | /* private_free callback */ |
573 | static void usb_mixer_elem_free(snd_kcontrol_t *kctl) | 624 | static void usb_mixer_elem_free(snd_kcontrol_t *kctl) |
574 | { | 625 | { |
575 | if (kctl->private_data) { | 626 | kfree(kctl->private_data); |
576 | kfree(kctl->private_data); | 627 | kctl->private_data = NULL; |
577 | kctl->private_data = NULL; | ||
578 | } | ||
579 | } | 628 | } |
580 | 629 | ||
581 | 630 | ||
@@ -608,7 +657,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min) | |||
608 | } | 657 | } |
609 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 658 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
610 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 659 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
611 | 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); | 660 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
661 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | ||
612 | return -EINVAL; | 662 | return -EINVAL; |
613 | } | 663 | } |
614 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 664 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
@@ -668,7 +718,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
668 | if (cval->cmask & (1 << c)) { | 718 | if (cval->cmask & (1 << c)) { |
669 | err = get_cur_mix_value(cval, c + 1, &val); | 719 | err = get_cur_mix_value(cval, c + 1, &val); |
670 | if (err < 0) { | 720 | if (err < 0) { |
671 | if (cval->chip->ignore_ctl_error) { | 721 | if (cval->mixer->ignore_ctl_error) { |
672 | ucontrol->value.integer.value[0] = cval->min; | 722 | ucontrol->value.integer.value[0] = cval->min; |
673 | return 0; | 723 | return 0; |
674 | } | 724 | } |
@@ -684,7 +734,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
684 | /* master channel */ | 734 | /* master channel */ |
685 | err = get_cur_mix_value(cval, 0, &val); | 735 | err = get_cur_mix_value(cval, 0, &val); |
686 | if (err < 0) { | 736 | if (err < 0) { |
687 | if (cval->chip->ignore_ctl_error) { | 737 | if (cval->mixer->ignore_ctl_error) { |
688 | ucontrol->value.integer.value[0] = cval->min; | 738 | ucontrol->value.integer.value[0] = cval->min; |
689 | return 0; | 739 | return 0; |
690 | } | 740 | } |
@@ -710,7 +760,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
710 | if (cval->cmask & (1 << c)) { | 760 | if (cval->cmask & (1 << c)) { |
711 | err = get_cur_mix_value(cval, c + 1, &oval); | 761 | err = get_cur_mix_value(cval, c + 1, &oval); |
712 | if (err < 0) { | 762 | if (err < 0) { |
713 | if (cval->chip->ignore_ctl_error) | 763 | if (cval->mixer->ignore_ctl_error) |
714 | return 0; | 764 | return 0; |
715 | return err; | 765 | return err; |
716 | } | 766 | } |
@@ -727,7 +777,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
727 | } else { | 777 | } else { |
728 | /* master channel */ | 778 | /* master channel */ |
729 | err = get_cur_mix_value(cval, 0, &oval); | 779 | err = get_cur_mix_value(cval, 0, &oval); |
730 | if (err < 0 && cval->chip->ignore_ctl_error) | 780 | if (err < 0 && cval->mixer->ignore_ctl_error) |
731 | return 0; | 781 | return 0; |
732 | if (err < 0) | 782 | if (err < 0) |
733 | return err; | 783 | return err; |
@@ -779,8 +829,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
779 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 829 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
780 | return; | 830 | return; |
781 | } | 831 | } |
782 | cval->chip = state->chip; | 832 | cval->mixer = state->mixer; |
783 | cval->ctrlif = state->ctrlif; | ||
784 | cval->id = unitid; | 833 | cval->id = unitid; |
785 | cval->control = control; | 834 | cval->control = control; |
786 | cval->cmask = ctl_mask; | 835 | cval->cmask = ctl_mask; |
@@ -855,16 +904,21 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, | |||
855 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ | 904 | /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ |
856 | /* is not very clear from datasheets */ | 905 | /* is not very clear from datasheets */ |
857 | /* I hope that the min value is -15360 for newer firmware --jk */ | 906 | /* I hope that the min value is -15360 for newer firmware --jk */ |
858 | if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) || | 907 | switch (state->chip->usb_id) { |
859 | (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") && | 908 | case USB_ID(0x0471, 0x0101): |
860 | cval->min == -15616) { | 909 | case USB_ID(0x0471, 0x0104): |
861 | snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n"); | 910 | case USB_ID(0x0471, 0x0105): |
862 | cval->max = -256; | 911 | case USB_ID(0x0672, 0x1041): |
912 | if (!strcmp(kctl->id.name, "PCM Playback Volume") && | ||
913 | cval->min == -15616) { | ||
914 | snd_printk("using volume control quirk for the UDA1321/N101 chip\n"); | ||
915 | cval->max = -256; | ||
916 | } | ||
863 | } | 917 | } |
864 | 918 | ||
865 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 919 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
866 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 920 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
867 | add_control_to_empty(state->chip->card, kctl); | 921 | add_control_to_empty(state, kctl); |
868 | } | 922 | } |
869 | 923 | ||
870 | 924 | ||
@@ -947,8 +1001,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
947 | if (! cval) | 1001 | if (! cval) |
948 | return; | 1002 | return; |
949 | 1003 | ||
950 | cval->chip = state->chip; | 1004 | cval->mixer = state->mixer; |
951 | cval->ctrlif = state->ctrlif; | ||
952 | cval->id = unitid; | 1005 | cval->id = unitid; |
953 | cval->control = in_ch + 1; /* based on 1 */ | 1006 | cval->control = in_ch + 1; /* based on 1 */ |
954 | cval->val_type = USB_MIXER_S16; | 1007 | cval->val_type = USB_MIXER_S16; |
@@ -979,7 +1032,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc, | |||
979 | 1032 | ||
980 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", | 1033 | snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", |
981 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1034 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
982 | add_control_to_empty(state->chip->card, kctl); | 1035 | add_control_to_empty(state, kctl); |
983 | } | 1036 | } |
984 | 1037 | ||
985 | 1038 | ||
@@ -1042,7 +1095,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1042 | int err, val; | 1095 | int err, val; |
1043 | 1096 | ||
1044 | err = get_cur_ctl_value(cval, cval->control << 8, &val); | 1097 | err = get_cur_ctl_value(cval, cval->control << 8, &val); |
1045 | if (err < 0 && cval->chip->ignore_ctl_error) { | 1098 | if (err < 0 && cval->mixer->ignore_ctl_error) { |
1046 | ucontrol->value.integer.value[0] = cval->min; | 1099 | ucontrol->value.integer.value[0] = cval->min; |
1047 | return 0; | 1100 | return 0; |
1048 | } | 1101 | } |
@@ -1061,7 +1114,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1061 | 1114 | ||
1062 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); | 1115 | err = get_cur_ctl_value(cval, cval->control << 8, &oval); |
1063 | if (err < 0) { | 1116 | if (err < 0) { |
1064 | if (cval->chip->ignore_ctl_error) | 1117 | if (cval->mixer->ignore_ctl_error) |
1065 | return 0; | 1118 | return 0; |
1066 | return err; | 1119 | return err; |
1067 | } | 1120 | } |
@@ -1179,9 +1232,6 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1179 | } | 1232 | } |
1180 | 1233 | ||
1181 | type = combine_word(&dsc[4]); | 1234 | type = combine_word(&dsc[4]); |
1182 | if (! type) | ||
1183 | return 0; /* undefined? */ | ||
1184 | |||
1185 | for (info = list; info && info->type; info++) | 1235 | for (info = list; info && info->type; info++) |
1186 | if (info->type == type) | 1236 | if (info->type == type) |
1187 | break; | 1237 | break; |
@@ -1199,8 +1249,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1199 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1249 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1200 | return -ENOMEM; | 1250 | return -ENOMEM; |
1201 | } | 1251 | } |
1202 | cval->chip = state->chip; | 1252 | cval->mixer = state->mixer; |
1203 | cval->ctrlif = state->ctrlif; | ||
1204 | cval->id = unitid; | 1253 | cval->id = unitid; |
1205 | cval->control = valinfo->control; | 1254 | cval->control = valinfo->control; |
1206 | cval->val_type = valinfo->val_type; | 1255 | cval->val_type = valinfo->val_type; |
@@ -1241,7 +1290,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char | |||
1241 | 1290 | ||
1242 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", | 1291 | snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", |
1243 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); | 1292 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max); |
1244 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1293 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1245 | return err; | 1294 | return err; |
1246 | } | 1295 | } |
1247 | return 0; | 1296 | return 0; |
@@ -1289,7 +1338,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1289 | 1338 | ||
1290 | err = get_cur_ctl_value(cval, 0, &val); | 1339 | err = get_cur_ctl_value(cval, 0, &val); |
1291 | if (err < 0) { | 1340 | if (err < 0) { |
1292 | if (cval->chip->ignore_ctl_error) { | 1341 | if (cval->mixer->ignore_ctl_error) { |
1293 | ucontrol->value.enumerated.item[0] = 0; | 1342 | ucontrol->value.enumerated.item[0] = 0; |
1294 | return 0; | 1343 | return 0; |
1295 | } | 1344 | } |
@@ -1308,7 +1357,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t | |||
1308 | 1357 | ||
1309 | err = get_cur_ctl_value(cval, 0, &oval); | 1358 | err = get_cur_ctl_value(cval, 0, &oval); |
1310 | if (err < 0) { | 1359 | if (err < 0) { |
1311 | if (cval->chip->ignore_ctl_error) | 1360 | if (cval->mixer->ignore_ctl_error) |
1312 | return 0; | 1361 | return 0; |
1313 | return err; | 1362 | return err; |
1314 | } | 1363 | } |
@@ -1386,8 +1435,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1386 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); | 1435 | snd_printk(KERN_ERR "cannot malloc kcontrol\n"); |
1387 | return -ENOMEM; | 1436 | return -ENOMEM; |
1388 | } | 1437 | } |
1389 | cval->chip = state->chip; | 1438 | cval->mixer = state->mixer; |
1390 | cval->ctrlif = state->ctrlif; | ||
1391 | cval->id = unitid; | 1439 | cval->id = unitid; |
1392 | cval->val_type = USB_MIXER_U8; | 1440 | cval->val_type = USB_MIXER_U8; |
1393 | cval->channels = 1; | 1441 | cval->channels = 1; |
@@ -1415,7 +1463,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1415 | kfree(cval); | 1463 | kfree(cval); |
1416 | return -ENOMEM; | 1464 | return -ENOMEM; |
1417 | } | 1465 | } |
1418 | if (check_input_term(state, desc[5 + i], &iterm) >= 0) | 1466 | len = check_mapped_selector_name(state, unitid, i, namelist[i], |
1467 | MAX_ITEM_NAME_LEN); | ||
1468 | if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0) | ||
1419 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); | 1469 | len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); |
1420 | if (! len) | 1470 | if (! len) |
1421 | sprintf(namelist[i], "Input %d", i); | 1471 | sprintf(namelist[i], "Input %d", i); |
@@ -1450,7 +1500,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned | |||
1450 | 1500 | ||
1451 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", | 1501 | snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", |
1452 | cval->id, kctl->id.name, num_ins); | 1502 | cval->id, kctl->id.name, num_ins); |
1453 | if ((err = add_control_to_empty(state->chip->card, kctl)) < 0) | 1503 | if ((err = add_control_to_empty(state, kctl)) < 0) |
1454 | return err; | 1504 | return err; |
1455 | 1505 | ||
1456 | return 0; | 1506 | return 0; |
@@ -1493,41 +1543,55 @@ static int parse_audio_unit(mixer_build_t *state, int unitid) | |||
1493 | } | 1543 | } |
1494 | } | 1544 | } |
1495 | 1545 | ||
1546 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | ||
1547 | { | ||
1548 | kfree(mixer->id_elems); | ||
1549 | if (mixer->urb) { | ||
1550 | kfree(mixer->urb->transfer_buffer); | ||
1551 | usb_free_urb(mixer->urb); | ||
1552 | } | ||
1553 | if (mixer->rc_urb) | ||
1554 | usb_free_urb(mixer->rc_urb); | ||
1555 | kfree(mixer->rc_setup_packet); | ||
1556 | kfree(mixer); | ||
1557 | } | ||
1558 | |||
1559 | static int snd_usb_mixer_dev_free(snd_device_t *device) | ||
1560 | { | ||
1561 | struct usb_mixer_interface *mixer = device->device_data; | ||
1562 | snd_usb_mixer_free(mixer); | ||
1563 | return 0; | ||
1564 | } | ||
1565 | |||
1496 | /* | 1566 | /* |
1497 | * create mixer controls | 1567 | * create mixer controls |
1498 | * | 1568 | * |
1499 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers | 1569 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers |
1500 | */ | 1570 | */ |
1501 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | 1571 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1502 | { | 1572 | { |
1503 | unsigned char *desc; | 1573 | unsigned char *desc; |
1504 | mixer_build_t state; | 1574 | mixer_build_t state; |
1505 | int err; | 1575 | int err; |
1506 | const struct usbmix_ctl_map *map; | 1576 | const struct usbmix_ctl_map *map; |
1507 | struct usb_device_descriptor *dev = &chip->dev->descriptor; | 1577 | struct usb_host_interface *hostif; |
1508 | struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | ||
1509 | |||
1510 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1511 | 1578 | ||
1579 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1512 | memset(&state, 0, sizeof(state)); | 1580 | memset(&state, 0, sizeof(state)); |
1513 | state.chip = chip; | 1581 | state.chip = mixer->chip; |
1582 | state.mixer = mixer; | ||
1514 | state.buffer = hostif->extra; | 1583 | state.buffer = hostif->extra; |
1515 | state.buflen = hostif->extralen; | 1584 | state.buflen = hostif->extralen; |
1516 | state.ctrlif = ctrlif; | ||
1517 | state.vendor = le16_to_cpu(dev->idVendor); | ||
1518 | state.product = le16_to_cpu(dev->idProduct); | ||
1519 | 1585 | ||
1520 | /* check the mapping table */ | 1586 | /* check the mapping table */ |
1521 | for (map = usbmix_ctl_maps; map->vendor; map++) { | 1587 | for (map = usbmix_ctl_maps; map->id; map++) { |
1522 | if (map->vendor == state.vendor && map->product == state.product) { | 1588 | if (map->id == state.chip->usb_id) { |
1523 | state.map = map->map; | 1589 | state.map = map->map; |
1524 | chip->ignore_ctl_error = map->ignore_ctl_error; | 1590 | state.selector_map = map->selector_map; |
1591 | mixer->ignore_ctl_error = map->ignore_ctl_error; | ||
1525 | break; | 1592 | break; |
1526 | } | 1593 | } |
1527 | } | 1594 | } |
1528 | #ifdef IGNORE_CTL_ERROR | ||
1529 | chip->ignore_ctl_error = 1; | ||
1530 | #endif | ||
1531 | 1595 | ||
1532 | desc = NULL; | 1596 | desc = NULL; |
1533 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { | 1597 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { |
@@ -1543,3 +1607,393 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | |||
1543 | } | 1607 | } |
1544 | return 0; | 1608 | return 0; |
1545 | } | 1609 | } |
1610 | |||
1611 | static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | ||
1612 | int unitid) | ||
1613 | { | ||
1614 | usb_mixer_elem_info_t *info; | ||
1615 | |||
1616 | for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) | ||
1617 | snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
1618 | info->elem_id); | ||
1619 | } | ||
1620 | |||
1621 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | ||
1622 | int unitid) | ||
1623 | { | ||
1624 | if (mixer->rc_type == RC_NONE) | ||
1625 | return; | ||
1626 | /* unit ids specific to Extigy/Audigy 2 NX: */ | ||
1627 | switch (unitid) { | ||
1628 | case 0: /* remote control */ | ||
1629 | mixer->rc_urb->dev = mixer->chip->dev; | ||
1630 | usb_submit_urb(mixer->rc_urb, GFP_ATOMIC); | ||
1631 | break; | ||
1632 | case 4: /* digital in jack */ | ||
1633 | case 7: /* line in jacks */ | ||
1634 | case 19: /* speaker out jacks */ | ||
1635 | case 20: /* headphones out jack */ | ||
1636 | break; | ||
1637 | default: | ||
1638 | snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid); | ||
1639 | break; | ||
1640 | } | ||
1641 | } | ||
1642 | |||
1643 | static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs) | ||
1644 | { | ||
1645 | struct usb_mixer_interface *mixer = urb->context; | ||
1646 | |||
1647 | if (urb->status == 0) { | ||
1648 | u8 *buf = urb->transfer_buffer; | ||
1649 | int i; | ||
1650 | |||
1651 | for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) { | ||
1652 | snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n", | ||
1653 | buf[0], buf[1]); | ||
1654 | /* ignore any notifications not from the control interface */ | ||
1655 | if ((buf[0] & 0x0f) != 0) | ||
1656 | continue; | ||
1657 | if (!(buf[0] & 0x40)) | ||
1658 | snd_usb_mixer_notify_id(mixer, buf[1]); | ||
1659 | else | ||
1660 | snd_usb_mixer_memory_change(mixer, buf[1]); | ||
1661 | } | ||
1662 | } | ||
1663 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | ||
1664 | urb->dev = mixer->chip->dev; | ||
1665 | usb_submit_urb(urb, GFP_ATOMIC); | ||
1666 | } | ||
1667 | } | ||
1668 | |||
1669 | /* create the handler for the optional status interrupt endpoint */ | ||
1670 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | ||
1671 | { | ||
1672 | struct usb_host_interface *hostif; | ||
1673 | struct usb_endpoint_descriptor *ep; | ||
1674 | void *transfer_buffer; | ||
1675 | int buffer_length; | ||
1676 | unsigned int epnum; | ||
1677 | |||
1678 | hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; | ||
1679 | /* we need one interrupt input endpoint */ | ||
1680 | if (get_iface_desc(hostif)->bNumEndpoints < 1) | ||
1681 | return 0; | ||
1682 | ep = get_endpoint(hostif, 0); | ||
1683 | if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN || | ||
1684 | (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) | ||
1685 | return 0; | ||
1686 | |||
1687 | epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
1688 | buffer_length = le16_to_cpu(ep->wMaxPacketSize); | ||
1689 | transfer_buffer = kmalloc(buffer_length, GFP_KERNEL); | ||
1690 | if (!transfer_buffer) | ||
1691 | return -ENOMEM; | ||
1692 | mixer->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1693 | if (!mixer->urb) { | ||
1694 | kfree(transfer_buffer); | ||
1695 | return -ENOMEM; | ||
1696 | } | ||
1697 | usb_fill_int_urb(mixer->urb, mixer->chip->dev, | ||
1698 | usb_rcvintpipe(mixer->chip->dev, epnum), | ||
1699 | transfer_buffer, buffer_length, | ||
1700 | snd_usb_mixer_status_complete, mixer, ep->bInterval); | ||
1701 | usb_submit_urb(mixer->urb, GFP_KERNEL); | ||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1705 | static void snd_usb_soundblaster_remote_complete(struct urb *urb, | ||
1706 | struct pt_regs *regs) | ||
1707 | { | ||
1708 | struct usb_mixer_interface *mixer = urb->context; | ||
1709 | /* | ||
1710 | * format of remote control data: | ||
1711 | * Extigy: xx 00 | ||
1712 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
1713 | */ | ||
1714 | int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; | ||
1715 | u32 code; | ||
1716 | |||
1717 | if (urb->status < 0 || urb->actual_length <= offset) | ||
1718 | return; | ||
1719 | code = mixer->rc_buffer[offset]; | ||
1720 | /* the Mute button actually changes the mixer control */ | ||
1721 | if (code == 13) | ||
1722 | snd_usb_mixer_notify_id(mixer, 18); | ||
1723 | mixer->rc_code = code; | ||
1724 | wmb(); | ||
1725 | wake_up(&mixer->rc_waitq); | ||
1726 | } | ||
1727 | |||
1728 | static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file) | ||
1729 | { | ||
1730 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1731 | |||
1732 | if (test_and_set_bit(0, &mixer->rc_hwdep_open)) | ||
1733 | return -EBUSY; | ||
1734 | return 0; | ||
1735 | } | ||
1736 | |||
1737 | static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file) | ||
1738 | { | ||
1739 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1740 | |||
1741 | clear_bit(0, &mixer->rc_hwdep_open); | ||
1742 | smp_mb__after_clear_bit(); | ||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1746 | static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf, | ||
1747 | long count, loff_t *offset) | ||
1748 | { | ||
1749 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1750 | int err; | ||
1751 | u32 rc_code; | ||
1752 | |||
1753 | if (count != 1 && count != 4) | ||
1754 | return -EINVAL; | ||
1755 | err = wait_event_interruptible(mixer->rc_waitq, | ||
1756 | (rc_code = xchg(&mixer->rc_code, 0)) != 0); | ||
1757 | if (err == 0) { | ||
1758 | if (count == 1) | ||
1759 | err = put_user(rc_code, buf); | ||
1760 | else | ||
1761 | err = put_user(rc_code, (u32 __user *)buf); | ||
1762 | } | ||
1763 | return err < 0 ? err : count; | ||
1764 | } | ||
1765 | |||
1766 | static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file, | ||
1767 | poll_table *wait) | ||
1768 | { | ||
1769 | struct usb_mixer_interface *mixer = hw->private_data; | ||
1770 | |||
1771 | poll_wait(file, &mixer->rc_waitq, wait); | ||
1772 | return mixer->rc_code ? POLLIN | POLLRDNORM : 0; | ||
1773 | } | ||
1774 | |||
1775 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | ||
1776 | { | ||
1777 | snd_hwdep_t *hwdep; | ||
1778 | int err, len; | ||
1779 | |||
1780 | switch (mixer->chip->usb_id) { | ||
1781 | case USB_ID(0x041e, 0x3000): | ||
1782 | mixer->rc_type = RC_EXTIGY; | ||
1783 | len = 2; | ||
1784 | break; | ||
1785 | case USB_ID(0x041e, 0x3020): | ||
1786 | mixer->rc_type = RC_AUDIGY2NX; | ||
1787 | len = 6; | ||
1788 | break; | ||
1789 | default: | ||
1790 | return 0; | ||
1791 | } | ||
1792 | |||
1793 | init_waitqueue_head(&mixer->rc_waitq); | ||
1794 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); | ||
1795 | if (err < 0) | ||
1796 | return err; | ||
1797 | snprintf(hwdep->name, sizeof(hwdep->name), | ||
1798 | "%s remote control", mixer->chip->card->shortname); | ||
1799 | hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC; | ||
1800 | hwdep->private_data = mixer; | ||
1801 | hwdep->ops.read = snd_usb_sbrc_hwdep_read; | ||
1802 | hwdep->ops.open = snd_usb_sbrc_hwdep_open; | ||
1803 | hwdep->ops.release = snd_usb_sbrc_hwdep_release; | ||
1804 | hwdep->ops.poll = snd_usb_sbrc_hwdep_poll; | ||
1805 | |||
1806 | mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
1807 | if (!mixer->rc_urb) | ||
1808 | return -ENOMEM; | ||
1809 | mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL); | ||
1810 | if (!mixer->rc_setup_packet) { | ||
1811 | usb_free_urb(mixer->rc_urb); | ||
1812 | mixer->rc_urb = NULL; | ||
1813 | return -ENOMEM; | ||
1814 | } | ||
1815 | mixer->rc_setup_packet->bRequestType = | ||
1816 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
1817 | mixer->rc_setup_packet->bRequest = GET_MEM; | ||
1818 | mixer->rc_setup_packet->wValue = cpu_to_le16(0); | ||
1819 | mixer->rc_setup_packet->wIndex = cpu_to_le16(0); | ||
1820 | mixer->rc_setup_packet->wLength = cpu_to_le16(len); | ||
1821 | usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, | ||
1822 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1823 | (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, | ||
1824 | snd_usb_soundblaster_remote_complete, mixer); | ||
1825 | return 0; | ||
1826 | } | ||
1827 | |||
1828 | static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) | ||
1829 | { | ||
1830 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1831 | uinfo->count = 1; | ||
1832 | uinfo->value.integer.min = 0; | ||
1833 | uinfo->value.integer.max = 1; | ||
1834 | return 0; | ||
1835 | } | ||
1836 | |||
1837 | static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1838 | { | ||
1839 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1840 | int index = kcontrol->private_value; | ||
1841 | |||
1842 | ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index]; | ||
1843 | return 0; | ||
1844 | } | ||
1845 | |||
1846 | static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | ||
1847 | { | ||
1848 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
1849 | int index = kcontrol->private_value; | ||
1850 | int value = ucontrol->value.integer.value[0]; | ||
1851 | int err, changed; | ||
1852 | |||
1853 | if (value > 1) | ||
1854 | return -EINVAL; | ||
1855 | changed = value != mixer->audigy2nx_leds[index]; | ||
1856 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1857 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
1858 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
1859 | value, index + 2, NULL, 0, 100); | ||
1860 | if (err < 0) | ||
1861 | return err; | ||
1862 | mixer->audigy2nx_leds[index] = value; | ||
1863 | return changed; | ||
1864 | } | ||
1865 | |||
1866 | static snd_kcontrol_new_t snd_audigy2nx_controls[] = { | ||
1867 | { | ||
1868 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1869 | .name = "CMSS LED Switch", | ||
1870 | .info = snd_audigy2nx_led_info, | ||
1871 | .get = snd_audigy2nx_led_get, | ||
1872 | .put = snd_audigy2nx_led_put, | ||
1873 | .private_value = 0, | ||
1874 | }, | ||
1875 | { | ||
1876 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1877 | .name = "Power LED Switch", | ||
1878 | .info = snd_audigy2nx_led_info, | ||
1879 | .get = snd_audigy2nx_led_get, | ||
1880 | .put = snd_audigy2nx_led_put, | ||
1881 | .private_value = 1, | ||
1882 | }, | ||
1883 | { | ||
1884 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1885 | .name = "Dolby Digital LED Switch", | ||
1886 | .info = snd_audigy2nx_led_info, | ||
1887 | .get = snd_audigy2nx_led_get, | ||
1888 | .put = snd_audigy2nx_led_put, | ||
1889 | .private_value = 2, | ||
1890 | }, | ||
1891 | }; | ||
1892 | |||
1893 | static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | ||
1894 | { | ||
1895 | int i, err; | ||
1896 | |||
1897 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | ||
1898 | err = snd_ctl_add(mixer->chip->card, | ||
1899 | snd_ctl_new1(&snd_audigy2nx_controls[i], mixer)); | ||
1900 | if (err < 0) | ||
1901 | return err; | ||
1902 | } | ||
1903 | mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */ | ||
1904 | return 0; | ||
1905 | } | ||
1906 | |||
1907 | static void snd_audigy2nx_proc_read(snd_info_entry_t *entry, | ||
1908 | snd_info_buffer_t *buffer) | ||
1909 | { | ||
1910 | static const struct { | ||
1911 | int unitid; | ||
1912 | const char *name; | ||
1913 | } jacks[] = { | ||
1914 | {4, "dig in "}, | ||
1915 | {7, "line in"}, | ||
1916 | {19, "spk out"}, | ||
1917 | {20, "hph out"}, | ||
1918 | }; | ||
1919 | struct usb_mixer_interface *mixer = entry->private_data; | ||
1920 | int i, err; | ||
1921 | u8 buf[3]; | ||
1922 | |||
1923 | snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname); | ||
1924 | for (i = 0; i < ARRAY_SIZE(jacks); ++i) { | ||
1925 | snd_iprintf(buffer, "%s: ", jacks[i].name); | ||
1926 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
1927 | usb_rcvctrlpipe(mixer->chip->dev, 0), | ||
1928 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | ||
1929 | USB_RECIP_INTERFACE, 0, | ||
1930 | jacks[i].unitid << 8, buf, 3, 100); | ||
1931 | if (err == 3 && buf[0] == 3) | ||
1932 | snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); | ||
1933 | else | ||
1934 | snd_iprintf(buffer, "?\n"); | ||
1935 | } | ||
1936 | } | ||
1937 | |||
1938 | int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) | ||
1939 | { | ||
1940 | static snd_device_ops_t dev_ops = { | ||
1941 | .dev_free = snd_usb_mixer_dev_free | ||
1942 | }; | ||
1943 | struct usb_mixer_interface *mixer; | ||
1944 | int err; | ||
1945 | |||
1946 | strcpy(chip->card->mixername, "USB Mixer"); | ||
1947 | |||
1948 | mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL); | ||
1949 | if (!mixer) | ||
1950 | return -ENOMEM; | ||
1951 | mixer->chip = chip; | ||
1952 | mixer->ctrlif = ctrlif; | ||
1953 | #ifdef IGNORE_CTL_ERROR | ||
1954 | mixer->ignore_ctl_error = 1; | ||
1955 | #endif | ||
1956 | mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); | ||
1957 | if (!mixer->id_elems) { | ||
1958 | kfree(mixer); | ||
1959 | return -ENOMEM; | ||
1960 | } | ||
1961 | |||
1962 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | ||
1963 | (err = snd_usb_mixer_status_create(mixer)) < 0) | ||
1964 | goto _error; | ||
1965 | |||
1966 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | ||
1967 | goto _error; | ||
1968 | |||
1969 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) { | ||
1970 | snd_info_entry_t *entry; | ||
1971 | |||
1972 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | ||
1973 | goto _error; | ||
1974 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | ||
1975 | snd_info_set_text_ops(entry, mixer, 1024, | ||
1976 | snd_audigy2nx_proc_read); | ||
1977 | } | ||
1978 | |||
1979 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | ||
1980 | if (err < 0) | ||
1981 | goto _error; | ||
1982 | list_add(&mixer->list, &chip->mixer_list); | ||
1983 | return 0; | ||
1984 | |||
1985 | _error: | ||
1986 | snd_usb_mixer_free(mixer); | ||
1987 | return err; | ||
1988 | } | ||
1989 | |||
1990 | void snd_usb_mixer_disconnect(struct list_head *p) | ||
1991 | { | ||
1992 | struct usb_mixer_interface *mixer; | ||
1993 | |||
1994 | mixer = list_entry(p, struct usb_mixer_interface, list); | ||
1995 | if (mixer->urb) | ||
1996 | usb_kill_urb(mixer->urb); | ||
1997 | if (mixer->rc_urb) | ||
1998 | usb_kill_urb(mixer->rc_urb); | ||
1999 | } | ||