diff options
author | Daniel Mack <daniel@caiaq.de> | 2010-02-22 17:49:09 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-02-23 02:40:12 -0500 |
commit | 28e1b773083d349d5223f586a39fa30f5d0f1c36 (patch) | |
tree | 4793eb1d87a094cf3642600ac3b201f81bab7e54 /sound | |
parent | 40717382e0c1f572553e4fdefb489db4b95a5e7e (diff) |
ALSA: usbaudio: parse USB descriptors with structs
In preparation of support for v2.0 audio class, use the structs from
linux/usb/audio.h and add some new ones to describe the fields that are
actually parsed by the descriptor decoders.
Also, factor out code from usb_create_streams(). This makes it easier to
adopt the new iteration logic needed for v2.0.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/usb/usbaudio.c | 198 | ||||
-rw-r--r-- | sound/usb/usbmixer.c | 37 |
2 files changed, 140 insertions, 95 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index c6b9c8cac59..f833dea6018 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include <linux/usb.h> | 46 | #include <linux/usb.h> |
47 | #include <linux/moduleparam.h> | 47 | #include <linux/moduleparam.h> |
48 | #include <linux/mutex.h> | 48 | #include <linux/mutex.h> |
49 | #include <linux/usb/audio.h> | ||
50 | |||
49 | #include <sound/core.h> | 51 | #include <sound/core.h> |
50 | #include <sound/info.h> | 52 | #include <sound/info.h> |
51 | #include <sound/pcm.h> | 53 | #include <sound/pcm.h> |
@@ -2421,15 +2423,17 @@ static int is_big_endian_format(struct snd_usb_audio *chip, struct audioformat * | |||
2421 | * @fmt: the format type descriptor | 2423 | * @fmt: the format type descriptor |
2422 | */ | 2424 | */ |
2423 | static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audioformat *fp, | 2425 | static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audioformat *fp, |
2424 | int format, unsigned char *fmt) | 2426 | int format, void *fmt_raw) |
2425 | { | 2427 | { |
2426 | int pcm_format; | 2428 | int pcm_format; |
2427 | int sample_width, sample_bytes; | 2429 | int sample_width, sample_bytes; |
2430 | struct uac_format_type_i_discrete_descriptor *fmt = fmt_raw; | ||
2428 | 2431 | ||
2429 | /* FIXME: correct endianess and sign? */ | 2432 | /* FIXME: correct endianess and sign? */ |
2430 | pcm_format = -1; | 2433 | pcm_format = -1; |
2431 | sample_width = fmt[6]; | 2434 | sample_width = fmt->bBitResolution; |
2432 | sample_bytes = fmt[5]; | 2435 | sample_bytes = fmt->bSubframeSize; |
2436 | |||
2433 | switch (format) { | 2437 | switch (format) { |
2434 | case 0: /* some devices don't define this correctly... */ | 2438 | case 0: /* some devices don't define this correctly... */ |
2435 | snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", | 2439 | snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n", |
@@ -2442,7 +2446,7 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor | |||
2442 | sample_width, sample_bytes); | 2446 | sample_width, sample_bytes); |
2443 | } | 2447 | } |
2444 | /* check the format byte size */ | 2448 | /* check the format byte size */ |
2445 | switch (fmt[5]) { | 2449 | switch (sample_bytes) { |
2446 | case 1: | 2450 | case 1: |
2447 | pcm_format = SNDRV_PCM_FORMAT_S8; | 2451 | pcm_format = SNDRV_PCM_FORMAT_S8; |
2448 | break; | 2452 | break; |
@@ -2463,8 +2467,8 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audiofor | |||
2463 | break; | 2467 | break; |
2464 | default: | 2468 | default: |
2465 | snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", | 2469 | snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n", |
2466 | chip->dev->devnum, fp->iface, | 2470 | chip->dev->devnum, fp->iface, fp->altsetting, |
2467 | fp->altsetting, sample_width, sample_bytes); | 2471 | sample_width, sample_bytes); |
2468 | break; | 2472 | break; |
2469 | } | 2473 | } |
2470 | break; | 2474 | break; |
@@ -2564,11 +2568,12 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform | |||
2564 | * parse the format type I and III descriptors | 2568 | * parse the format type I and III descriptors |
2565 | */ | 2569 | */ |
2566 | static int parse_audio_format_i(struct snd_usb_audio *chip, struct audioformat *fp, | 2570 | static int parse_audio_format_i(struct snd_usb_audio *chip, struct audioformat *fp, |
2567 | int format, unsigned char *fmt) | 2571 | int format, void *fmt_raw) |
2568 | { | 2572 | { |
2569 | int pcm_format; | 2573 | int pcm_format; |
2574 | struct uac_format_type_i_discrete_descriptor *fmt = fmt_raw; | ||
2570 | 2575 | ||
2571 | if (fmt[3] == USB_FORMAT_TYPE_III) { | 2576 | if (fmt->bFormatType == USB_FORMAT_TYPE_III) { |
2572 | /* FIXME: the format type is really IECxxx | 2577 | /* FIXME: the format type is really IECxxx |
2573 | * but we give normal PCM format to get the existing | 2578 | * but we give normal PCM format to get the existing |
2574 | * apps working... | 2579 | * apps working... |
@@ -2590,23 +2595,27 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, struct audioformat * | |||
2590 | if (pcm_format < 0) | 2595 | if (pcm_format < 0) |
2591 | return -1; | 2596 | return -1; |
2592 | } | 2597 | } |
2598 | |||
2593 | fp->format = pcm_format; | 2599 | fp->format = pcm_format; |
2594 | fp->channels = fmt[4]; | 2600 | fp->channels = fmt->bNrChannels; |
2601 | |||
2595 | if (fp->channels < 1) { | 2602 | if (fp->channels < 1) { |
2596 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", | 2603 | snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n", |
2597 | chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); | 2604 | chip->dev->devnum, fp->iface, fp->altsetting, fp->channels); |
2598 | return -1; | 2605 | return -1; |
2599 | } | 2606 | } |
2600 | return parse_audio_format_rates(chip, fp, fmt, 7); | 2607 | return parse_audio_format_rates(chip, fp, fmt_raw, 7); |
2601 | } | 2608 | } |
2602 | 2609 | ||
2603 | /* | 2610 | /* |
2604 | * prase the format type II descriptor | 2611 | * parse the format type II descriptor |
2605 | */ | 2612 | */ |
2606 | static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat *fp, | 2613 | static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat *fp, |
2607 | int format, unsigned char *fmt) | 2614 | int format, void *fmt_raw) |
2608 | { | 2615 | { |
2609 | int brate, framesize; | 2616 | int brate, framesize; |
2617 | struct uac_format_type_ii_discrete_descriptor *fmt = fmt_raw; | ||
2618 | |||
2610 | switch (format) { | 2619 | switch (format) { |
2611 | case USB_AUDIO_FORMAT_AC3: | 2620 | case USB_AUDIO_FORMAT_AC3: |
2612 | /* FIXME: there is no AC3 format defined yet */ | 2621 | /* FIXME: there is no AC3 format defined yet */ |
@@ -2622,20 +2631,25 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat | |||
2622 | fp->format = SNDRV_PCM_FORMAT_MPEG; | 2631 | fp->format = SNDRV_PCM_FORMAT_MPEG; |
2623 | break; | 2632 | break; |
2624 | } | 2633 | } |
2634 | |||
2625 | fp->channels = 1; | 2635 | fp->channels = 1; |
2626 | brate = combine_word(&fmt[4]); /* fmt[4,5] : wMaxBitRate (in kbps) */ | 2636 | |
2627 | framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */ | 2637 | brate = le16_to_cpu(fmt->wMaxBitRate); |
2638 | framesize = le16_to_cpu(fmt->wSamplesPerFrame); | ||
2628 | snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); | 2639 | snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize); |
2629 | fp->frame_size = framesize; | 2640 | fp->frame_size = framesize; |
2630 | return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */ | 2641 | return parse_audio_format_rates(chip, fp, fmt_raw, 8); /* fmt[8..] sample rates */ |
2631 | } | 2642 | } |
2632 | 2643 | ||
2633 | static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, | 2644 | static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp, |
2634 | int format, unsigned char *fmt, int stream) | 2645 | int format, void *fmt_raw, int stream) |
2635 | { | 2646 | { |
2636 | int err; | 2647 | int err; |
2648 | /* we only parse the common header of all format types here, | ||
2649 | * so it is safe to take a type_i struct */ | ||
2650 | struct uac_format_type_i_discrete_descriptor *fmt = fmt_raw; | ||
2637 | 2651 | ||
2638 | switch (fmt[3]) { | 2652 | switch (fmt->bFormatType) { |
2639 | case USB_FORMAT_TYPE_I: | 2653 | case USB_FORMAT_TYPE_I: |
2640 | case USB_FORMAT_TYPE_III: | 2654 | case USB_FORMAT_TYPE_III: |
2641 | err = parse_audio_format_i(chip, fp, format, fmt); | 2655 | err = parse_audio_format_i(chip, fp, format, fmt); |
@@ -2645,10 +2659,10 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp | |||
2645 | break; | 2659 | break; |
2646 | default: | 2660 | default: |
2647 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", | 2661 | snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", |
2648 | chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]); | 2662 | chip->dev->devnum, fp->iface, fp->altsetting, fmt->bFormatType); |
2649 | return -1; | 2663 | return -1; |
2650 | } | 2664 | } |
2651 | fp->fmt_type = fmt[3]; | 2665 | fp->fmt_type = fmt->bFormatType; |
2652 | if (err < 0) | 2666 | if (err < 0) |
2653 | return err; | 2667 | return err; |
2654 | #if 1 | 2668 | #if 1 |
@@ -2659,7 +2673,7 @@ static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp | |||
2659 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || | 2673 | if (chip->usb_id == USB_ID(0x041e, 0x3000) || |
2660 | chip->usb_id == USB_ID(0x041e, 0x3020) || | 2674 | chip->usb_id == USB_ID(0x041e, 0x3020) || |
2661 | chip->usb_id == USB_ID(0x041e, 0x3061)) { | 2675 | chip->usb_id == USB_ID(0x041e, 0x3061)) { |
2662 | if (fmt[3] == USB_FORMAT_TYPE_I && | 2676 | if (fmt->bFormatType == USB_FORMAT_TYPE_I && |
2663 | fp->rates != SNDRV_PCM_RATE_48000 && | 2677 | fp->rates != SNDRV_PCM_RATE_48000 && |
2664 | fp->rates != SNDRV_PCM_RATE_96000) | 2678 | fp->rates != SNDRV_PCM_RATE_96000) |
2665 | return -1; | 2679 | return -1; |
@@ -2708,6 +2722,8 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2708 | num = 4; | 2722 | num = 4; |
2709 | 2723 | ||
2710 | for (i = 0; i < num; i++) { | 2724 | for (i = 0; i < num; i++) { |
2725 | struct uac_as_header_descriptor_v1 *as; | ||
2726 | |||
2711 | alts = &iface->altsetting[i]; | 2727 | alts = &iface->altsetting[i]; |
2712 | altsd = get_iface_desc(alts); | 2728 | altsd = get_iface_desc(alts); |
2713 | /* skip invalid one */ | 2729 | /* skip invalid one */ |
@@ -2726,7 +2742,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2726 | stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? | 2742 | stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ? |
2727 | SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; | 2743 | SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK; |
2728 | altno = altsd->bAlternateSetting; | 2744 | altno = altsd->bAlternateSetting; |
2729 | 2745 | ||
2730 | /* audiophile usb: skip altsets incompatible with device_setup | 2746 | /* audiophile usb: skip altsets incompatible with device_setup |
2731 | */ | 2747 | */ |
2732 | if (chip->usb_id == USB_ID(0x0763, 0x2003) && | 2748 | if (chip->usb_id == USB_ID(0x0763, 0x2003) && |
@@ -2734,20 +2750,21 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2734 | continue; | 2750 | continue; |
2735 | 2751 | ||
2736 | /* get audio formats */ | 2752 | /* get audio formats */ |
2737 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, AS_GENERAL); | 2753 | as = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, AS_GENERAL); |
2738 | if (!fmt) { | 2754 | |
2755 | if (!as) { | ||
2739 | snd_printk(KERN_ERR "%d:%u:%d : AS_GENERAL descriptor not found\n", | 2756 | snd_printk(KERN_ERR "%d:%u:%d : AS_GENERAL descriptor not found\n", |
2740 | dev->devnum, iface_no, altno); | 2757 | dev->devnum, iface_no, altno); |
2741 | continue; | 2758 | continue; |
2742 | } | 2759 | } |
2743 | 2760 | ||
2744 | if (fmt[0] < 7) { | 2761 | if (as->bLength < sizeof(*as)) { |
2745 | snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n", | 2762 | snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n", |
2746 | dev->devnum, iface_no, altno); | 2763 | dev->devnum, iface_no, altno); |
2747 | continue; | 2764 | continue; |
2748 | } | 2765 | } |
2749 | 2766 | ||
2750 | format = (fmt[6] << 8) | fmt[5]; /* remember the format value */ | 2767 | format = le16_to_cpu(as->wFormatTag); /* remember the format value */ |
2751 | 2768 | ||
2752 | /* get format type */ | 2769 | /* get format type */ |
2753 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, FORMAT_TYPE); | 2770 | fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, FORMAT_TYPE); |
@@ -2875,6 +2892,65 @@ static void snd_usb_stream_disconnect(struct list_head *head) | |||
2875 | } | 2892 | } |
2876 | } | 2893 | } |
2877 | 2894 | ||
2895 | static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int interface) | ||
2896 | { | ||
2897 | struct usb_device *dev = chip->dev; | ||
2898 | struct usb_host_interface *alts; | ||
2899 | struct usb_interface_descriptor *altsd; | ||
2900 | struct usb_interface *iface = usb_ifnum_to_if(dev, interface); | ||
2901 | |||
2902 | if (!iface) { | ||
2903 | snd_printk(KERN_ERR "%d:%u:%d : does not exist\n", | ||
2904 | dev->devnum, ctrlif, interface); | ||
2905 | return -EINVAL; | ||
2906 | } | ||
2907 | |||
2908 | if (usb_interface_claimed(iface)) { | ||
2909 | snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", | ||
2910 | dev->devnum, ctrlif, interface); | ||
2911 | return -EINVAL; | ||
2912 | } | ||
2913 | |||
2914 | alts = &iface->altsetting[0]; | ||
2915 | altsd = get_iface_desc(alts); | ||
2916 | if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || | ||
2917 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && | ||
2918 | altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) { | ||
2919 | int err = snd_usbmidi_create(chip->card, iface, | ||
2920 | &chip->midi_list, NULL); | ||
2921 | if (err < 0) { | ||
2922 | snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", | ||
2923 | dev->devnum, ctrlif, interface); | ||
2924 | return -EINVAL; | ||
2925 | } | ||
2926 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); | ||
2927 | |||
2928 | return 0; | ||
2929 | } | ||
2930 | |||
2931 | if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && | ||
2932 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || | ||
2933 | altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) { | ||
2934 | snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", | ||
2935 | dev->devnum, ctrlif, interface, altsd->bInterfaceClass); | ||
2936 | /* skip non-supported classes */ | ||
2937 | return -EINVAL; | ||
2938 | } | ||
2939 | |||
2940 | if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { | ||
2941 | snd_printk(KERN_ERR "low speed audio streaming not supported\n"); | ||
2942 | return -EINVAL; | ||
2943 | } | ||
2944 | |||
2945 | if (! parse_audio_endpoints(chip, interface)) { | ||
2946 | usb_set_interface(dev, interface, 0); /* reset the current interface */ | ||
2947 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); | ||
2948 | return -EINVAL; | ||
2949 | } | ||
2950 | |||
2951 | return 0; | ||
2952 | } | ||
2953 | |||
2878 | /* | 2954 | /* |
2879 | * parse audio control descriptor and create pcm/midi streams | 2955 | * parse audio control descriptor and create pcm/midi streams |
2880 | */ | 2956 | */ |
@@ -2882,69 +2958,36 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif) | |||
2882 | { | 2958 | { |
2883 | struct usb_device *dev = chip->dev; | 2959 | struct usb_device *dev = chip->dev; |
2884 | struct usb_host_interface *host_iface; | 2960 | struct usb_host_interface *host_iface; |
2885 | struct usb_interface *iface; | 2961 | struct uac_ac_header_descriptor_v1 *h1; |
2886 | unsigned char *p1; | 2962 | void *control_header; |
2887 | int i, j; | 2963 | int i; |
2888 | 2964 | ||
2889 | /* find audiocontrol interface */ | 2965 | /* find audiocontrol interface */ |
2890 | host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; | 2966 | host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0]; |
2891 | if (!(p1 = snd_usb_find_csint_desc(host_iface->extra, host_iface->extralen, NULL, HEADER))) { | 2967 | control_header = snd_usb_find_csint_desc(host_iface->extra, |
2968 | host_iface->extralen, | ||
2969 | NULL, HEADER); | ||
2970 | |||
2971 | if (!control_header) { | ||
2892 | snd_printk(KERN_ERR "cannot find HEADER\n"); | 2972 | snd_printk(KERN_ERR "cannot find HEADER\n"); |
2893 | return -EINVAL; | 2973 | return -EINVAL; |
2894 | } | 2974 | } |
2895 | if (! p1[7] || p1[0] < 8 + p1[7]) { | 2975 | |
2896 | snd_printk(KERN_ERR "invalid HEADER\n"); | 2976 | h1 = control_header; |
2977 | |||
2978 | if (!h1->bInCollection) { | ||
2979 | snd_printk(KERN_INFO "skipping empty audio interface (v1)\n"); | ||
2897 | return -EINVAL; | 2980 | return -EINVAL; |
2898 | } | 2981 | } |
2899 | 2982 | ||
2900 | /* | 2983 | if (h1->bLength < sizeof(*h1) + h1->bInCollection) { |
2901 | * parse all USB audio streaming interfaces | 2984 | snd_printk(KERN_ERR "invalid HEADER (v1)\n"); |
2902 | */ | 2985 | return -EINVAL; |
2903 | for (i = 0; i < p1[7]; i++) { | ||
2904 | struct usb_host_interface *alts; | ||
2905 | struct usb_interface_descriptor *altsd; | ||
2906 | j = p1[8 + i]; | ||
2907 | iface = usb_ifnum_to_if(dev, j); | ||
2908 | if (!iface) { | ||
2909 | snd_printk(KERN_ERR "%d:%u:%d : does not exist\n", | ||
2910 | dev->devnum, ctrlif, j); | ||
2911 | continue; | ||
2912 | } | ||
2913 | if (usb_interface_claimed(iface)) { | ||
2914 | snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", dev->devnum, ctrlif, j); | ||
2915 | continue; | ||
2916 | } | ||
2917 | alts = &iface->altsetting[0]; | ||
2918 | altsd = get_iface_desc(alts); | ||
2919 | if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || | ||
2920 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && | ||
2921 | altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) { | ||
2922 | int err = snd_usbmidi_create(chip->card, iface, | ||
2923 | &chip->midi_list, NULL); | ||
2924 | if (err < 0) { | ||
2925 | snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j); | ||
2926 | continue; | ||
2927 | } | ||
2928 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); | ||
2929 | continue; | ||
2930 | } | ||
2931 | if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && | ||
2932 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || | ||
2933 | altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIO_STREAMING) { | ||
2934 | snd_printdd(KERN_ERR "%d:%u:%d: skipping non-supported interface %d\n", dev->devnum, ctrlif, j, altsd->bInterfaceClass); | ||
2935 | /* skip non-supported classes */ | ||
2936 | continue; | ||
2937 | } | ||
2938 | if (snd_usb_get_speed(dev) == USB_SPEED_LOW) { | ||
2939 | snd_printk(KERN_ERR "low speed audio streaming not supported\n"); | ||
2940 | continue; | ||
2941 | } | ||
2942 | if (! parse_audio_endpoints(chip, j)) { | ||
2943 | usb_set_interface(dev, j, 0); /* reset the current interface */ | ||
2944 | usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L); | ||
2945 | } | ||
2946 | } | 2986 | } |
2947 | 2987 | ||
2988 | for (i = 0; i < h1->bInCollection; i++) | ||
2989 | snd_usb_create_stream(chip, ctrlif, h1->baInterfaceNr[i]); | ||
2990 | |||
2948 | return 0; | 2991 | return 0; |
2949 | } | 2992 | } |
2950 | 2993 | ||
@@ -3607,7 +3650,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
3607 | ifnum = get_iface_desc(alts)->bInterfaceNumber; | 3650 | ifnum = get_iface_desc(alts)->bInterfaceNumber; |
3608 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | 3651 | id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), |
3609 | le16_to_cpu(dev->descriptor.idProduct)); | 3652 | le16_to_cpu(dev->descriptor.idProduct)); |
3610 | |||
3611 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) | 3653 | if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) |
3612 | goto __err_val; | 3654 | goto __err_val; |
3613 | 3655 | ||
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index 35b4830fb0c..11636a6112d 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> |
@@ -1086,29 +1088,30 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, | |||
1086 | * | 1088 | * |
1087 | * most of controlls are defined here. | 1089 | * most of controlls are defined here. |
1088 | */ | 1090 | */ |
1089 | 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) |
1090 | { | 1092 | { |
1091 | int channels, i, j; | 1093 | int channels, i, j; |
1092 | struct usb_audio_term iterm; | 1094 | struct usb_audio_term iterm; |
1093 | unsigned int master_bits, first_ch_bits; | 1095 | unsigned int master_bits, first_ch_bits; |
1094 | int err, csize; | 1096 | int err, csize; |
1097 | struct uac_feature_unit_descriptor *ftr = _ftr; | ||
1095 | 1098 | ||
1096 | if (ftr[0] < 7 || ! (csize = ftr[5]) || ftr[0] < 7 + csize) { | 1099 | if (ftr->bLength < 7 || ! (csize = ftr->bControlSize) || ftr->bLength < 7 + csize) { |
1097 | snd_printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); | 1100 | snd_printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", unitid); |
1098 | return -EINVAL; | 1101 | return -EINVAL; |
1099 | } | 1102 | } |
1100 | 1103 | ||
1101 | /* parse the source unit */ | 1104 | /* parse the source unit */ |
1102 | if ((err = parse_audio_unit(state, ftr[4])) < 0) | 1105 | if ((err = parse_audio_unit(state, ftr->bSourceID)) < 0) |
1103 | return err; | 1106 | return err; |
1104 | 1107 | ||
1105 | /* determine the input source type and name */ | 1108 | /* determine the input source type and name */ |
1106 | if (check_input_term(state, ftr[4], &iterm) < 0) | 1109 | if (check_input_term(state, ftr->bSourceID, &iterm) < 0) |
1107 | return -EINVAL; | 1110 | return -EINVAL; |
1108 | 1111 | ||
1109 | channels = (ftr[0] - 7) / csize - 1; | 1112 | channels = (ftr->bLength - 7) / csize - 1; |
1110 | 1113 | ||
1111 | master_bits = snd_usb_combine_bytes(ftr + 6, csize); | 1114 | master_bits = snd_usb_combine_bytes(ftr->controls, csize); |
1112 | /* master configuration quirks */ | 1115 | /* master configuration quirks */ |
1113 | switch (state->chip->usb_id) { | 1116 | switch (state->chip->usb_id) { |
1114 | case USB_ID(0x08bb, 0x2702): | 1117 | case USB_ID(0x08bb, 0x2702): |
@@ -1119,21 +1122,21 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsig | |||
1119 | break; | 1122 | break; |
1120 | } | 1123 | } |
1121 | if (channels > 0) | 1124 | if (channels > 0) |
1122 | first_ch_bits = snd_usb_combine_bytes(ftr + 6 + csize, csize); | 1125 | first_ch_bits = snd_usb_combine_bytes(ftr->controls + csize, csize); |
1123 | else | 1126 | else |
1124 | first_ch_bits = 0; | 1127 | first_ch_bits = 0; |
1125 | /* check all control types */ | 1128 | /* check all control types */ |
1126 | for (i = 0; i < 10; i++) { | 1129 | for (i = 0; i < 10; i++) { |
1127 | unsigned int ch_bits = 0; | 1130 | unsigned int ch_bits = 0; |
1128 | for (j = 0; j < channels; j++) { | 1131 | for (j = 0; j < channels; j++) { |
1129 | 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); |
1130 | if (mask & (1 << i)) | 1133 | if (mask & (1 << i)) |
1131 | ch_bits |= (1 << j); | 1134 | ch_bits |= (1 << j); |
1132 | } | 1135 | } |
1133 | 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) */ |
1134 | build_feature_ctl(state, ftr, ch_bits, i, &iterm, unitid); | 1137 | build_feature_ctl(state, _ftr, ch_bits, i, &iterm, unitid); |
1135 | if (master_bits & (1 << i)) | 1138 | if (master_bits & (1 << i)) |
1136 | build_feature_ctl(state, ftr, 0, i, &iterm, unitid); | 1139 | build_feature_ctl(state, _ftr, 0, i, &iterm, unitid); |
1137 | } | 1140 | } |
1138 | 1141 | ||
1139 | return 0; | 1142 | return 0; |
@@ -1780,7 +1783,7 @@ static int snd_usb_mixer_dev_free(struct snd_device *device) | |||
1780 | */ | 1783 | */ |
1781 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | 1784 | static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) |
1782 | { | 1785 | { |
1783 | unsigned char *desc; | 1786 | struct uac_output_terminal_descriptor_v1 *desc; |
1784 | struct mixer_build state; | 1787 | struct mixer_build state; |
1785 | int err; | 1788 | int err; |
1786 | const struct usbmix_ctl_map *map; | 1789 | const struct usbmix_ctl_map *map; |
@@ -1805,13 +1808,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) | |||
1805 | 1808 | ||
1806 | desc = NULL; | 1809 | desc = NULL; |
1807 | 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, OUTPUT_TERMINAL)) != NULL) { |
1808 | if (desc[0] < 9) | 1811 | if (desc->bLength < 9) |
1809 | continue; /* invalid descriptor? */ | 1812 | continue; /* invalid descriptor? */ |
1810 | set_bit(desc[3], state.unitbitmap); /* mark terminal ID as visited */ | 1813 | set_bit(desc->bTerminalID, state.unitbitmap); /* mark terminal ID as visited */ |
1811 | state.oterm.id = desc[3]; | 1814 | state.oterm.id = desc->bTerminalID; |
1812 | state.oterm.type = combine_word(&desc[4]); | 1815 | state.oterm.type = le16_to_cpu(desc->wTerminalType); |
1813 | state.oterm.name = desc[8]; | 1816 | state.oterm.name = desc->iTerminal; |
1814 | err = parse_audio_unit(&state, desc[7]); | 1817 | err = parse_audio_unit(&state, desc->bSourceID); |
1815 | if (err < 0) | 1818 | if (err < 0) |
1816 | return err; | 1819 | return err; |
1817 | } | 1820 | } |