diff options
Diffstat (limited to 'sound/usb/usbmixer.c')
-rw-r--r-- | sound/usb/usbmixer.c | 371 |
1 files changed, 264 insertions, 107 deletions
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index c998220b99c6..8e8f871b74ca 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/usb/audio.h> | ||
36 | |||
35 | #include <sound/core.h> | 37 | #include <sound/core.h> |
36 | #include <sound/control.h> | 38 | #include <sound/control.h> |
37 | #include <sound/hwdep.h> | 39 | #include <sound/hwdep.h> |
@@ -69,13 +71,16 @@ static const struct rc_config { | |||
69 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ | 71 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ |
70 | }; | 72 | }; |
71 | 73 | ||
74 | #define MAX_ID_ELEMS 256 | ||
75 | |||
72 | struct usb_mixer_interface { | 76 | struct usb_mixer_interface { |
73 | struct snd_usb_audio *chip; | 77 | struct snd_usb_audio *chip; |
74 | unsigned int ctrlif; | 78 | unsigned int ctrlif; |
75 | struct list_head list; | 79 | struct list_head list; |
76 | unsigned int ignore_ctl_error; | 80 | unsigned int ignore_ctl_error; |
77 | struct urb *urb; | 81 | struct urb *urb; |
78 | struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ | 82 | /* array[MAX_ID_ELEMS], indexed by unit id */ |
83 | struct usb_mixer_elem_info **id_elems; | ||
79 | 84 | ||
80 | /* Sound Blaster remote control stuff */ | 85 | /* Sound Blaster remote control stuff */ |
81 | const struct rc_config *rc_cfg; | 86 | const struct rc_config *rc_cfg; |
@@ -105,7 +110,7 @@ struct mixer_build { | |||
105 | struct usb_mixer_interface *mixer; | 110 | struct usb_mixer_interface *mixer; |
106 | unsigned char *buffer; | 111 | unsigned char *buffer; |
107 | unsigned int buflen; | 112 | unsigned int buflen; |
108 | DECLARE_BITMAP(unitbitmap, 256); | 113 | DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS); |
109 | struct usb_audio_term oterm; | 114 | struct usb_audio_term oterm; |
110 | const struct usbmix_name_map *map; | 115 | const struct usbmix_name_map *map; |
111 | const struct usbmix_selector_map *selector_map; | 116 | const struct usbmix_selector_map *selector_map; |
@@ -123,6 +128,7 @@ struct usb_mixer_elem_info { | |||
123 | int channels; | 128 | int channels; |
124 | int val_type; | 129 | int val_type; |
125 | int min, max, res; | 130 | int min, max, res; |
131 | int dBmin, dBmax; | ||
126 | int cached; | 132 | int cached; |
127 | int cache_val[MAX_CHANNELS]; | 133 | int cache_val[MAX_CHANNELS]; |
128 | u8 initialized; | 134 | u8 initialized; |
@@ -186,6 +192,21 @@ enum { | |||
186 | USB_PROC_DCR_RELEASE = 6, | 192 | USB_PROC_DCR_RELEASE = 6, |
187 | }; | 193 | }; |
188 | 194 | ||
195 | /*E-mu 0202(0404) eXtension Unit(XU) control*/ | ||
196 | enum { | ||
197 | USB_XU_CLOCK_RATE = 0xe301, | ||
198 | USB_XU_CLOCK_SOURCE = 0xe302, | ||
199 | USB_XU_DIGITAL_IO_STATUS = 0xe303, | ||
200 | USB_XU_DEVICE_OPTIONS = 0xe304, | ||
201 | USB_XU_DIRECT_MONITORING = 0xe305, | ||
202 | USB_XU_METERING = 0xe306 | ||
203 | }; | ||
204 | enum { | ||
205 | USB_XU_CLOCK_SOURCE_SELECTOR = 0x02, /* clock source*/ | ||
206 | USB_XU_CLOCK_RATE_SELECTOR = 0x03, /* clock rate */ | ||
207 | USB_XU_DIGITAL_FORMAT_SELECTOR = 0x01, /* the spdif format */ | ||
208 | USB_XU_SOFT_LIMIT_SELECTOR = 0x03 /* soft limiter */ | ||
209 | }; | ||
189 | 210 | ||
190 | /* | 211 | /* |
191 | * manual mapping of mixer names | 212 | * manual mapping of mixer names |
@@ -194,42 +215,50 @@ enum { | |||
194 | */ | 215 | */ |
195 | #include "usbmixer_maps.c" | 216 | #include "usbmixer_maps.c" |
196 | 217 | ||
197 | /* get the mapped name if the unit matches */ | 218 | static const struct usbmix_name_map * |
198 | static int check_mapped_name(struct mixer_build *state, int unitid, int control, char *buf, int buflen) | 219 | find_map(struct mixer_build *state, int unitid, int control) |
199 | { | 220 | { |
200 | const struct usbmix_name_map *p; | 221 | const struct usbmix_name_map *p = state->map; |
201 | 222 | ||
202 | if (! state->map) | 223 | if (!p) |
203 | return 0; | 224 | return NULL; |
204 | 225 | ||
205 | for (p = state->map; p->id; p++) { | 226 | for (p = state->map; p->id; p++) { |
206 | if (p->id == unitid && p->name && | 227 | if (p->id == unitid && |
207 | (! control || ! p->control || control == p->control)) { | 228 | (!control || !p->control || control == p->control)) |
208 | buflen--; | 229 | return p; |
209 | return strlcpy(buf, p->name, buflen); | ||
210 | } | ||
211 | } | 230 | } |
212 | return 0; | 231 | return NULL; |
213 | } | 232 | } |
214 | 233 | ||
215 | /* check whether the control should be ignored */ | 234 | /* get the mapped name if the unit matches */ |
216 | static int check_ignored_ctl(struct mixer_build *state, int unitid, int control) | 235 | static int |
236 | check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen) | ||
217 | { | 237 | { |
218 | const struct usbmix_name_map *p; | 238 | if (!p || !p->name) |
239 | return 0; | ||
240 | |||
241 | buflen--; | ||
242 | return strlcpy(buf, p->name, buflen); | ||
243 | } | ||
219 | 244 | ||
220 | if (! state->map) | 245 | /* check whether the control should be ignored */ |
246 | static inline int | ||
247 | check_ignored_ctl(const struct usbmix_name_map *p) | ||
248 | { | ||
249 | if (!p || p->name || p->dB) | ||
221 | return 0; | 250 | return 0; |
222 | for (p = state->map; p->id; p++) { | 251 | return 1; |
223 | if (p->id == unitid && ! p->name && | 252 | } |
224 | (! control || ! p->control || control == p->control)) { | 253 | |
225 | /* | 254 | /* dB mapping */ |
226 | printk(KERN_DEBUG "ignored control %d:%d\n", | 255 | static inline void check_mapped_dB(const struct usbmix_name_map *p, |
227 | unitid, control); | 256 | struct usb_mixer_elem_info *cval) |
228 | */ | 257 | { |
229 | return 1; | 258 | if (p && p->dB) { |
230 | } | 259 | cval->dBmin = p->dB->min; |
260 | cval->dBmax = p->dB->max; | ||
231 | } | 261 | } |
232 | return 0; | ||
233 | } | 262 | } |
234 | 263 | ||
235 | /* get the mapped selector source name */ | 264 | /* get the mapped selector source name */ |
@@ -257,7 +286,7 @@ static void *find_audio_control_unit(struct mixer_build *state, unsigned char un | |||
257 | p = NULL; | 286 | p = NULL; |
258 | while ((p = snd_usb_find_desc(state->buffer, state->buflen, p, | 287 | while ((p = snd_usb_find_desc(state->buffer, state->buflen, p, |
259 | USB_DT_CS_INTERFACE)) != NULL) { | 288 | USB_DT_CS_INTERFACE)) != NULL) { |
260 | if (p[0] >= 4 && p[2] >= INPUT_TERMINAL && p[2] <= EXTENSION_UNIT && p[3] == unit) | 289 | if (p[0] >= 4 && p[2] >= UAC_INPUT_TERMINAL && p[2] <= UAC_EXTENSION_UNIT_V1 && p[3] == unit) |
261 | return p; | 290 | return p; |
262 | } | 291 | } |
263 | return NULL; | 292 | return NULL; |
@@ -378,14 +407,14 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali | |||
378 | 407 | ||
379 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) | 408 | static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value) |
380 | { | 409 | { |
381 | return get_ctl_value(cval, GET_CUR, validx, value); | 410 | return get_ctl_value(cval, UAC_GET_CUR, validx, value); |
382 | } | 411 | } |
383 | 412 | ||
384 | /* channel = 0: master, 1 = first channel */ | 413 | /* channel = 0: master, 1 = first channel */ |
385 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, | 414 | static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, |
386 | int channel, int *value) | 415 | int channel, int *value) |
387 | { | 416 | { |
388 | return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); | 417 | return get_ctl_value(cval, UAC_GET_CUR, (cval->control << 8) | channel, value); |
389 | } | 418 | } |
390 | 419 | ||
391 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, | 420 | static int get_cur_mix_value(struct usb_mixer_elem_info *cval, |
@@ -439,14 +468,14 @@ static int set_ctl_value(struct usb_mixer_elem_info *cval, int request, int vali | |||
439 | 468 | ||
440 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) | 469 | static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) |
441 | { | 470 | { |
442 | return set_ctl_value(cval, SET_CUR, validx, value); | 471 | return set_ctl_value(cval, UAC_SET_CUR, validx, value); |
443 | } | 472 | } |
444 | 473 | ||
445 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | 474 | static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, |
446 | int index, int value) | 475 | int index, int value) |
447 | { | 476 | { |
448 | int err; | 477 | int err; |
449 | err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, | 478 | err = set_ctl_value(cval, UAC_SET_CUR, (cval->control << 8) | channel, |
450 | value); | 479 | value); |
451 | if (err < 0) | 480 | if (err < 0) |
452 | return err; | 481 | return err; |
@@ -466,20 +495,8 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
466 | 495 | ||
467 | if (size < sizeof(scale)) | 496 | if (size < sizeof(scale)) |
468 | return -ENOMEM; | 497 | return -ENOMEM; |
469 | /* USB descriptions contain the dB scale in 1/256 dB unit | 498 | scale[2] = cval->dBmin; |
470 | * while ALSA TLV contains in 1/100 dB unit | 499 | scale[3] = cval->dBmax; |
471 | */ | ||
472 | scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; | ||
473 | scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256; | ||
474 | if (scale[3] <= scale[2]) { | ||
475 | /* something is wrong; assume it's either from/to 0dB */ | ||
476 | if (scale[2] < 0) | ||
477 | scale[3] = 0; | ||
478 | else if (scale[2] > 0) | ||
479 | scale[2] = 0; | ||
480 | else /* totally crap, return an error */ | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | if (copy_to_user(_tlv, scale, sizeof(scale))) | 500 | if (copy_to_user(_tlv, scale, sizeof(scale))) |
484 | return -EFAULT; | 501 | return -EFAULT; |
485 | return 0; | 502 | return 0; |
@@ -588,13 +605,13 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm | |||
588 | if (term_only) | 605 | if (term_only) |
589 | return 0; | 606 | return 0; |
590 | switch (iterm->type >> 16) { | 607 | switch (iterm->type >> 16) { |
591 | case SELECTOR_UNIT: | 608 | case UAC_SELECTOR_UNIT: |
592 | strcpy(name, "Selector"); return 8; | 609 | strcpy(name, "Selector"); return 8; |
593 | case PROCESSING_UNIT: | 610 | case UAC_PROCESSING_UNIT_V1: |
594 | strcpy(name, "Process Unit"); return 12; | 611 | strcpy(name, "Process Unit"); return 12; |
595 | case EXTENSION_UNIT: | 612 | case UAC_EXTENSION_UNIT_V1: |
596 | strcpy(name, "Ext Unit"); return 8; | 613 | strcpy(name, "Ext Unit"); return 8; |
597 | case MIXER_UNIT: | 614 | case UAC_MIXER_UNIT: |
598 | strcpy(name, "Mixer"); return 5; | 615 | strcpy(name, "Mixer"); return 5; |
599 | default: | 616 | default: |
600 | return sprintf(name, "Unit %d", iterm->id); | 617 | return sprintf(name, "Unit %d", iterm->id); |
@@ -633,22 +650,22 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
633 | while ((p1 = find_audio_control_unit(state, id)) != NULL) { | 650 | while ((p1 = find_audio_control_unit(state, id)) != NULL) { |
634 | term->id = id; | 651 | term->id = id; |
635 | switch (p1[2]) { | 652 | switch (p1[2]) { |
636 | case INPUT_TERMINAL: | 653 | case UAC_INPUT_TERMINAL: |
637 | term->type = combine_word(p1 + 4); | 654 | term->type = combine_word(p1 + 4); |
638 | term->channels = p1[7]; | 655 | term->channels = p1[7]; |
639 | term->chconfig = combine_word(p1 + 8); | 656 | term->chconfig = combine_word(p1 + 8); |
640 | term->name = p1[11]; | 657 | term->name = p1[11]; |
641 | return 0; | 658 | return 0; |
642 | case FEATURE_UNIT: | 659 | case UAC_FEATURE_UNIT: |
643 | id = p1[4]; | 660 | id = p1[4]; |
644 | break; /* continue to parse */ | 661 | break; /* continue to parse */ |
645 | case MIXER_UNIT: | 662 | case UAC_MIXER_UNIT: |
646 | term->type = p1[2] << 16; /* virtual type */ | 663 | term->type = p1[2] << 16; /* virtual type */ |
647 | term->channels = p1[5 + p1[4]]; | 664 | term->channels = p1[5 + p1[4]]; |
648 | term->chconfig = combine_word(p1 + 6 + p1[4]); | 665 | term->chconfig = combine_word(p1 + 6 + p1[4]); |
649 | term->name = p1[p1[0] - 1]; | 666 | term->name = p1[p1[0] - 1]; |
650 | return 0; | 667 | return 0; |
651 | case SELECTOR_UNIT: | 668 | case UAC_SELECTOR_UNIT: |
652 | /* call recursively to retrieve the channel info */ | 669 | /* call recursively to retrieve the channel info */ |
653 | if (check_input_term(state, p1[5], term) < 0) | 670 | if (check_input_term(state, p1[5], term) < 0) |
654 | return -ENODEV; | 671 | return -ENODEV; |
@@ -656,8 +673,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ | |||
656 | term->id = id; | 673 | term->id = id; |
657 | term->name = p1[9 + p1[0] - 1]; | 674 | term->name = p1[9 + p1[0] - 1]; |
658 | return 0; | 675 | return 0; |
659 | case PROCESSING_UNIT: | 676 | case UAC_PROCESSING_UNIT_V1: |
660 | case EXTENSION_UNIT: | 677 | case UAC_EXTENSION_UNIT_V1: |
661 | if (p1[6] == 1) { | 678 | if (p1[6] == 1) { |
662 | id = p1[7]; | 679 | id = p1[7]; |
663 | break; /* continue to parse */ | 680 | break; /* continue to parse */ |
@@ -720,6 +737,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
720 | cval->min = default_min; | 737 | cval->min = default_min; |
721 | cval->max = cval->min + 1; | 738 | cval->max = cval->min + 1; |
722 | cval->res = 1; | 739 | cval->res = 1; |
740 | cval->dBmin = cval->dBmax = 0; | ||
723 | 741 | ||
724 | if (cval->val_type == USB_MIXER_BOOLEAN || | 742 | if (cval->val_type == USB_MIXER_BOOLEAN || |
725 | cval->val_type == USB_MIXER_INV_BOOLEAN) { | 743 | cval->val_type == USB_MIXER_INV_BOOLEAN) { |
@@ -734,23 +752,23 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
734 | break; | 752 | break; |
735 | } | 753 | } |
736 | } | 754 | } |
737 | if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || | 755 | if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || |
738 | get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { | 756 | get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { |
739 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", | 757 | snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", |
740 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); | 758 | cval->id, cval->mixer->ctrlif, cval->control, cval->id); |
741 | return -EINVAL; | 759 | return -EINVAL; |
742 | } | 760 | } |
743 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { | 761 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { |
744 | cval->res = 1; | 762 | cval->res = 1; |
745 | } else { | 763 | } else { |
746 | int last_valid_res = cval->res; | 764 | int last_valid_res = cval->res; |
747 | 765 | ||
748 | while (cval->res > 1) { | 766 | while (cval->res > 1) { |
749 | if (set_ctl_value(cval, SET_RES, (cval->control << 8) | minchn, cval->res / 2) < 0) | 767 | if (set_ctl_value(cval, UAC_SET_RES, (cval->control << 8) | minchn, cval->res / 2) < 0) |
750 | break; | 768 | break; |
751 | cval->res /= 2; | 769 | cval->res /= 2; |
752 | } | 770 | } |
753 | if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) | 771 | if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) |
754 | cval->res = last_valid_res; | 772 | cval->res = last_valid_res; |
755 | } | 773 | } |
756 | if (cval->res == 0) | 774 | if (cval->res == 0) |
@@ -787,6 +805,24 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) | |||
787 | 805 | ||
788 | cval->initialized = 1; | 806 | cval->initialized = 1; |
789 | } | 807 | } |
808 | |||
809 | /* USB descriptions contain the dB scale in 1/256 dB unit | ||
810 | * while ALSA TLV contains in 1/100 dB unit | ||
811 | */ | ||
812 | cval->dBmin = (convert_signed_value(cval, cval->min) * 100) / 256; | ||
813 | cval->dBmax = (convert_signed_value(cval, cval->max) * 100) / 256; | ||
814 | if (cval->dBmin > cval->dBmax) { | ||
815 | /* something is wrong; assume it's either from/to 0dB */ | ||
816 | if (cval->dBmin < 0) | ||
817 | cval->dBmax = 0; | ||
818 | else if (cval->dBmin > 0) | ||
819 | cval->dBmin = 0; | ||
820 | if (cval->dBmin > cval->dBmax) { | ||
821 | /* totally crap, return an error */ | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | } | ||
825 | |||
790 | return 0; | 826 | return 0; |
791 | } | 827 | } |
792 | 828 | ||
@@ -912,6 +948,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
912 | int nameid = desc[desc[0] - 1]; | 948 | int nameid = desc[desc[0] - 1]; |
913 | struct snd_kcontrol *kctl; | 949 | struct snd_kcontrol *kctl; |
914 | struct usb_mixer_elem_info *cval; | 950 | struct usb_mixer_elem_info *cval; |
951 | const struct usbmix_name_map *map; | ||
915 | 952 | ||
916 | control++; /* change from zero-based to 1-based value */ | 953 | control++; /* change from zero-based to 1-based value */ |
917 | 954 | ||
@@ -920,7 +957,8 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
920 | return; | 957 | return; |
921 | } | 958 | } |
922 | 959 | ||
923 | if (check_ignored_ctl(state, unitid, control)) | 960 | map = find_map(state, unitid, control); |
961 | if (check_ignored_ctl(map)) | ||
924 | return; | 962 | return; |
925 | 963 | ||
926 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 964 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
@@ -954,10 +992,11 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
954 | } | 992 | } |
955 | kctl->private_free = usb_mixer_elem_free; | 993 | kctl->private_free = usb_mixer_elem_free; |
956 | 994 | ||
957 | len = check_mapped_name(state, unitid, control, kctl->id.name, sizeof(kctl->id.name)); | 995 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
958 | mapped_name = len != 0; | 996 | mapped_name = len != 0; |
959 | if (! len && nameid) | 997 | if (! len && nameid) |
960 | len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); | 998 | len = snd_usb_copy_string_desc(state, nameid, |
999 | kctl->id.name, sizeof(kctl->id.name)); | ||
961 | 1000 | ||
962 | switch (control) { | 1001 | switch (control) { |
963 | case USB_FEATURE_MUTE: | 1002 | case USB_FEATURE_MUTE: |
@@ -995,6 +1034,7 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
995 | kctl->vd[0].access |= | 1034 | kctl->vd[0].access |= |
996 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | 1035 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | |
997 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | 1036 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; |
1037 | check_mapped_dB(map, cval); | ||
998 | } | 1038 | } |
999 | break; | 1039 | break; |
1000 | 1040 | ||
@@ -1048,29 +1088,30 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
1048 | * | 1088 | * |
1049 | * most of controlls are defined here. | 1089 | * most of controlls are defined here. |
1050 | */ | 1090 | */ |
1051 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsigned char *ftr) | 1091 | static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void *_ftr) |
1052 | { | 1092 | { |
1053 | int channels, i, j; | 1093 | int channels, i, j; |
1054 | struct usb_audio_term iterm; | 1094 | struct usb_audio_term iterm; |
1055 | unsigned int master_bits, first_ch_bits; | 1095 | unsigned int master_bits, first_ch_bits; |
1056 | int err, csize; | 1096 | int err, csize; |
1097 | struct uac_feature_unit_descriptor *ftr = _ftr; | ||
1057 | 1098 | ||
1058 | if (ftr[0] < 7 || ! (csize = ftr[5]) || ftr[0] < 7 + csize) { | 1099 | if (ftr->bLength < 7 || ! (csize = ftr->bControlSize) || ftr->bLength < 7 + csize) { |
1059 | snd_printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); | 1100 | snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); |
1060 | return -EINVAL; | 1101 | return -EINVAL; |
1061 | } | 1102 | } |
1062 | 1103 | ||
1063 | /* parse the source unit */ | 1104 | /* parse the source unit */ |
1064 | if ((err = parse_audio_unit(state, ftr[4])) < 0) | 1105 | if ((err = parse_audio_unit(state, ftr->bSourceID)) < 0) |
1065 | return err; | 1106 | return err; |
1066 | 1107 | ||
1067 | /* determine the input source type and name */ | 1108 | /* determine the input source type and name */ |
1068 | if (check_input_term(state, ftr[4], &iterm) < 0) | 1109 | if (check_input_term(state, ftr->bSourceID, &iterm) < 0) |
1069 | return -EINVAL; | 1110 | return -EINVAL; |
1070 | 1111 | ||
1071 | channels = (ftr[0] - 7) / csize - 1; | 1112 | channels = (ftr->bLength - 7) / csize - 1; |
1072 | 1113 | ||
1073 | master_bits = snd_usb_combine_bytes(ftr + 6, csize); | 1114 | master_bits = snd_usb_combine_bytes(ftr->controls, csize); |
1074 | /* master configuration quirks */ | 1115 | /* master configuration quirks */ |
1075 | switch (state->chip->usb_id) { | 1116 | switch (state->chip->usb_id) { |
1076 | case USB_ID(0x08bb, 0x2702): | 1117 | case USB_ID(0x08bb, 0x2702): |
@@ -1081,21 +1122,21 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsig | |||
1081 | break; | 1122 | break; |
1082 | } | 1123 | } |
1083 | if (channels > 0) | 1124 | if (channels > 0) |
1084 | first_ch_bits = snd_usb_combine_bytes(ftr + 6 + csize, csize); | 1125 | first_ch_bits = snd_usb_combine_bytes(ftr->controls + csize, csize); |
1085 | else | 1126 | else |
1086 | first_ch_bits = 0; | 1127 | first_ch_bits = 0; |
1087 | /* check all control types */ | 1128 | /* check all control types */ |
1088 | for (i = 0; i < 10; i++) { | 1129 | for (i = 0; i < 10; i++) { |
1089 | unsigned int ch_bits = 0; | 1130 | unsigned int ch_bits = 0; |
1090 | for (j = 0; j < channels; j++) { | 1131 | for (j = 0; j < channels; j++) { |
1091 | unsigned int mask = snd_usb_combine_bytes(ftr + 6 + csize * (j+1), csize); | 1132 | unsigned int mask = snd_usb_combine_bytes(ftr->controls + csize * (j+1), csize); |
1092 | if (mask & (1 << i)) | 1133 | if (mask & (1 << i)) |
1093 | ch_bits |= (1 << j); | 1134 | ch_bits |= (1 << j); |
1094 | } | 1135 | } |
1095 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ | 1136 | if (ch_bits & 1) /* the first channel must be set (for ease of programming) */ |
1096 | build_feature_ctl(state, ftr, ch_bits, i, &iterm, unitid); | 1137 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid); |
1097 | if (master_bits & (1 << i)) | 1138 | if (master_bits & (1 << i)) |
1098 | build_feature_ctl(state, ftr, 0, i, &iterm, unitid); | 1139 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid); |
1099 | } | 1140 | } |
1100 | 1141 | ||
1101 | return 0; | 1142 | return 0; |
@@ -1122,8 +1163,10 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc, | |||
1122 | unsigned int num_outs = desc[5 + input_pins]; | 1163 | unsigned int num_outs = desc[5 + input_pins]; |
1123 | unsigned int i, len; | 1164 | unsigned int i, len; |
1124 | struct snd_kcontrol *kctl; | 1165 | struct snd_kcontrol *kctl; |
1166 | const struct usbmix_name_map *map; | ||
1125 | 1167 | ||
1126 | if (check_ignored_ctl(state, unitid, 0)) | 1168 | map = find_map(state, unitid, 0); |
1169 | if (check_ignored_ctl(map)) | ||
1127 | return; | 1170 | return; |
1128 | 1171 | ||
1129 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1172 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
@@ -1152,7 +1195,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc, | |||
1152 | } | 1195 | } |
1153 | kctl->private_free = usb_mixer_elem_free; | 1196 | kctl->private_free = usb_mixer_elem_free; |
1154 | 1197 | ||
1155 | len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name)); | 1198 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1156 | if (! len) | 1199 | if (! len) |
1157 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); | 1200 | len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); |
1158 | if (! len) | 1201 | if (! len) |
@@ -1330,7 +1373,32 @@ static struct procunit_info procunits[] = { | |||
1330 | { USB_PROC_DCR, "DCR", dcr_proc_info }, | 1373 | { USB_PROC_DCR, "DCR", dcr_proc_info }, |
1331 | { 0 }, | 1374 | { 0 }, |
1332 | }; | 1375 | }; |
1333 | 1376 | /* | |
1377 | * predefined data for extension units | ||
1378 | */ | ||
1379 | static struct procunit_value_info clock_rate_xu_info[] = { | ||
1380 | { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 }, | ||
1381 | { 0 } | ||
1382 | }; | ||
1383 | static struct procunit_value_info clock_source_xu_info[] = { | ||
1384 | { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN }, | ||
1385 | { 0 } | ||
1386 | }; | ||
1387 | static struct procunit_value_info spdif_format_xu_info[] = { | ||
1388 | { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN }, | ||
1389 | { 0 } | ||
1390 | }; | ||
1391 | static struct procunit_value_info soft_limit_xu_info[] = { | ||
1392 | { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN }, | ||
1393 | { 0 } | ||
1394 | }; | ||
1395 | static struct procunit_info extunits[] = { | ||
1396 | { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info }, | ||
1397 | { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info }, | ||
1398 | { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info }, | ||
1399 | { USB_XU_DEVICE_OPTIONS, "AnalogueIn Soft Limit", soft_limit_xu_info }, | ||
1400 | { 0 } | ||
1401 | }; | ||
1334 | /* | 1402 | /* |
1335 | * build a processing/extension unit | 1403 | * build a processing/extension unit |
1336 | */ | 1404 | */ |
@@ -1342,6 +1410,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned | |||
1342 | int i, err, nameid, type, len; | 1410 | int i, err, nameid, type, len; |
1343 | struct procunit_info *info; | 1411 | struct procunit_info *info; |
1344 | struct procunit_value_info *valinfo; | 1412 | struct procunit_value_info *valinfo; |
1413 | const struct usbmix_name_map *map; | ||
1345 | static struct procunit_value_info default_value_info[] = { | 1414 | static struct procunit_value_info default_value_info[] = { |
1346 | { 0x01, "Switch", USB_MIXER_BOOLEAN }, | 1415 | { 0x01, "Switch", USB_MIXER_BOOLEAN }, |
1347 | { 0 } | 1416 | { 0 } |
@@ -1371,7 +1440,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned | |||
1371 | /* FIXME: bitmap might be longer than 8bit */ | 1440 | /* FIXME: bitmap might be longer than 8bit */ |
1372 | if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1)))) | 1441 | if (! (dsc[12 + num_ins] & (1 << (valinfo->control - 1)))) |
1373 | continue; | 1442 | continue; |
1374 | if (check_ignored_ctl(state, unitid, valinfo->control)) | 1443 | map = find_map(state, unitid, valinfo->control); |
1444 | if (check_ignored_ctl(map)) | ||
1375 | continue; | 1445 | continue; |
1376 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1446 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
1377 | if (! cval) { | 1447 | if (! cval) { |
@@ -1391,8 +1461,18 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned | |||
1391 | cval->max = dsc[15]; | 1461 | cval->max = dsc[15]; |
1392 | cval->res = 1; | 1462 | cval->res = 1; |
1393 | cval->initialized = 1; | 1463 | cval->initialized = 1; |
1394 | } else | 1464 | } else { |
1395 | get_min_max(cval, valinfo->min_value); | 1465 | if (type == USB_XU_CLOCK_RATE) { |
1466 | /* E-Mu USB 0404/0202/TrackerPre | ||
1467 | * samplerate control quirk | ||
1468 | */ | ||
1469 | cval->min = 0; | ||
1470 | cval->max = 5; | ||
1471 | cval->res = 1; | ||
1472 | cval->initialized = 1; | ||
1473 | } else | ||
1474 | get_min_max(cval, valinfo->min_value); | ||
1475 | } | ||
1396 | 1476 | ||
1397 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); | 1477 | kctl = snd_ctl_new1(&mixer_procunit_ctl, cval); |
1398 | if (! kctl) { | 1478 | if (! kctl) { |
@@ -1402,8 +1482,9 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned | |||
1402 | } | 1482 | } |
1403 | kctl->private_free = usb_mixer_elem_free; | 1483 | kctl->private_free = usb_mixer_elem_free; |
1404 | 1484 | ||
1405 | if (check_mapped_name(state, unitid, cval->control, kctl->id.name, sizeof(kctl->id.name))) | 1485 | if (check_mapped_name(map, kctl->id.name, |
1406 | ; | 1486 | sizeof(kctl->id.name))) |
1487 | /* nothing */ ; | ||
1407 | else if (info->name) | 1488 | else if (info->name) |
1408 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); | 1489 | strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name)); |
1409 | else { | 1490 | else { |
@@ -1433,7 +1514,7 @@ static int parse_audio_processing_unit(struct mixer_build *state, int unitid, un | |||
1433 | 1514 | ||
1434 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc) | 1515 | static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc) |
1435 | { | 1516 | { |
1436 | return build_audio_procunit(state, unitid, desc, NULL, "Extension Unit"); | 1517 | return build_audio_procunit(state, unitid, desc, extunits, "Extension Unit"); |
1437 | } | 1518 | } |
1438 | 1519 | ||
1439 | 1520 | ||
@@ -1542,6 +1623,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi | |||
1542 | int err; | 1623 | int err; |
1543 | struct usb_mixer_elem_info *cval; | 1624 | struct usb_mixer_elem_info *cval; |
1544 | struct snd_kcontrol *kctl; | 1625 | struct snd_kcontrol *kctl; |
1626 | const struct usbmix_name_map *map; | ||
1545 | char **namelist; | 1627 | char **namelist; |
1546 | 1628 | ||
1547 | if (! num_ins || desc[0] < 5 + num_ins) { | 1629 | if (! num_ins || desc[0] < 5 + num_ins) { |
@@ -1557,7 +1639,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi | |||
1557 | if (num_ins == 1) /* only one ? nonsense! */ | 1639 | if (num_ins == 1) /* only one ? nonsense! */ |
1558 | return 0; | 1640 | return 0; |
1559 | 1641 | ||
1560 | if (check_ignored_ctl(state, unitid, 0)) | 1642 | map = find_map(state, unitid, 0); |
1643 | if (check_ignored_ctl(map)) | ||
1561 | return 0; | 1644 | return 0; |
1562 | 1645 | ||
1563 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | 1646 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); |
@@ -1612,7 +1695,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi | |||
1612 | kctl->private_free = usb_mixer_selector_elem_free; | 1695 | kctl->private_free = usb_mixer_selector_elem_free; |
1613 | 1696 | ||
1614 | nameid = desc[desc[0] - 1]; | 1697 | nameid = desc[desc[0] - 1]; |
1615 | len = check_mapped_name(state, unitid, 0, kctl->id.name, sizeof(kctl->id.name)); | 1698 | len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)); |
1616 | if (len) | 1699 | if (len) |
1617 | ; | 1700 | ; |
1618 | else if (nameid) | 1701 | else if (nameid) |
@@ -1656,17 +1739,17 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) | |||
1656 | } | 1739 | } |
1657 | 1740 | ||
1658 | switch (p1[2]) { | 1741 | switch (p1[2]) { |
1659 | case INPUT_TERMINAL: | 1742 | case UAC_INPUT_TERMINAL: |
1660 | return 0; /* NOP */ | 1743 | return 0; /* NOP */ |
1661 | case MIXER_UNIT: | 1744 | case UAC_MIXER_UNIT: |
1662 | return parse_audio_mixer_unit(state, unitid, p1); | 1745 | return parse_audio_mixer_unit(state, unitid, p1); |
1663 | case SELECTOR_UNIT: | 1746 | case UAC_SELECTOR_UNIT: |
1664 | return parse_audio_selector_unit(state, unitid, p1); | 1747 | return parse_audio_selector_unit(state, unitid, p1); |
1665 | case FEATURE_UNIT: | 1748 | case UAC_FEATURE_UNIT: |
1666 | return parse_audio_feature_unit(state, unitid, p1); | 1749 | return parse_audio_feature_unit(state, unitid, p1); |
1667 | case PROCESSING_UNIT: | 1750 | case UAC_PROCESSING_UNIT_V1: |
1668 | return parse_audio_processing_unit(state, unitid, p1); | 1751 | return parse_audio_processing_unit(state, unitid, p1); |
1669 | case EXTENSION_UNIT: | 1752 | case UAC_EXTENSION_UNIT_V1: |
1670 | return parse_audio_extension_unit(state, unitid, p1); | 1753 | return parse_audio_extension_unit(state, unitid, p1); |
1671 | default: | 1754 | default: |
1672 | snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); | 1755 | snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]); |
@@ -1696,11 +1779,11 @@ static int snd_usb_mixer_dev_free(struct snd_device *device) | |||
1696 | /* | 1779 | /* |
1697 | * create mixer controls | 1780 | * create mixer controls |
1698 | * | 1781 | * |
1699 | * walk through all OUTPUT_TERMINAL descriptors to search for mixers | 1782 | * walk through all UAC_OUTPUT_TERMINAL descriptors to search for mixers |
1700 | */ | 1783 | */ |
1701 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | 1784 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1702 | { | 1785 | { |
1703 | unsigned char *desc; | 1786 | struct uac_output_terminal_descriptor_v1 *desc; |
1704 | struct mixer_build state; | 1787 | struct mixer_build state; |
1705 | int err; | 1788 | int err; |
1706 | const struct usbmix_ctl_map *map; | 1789 | const struct usbmix_ctl_map *map; |
@@ -1724,14 +1807,14 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
1724 | } | 1807 | } |
1725 | 1808 | ||
1726 | desc = NULL; | 1809 | desc = NULL; |
1727 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) { | 1810 | while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, UAC_OUTPUT_TERMINAL)) != NULL) { |
1728 | if (desc[0] < 9) | 1811 | if (desc->bLength < 9) |
1729 | continue; /* invalid descriptor? */ | 1812 | continue; /* invalid descriptor? */ |
1730 | set_bit(desc[3], state.unitbitmap); /* mark terminal ID as visited */ | 1813 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ |
1731 | state.oterm.id = desc[3]; | 1814 | state.oterm.id = desc->bTerminalID; |
1732 | state.oterm.type = combine_word(&desc[4]); | 1815 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
1733 | state.oterm.name = desc[8]; | 1816 | state.oterm.name = desc->iTerminal; |
1734 | err = parse_audio_unit(&state, desc[7]); | 1817 | err = parse_audio_unit(&state, desc->bSourceID); |
1735 | if (err < 0) | 1818 | if (err < 0) |
1736 | return err; | 1819 | return err; |
1737 | } | 1820 | } |
@@ -1748,6 +1831,46 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | |||
1748 | info->elem_id); | 1831 | info->elem_id); |
1749 | } | 1832 | } |
1750 | 1833 | ||
1834 | static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, | ||
1835 | int unitid, | ||
1836 | struct usb_mixer_elem_info *cval) | ||
1837 | { | ||
1838 | static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN", | ||
1839 | "S8", "U8", "S16", "U16"}; | ||
1840 | snd_iprintf(buffer, " Unit: %i\n", unitid); | ||
1841 | if (cval->elem_id) | ||
1842 | snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n", | ||
1843 | cval->elem_id->name, cval->elem_id->index); | ||
1844 | snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " | ||
1845 | "channels=%i, type=\"%s\"\n", cval->id, | ||
1846 | cval->control, cval->cmask, cval->channels, | ||
1847 | val_types[cval->val_type]); | ||
1848 | snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n", | ||
1849 | cval->min, cval->max, cval->dBmin, cval->dBmax); | ||
1850 | } | ||
1851 | |||
1852 | static void snd_usb_mixer_proc_read(struct snd_info_entry *entry, | ||
1853 | struct snd_info_buffer *buffer) | ||
1854 | { | ||
1855 | struct snd_usb_audio *chip = entry->private_data; | ||
1856 | struct usb_mixer_interface *mixer; | ||
1857 | struct usb_mixer_elem_info *cval; | ||
1858 | int unitid; | ||
1859 | |||
1860 | list_for_each_entry(mixer, &chip->mixer_list, list) { | ||
1861 | snd_iprintf(buffer, | ||
1862 | "USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n", | ||
1863 | chip->usb_id, mixer->ctrlif, | ||
1864 | mixer->ignore_ctl_error); | ||
1865 | snd_iprintf(buffer, "Card: %s\n", chip->card->longname); | ||
1866 | for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) { | ||
1867 | for (cval = mixer->id_elems[unitid]; cval; | ||
1868 | cval = cval->next_id_elem) | ||
1869 | snd_usb_mixer_dump_cval(buffer, unitid, cval); | ||
1870 | } | ||
1871 | } | ||
1872 | } | ||
1873 | |||
1751 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | 1874 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, |
1752 | int unitid) | 1875 | int unitid) |
1753 | { | 1876 | { |
@@ -1924,7 +2047,7 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | |||
1924 | } | 2047 | } |
1925 | mixer->rc_setup_packet->bRequestType = | 2048 | mixer->rc_setup_packet->bRequestType = |
1926 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; | 2049 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
1927 | mixer->rc_setup_packet->bRequest = GET_MEM; | 2050 | mixer->rc_setup_packet->bRequest = UAC_GET_MEM; |
1928 | mixer->rc_setup_packet->wValue = cpu_to_le16(0); | 2051 | mixer->rc_setup_packet->wValue = cpu_to_le16(0); |
1929 | mixer->rc_setup_packet->wIndex = cpu_to_le16(0); | 2052 | mixer->rc_setup_packet->wIndex = cpu_to_le16(0); |
1930 | mixer->rc_setup_packet->wLength = cpu_to_le16(len); | 2053 | mixer->rc_setup_packet->wLength = cpu_to_le16(len); |
@@ -2047,7 +2170,7 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
2047 | snd_iprintf(buffer, "%s: ", jacks[i].name); | 2170 | snd_iprintf(buffer, "%s: ", jacks[i].name); |
2048 | err = snd_usb_ctl_msg(mixer->chip->dev, | 2171 | err = snd_usb_ctl_msg(mixer->chip->dev, |
2049 | usb_rcvctrlpipe(mixer->chip->dev, 0), | 2172 | usb_rcvctrlpipe(mixer->chip->dev, 0), |
2050 | GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | | 2173 | UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | |
2051 | USB_RECIP_INTERFACE, 0, | 2174 | USB_RECIP_INTERFACE, 0, |
2052 | jacks[i].unitid << 8, buf, 3, 100); | 2175 | jacks[i].unitid << 8, buf, 3, 100); |
2053 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) | 2176 | if (err == 3 && (buf[0] == 3 || buf[0] == 6)) |
@@ -2109,6 +2232,24 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | |||
2109 | return 0; | 2232 | return 0; |
2110 | } | 2233 | } |
2111 | 2234 | ||
2235 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | ||
2236 | unsigned char samplerate_id) | ||
2237 | { | ||
2238 | struct usb_mixer_interface *mixer; | ||
2239 | struct usb_mixer_elem_info *cval; | ||
2240 | int unitid = 12; /* SamleRate ExtensionUnit ID */ | ||
2241 | |||
2242 | list_for_each_entry(mixer, &chip->mixer_list, list) { | ||
2243 | cval = mixer->id_elems[unitid]; | ||
2244 | if (cval) { | ||
2245 | set_cur_ctl_value(cval, cval->control << 8, | ||
2246 | samplerate_id); | ||
2247 | snd_usb_mixer_notify_id(mixer, unitid); | ||
2248 | } | ||
2249 | break; | ||
2250 | } | ||
2251 | } | ||
2252 | |||
2112 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | 2253 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, |
2113 | int ignore_error) | 2254 | int ignore_error) |
2114 | { | 2255 | { |
@@ -2116,7 +2257,9 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2116 | .dev_free = snd_usb_mixer_dev_free | 2257 | .dev_free = snd_usb_mixer_dev_free |
2117 | }; | 2258 | }; |
2118 | struct usb_mixer_interface *mixer; | 2259 | struct usb_mixer_interface *mixer; |
2119 | int err; | 2260 | struct snd_info_entry *entry; |
2261 | struct usb_host_interface *host_iface; | ||
2262 | int err, protocol; | ||
2120 | 2263 | ||
2121 | strcpy(chip->card->mixername, "USB Mixer"); | 2264 | strcpy(chip->card->mixername, "USB Mixer"); |
2122 | 2265 | ||
@@ -2126,12 +2269,23 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2126 | mixer->chip = chip; | 2269 | mixer->chip = chip; |
2127 | mixer->ctrlif = ctrlif; | 2270 | mixer->ctrlif = ctrlif; |
2128 | mixer->ignore_ctl_error = ignore_error; | 2271 | mixer->ignore_ctl_error = ignore_error; |
2129 | mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL); | 2272 | mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems), |
2273 | GFP_KERNEL); | ||
2130 | if (!mixer->id_elems) { | 2274 | if (!mixer->id_elems) { |
2131 | kfree(mixer); | 2275 | kfree(mixer); |
2132 | return -ENOMEM; | 2276 | return -ENOMEM; |
2133 | } | 2277 | } |
2134 | 2278 | ||
2279 | host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0]; | ||
2280 | protocol = host_iface->desc.bInterfaceProtocol; | ||
2281 | |||
2282 | /* FIXME! */ | ||
2283 | if (protocol != UAC_VERSION_1) { | ||
2284 | snd_printk(KERN_WARNING "mixer interface protocol 0x%02x not yet supported\n", | ||
2285 | protocol); | ||
2286 | return 0; | ||
2287 | } | ||
2288 | |||
2135 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || | 2289 | if ((err = snd_usb_mixer_controls(mixer)) < 0 || |
2136 | (err = snd_usb_mixer_status_create(mixer)) < 0) | 2290 | (err = snd_usb_mixer_status_create(mixer)) < 0) |
2137 | goto _error; | 2291 | goto _error; |
@@ -2142,8 +2296,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2142 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || | 2296 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || |
2143 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 2297 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
2144 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { | 2298 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { |
2145 | struct snd_info_entry *entry; | ||
2146 | |||
2147 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 2299 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) |
2148 | goto _error; | 2300 | goto _error; |
2149 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | 2301 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) |
@@ -2161,6 +2313,11 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2161 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | 2313 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); |
2162 | if (err < 0) | 2314 | if (err < 0) |
2163 | goto _error; | 2315 | goto _error; |
2316 | |||
2317 | if (list_empty(&chip->mixer_list) && | ||
2318 | !snd_card_proc_new(chip->card, "usbmixer", &entry)) | ||
2319 | snd_info_set_text_ops(entry, chip, snd_usb_mixer_proc_read); | ||
2320 | |||
2164 | list_add(&mixer->list, &chip->mixer_list); | 2321 | list_add(&mixer->list, &chip->mixer_list); |
2165 | return 0; | 2322 | return 0; |
2166 | 2323 | ||