diff options
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r-- | sound/usb/stream.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 67cf849aa16b..d9e3de495c16 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c | |||
@@ -596,12 +596,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
596 | csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT); | 596 | csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT); |
597 | 597 | ||
598 | if (!csep || csep->bLength < 7 || | 598 | if (!csep || csep->bLength < 7 || |
599 | csep->bDescriptorSubtype != UAC_EP_GENERAL) { | 599 | csep->bDescriptorSubtype != UAC_EP_GENERAL) |
600 | usb_audio_warn(chip, | 600 | goto error; |
601 | "%u:%d : no or invalid class specific endpoint descriptor\n", | ||
602 | iface_no, altsd->bAlternateSetting); | ||
603 | return 0; | ||
604 | } | ||
605 | 601 | ||
606 | if (protocol == UAC_VERSION_1) { | 602 | if (protocol == UAC_VERSION_1) { |
607 | attributes = csep->bmAttributes; | 603 | attributes = csep->bmAttributes; |
@@ -609,6 +605,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
609 | struct uac2_iso_endpoint_descriptor *csep2 = | 605 | struct uac2_iso_endpoint_descriptor *csep2 = |
610 | (struct uac2_iso_endpoint_descriptor *) csep; | 606 | (struct uac2_iso_endpoint_descriptor *) csep; |
611 | 607 | ||
608 | if (csep2->bLength < sizeof(*csep2)) | ||
609 | goto error; | ||
612 | attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; | 610 | attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX; |
613 | 611 | ||
614 | /* emulate the endpoint attributes of a v1 device */ | 612 | /* emulate the endpoint attributes of a v1 device */ |
@@ -618,12 +616,20 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
618 | struct uac3_iso_endpoint_descriptor *csep3 = | 616 | struct uac3_iso_endpoint_descriptor *csep3 = |
619 | (struct uac3_iso_endpoint_descriptor *) csep; | 617 | (struct uac3_iso_endpoint_descriptor *) csep; |
620 | 618 | ||
619 | if (csep3->bLength < sizeof(*csep3)) | ||
620 | goto error; | ||
621 | /* emulate the endpoint attributes of a v1 device */ | 621 | /* emulate the endpoint attributes of a v1 device */ |
622 | if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH) | 622 | if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH) |
623 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; | 623 | attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL; |
624 | } | 624 | } |
625 | 625 | ||
626 | return attributes; | 626 | return attributes; |
627 | |||
628 | error: | ||
629 | usb_audio_warn(chip, | ||
630 | "%u:%d : no or invalid class specific endpoint descriptor\n", | ||
631 | iface_no, altsd->bAlternateSetting); | ||
632 | return 0; | ||
627 | } | 633 | } |
628 | 634 | ||
629 | /* find an input terminal descriptor (either UAC1 or UAC2) with the given | 635 | /* find an input terminal descriptor (either UAC1 or UAC2) with the given |
@@ -631,13 +637,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, | |||
631 | */ | 637 | */ |
632 | static void * | 638 | static void * |
633 | snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, | 639 | snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, |
634 | int terminal_id) | 640 | int terminal_id, bool uac23) |
635 | { | 641 | { |
636 | struct uac2_input_terminal_descriptor *term = NULL; | 642 | struct uac2_input_terminal_descriptor *term = NULL; |
643 | size_t minlen = uac23 ? sizeof(struct uac2_input_terminal_descriptor) : | ||
644 | sizeof(struct uac_input_terminal_descriptor); | ||
637 | 645 | ||
638 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | 646 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, |
639 | ctrl_iface->extralen, | 647 | ctrl_iface->extralen, |
640 | term, UAC_INPUT_TERMINAL))) { | 648 | term, UAC_INPUT_TERMINAL))) { |
649 | if (term->bLength < minlen) | ||
650 | continue; | ||
641 | if (term->bTerminalID == terminal_id) | 651 | if (term->bTerminalID == terminal_id) |
642 | return term; | 652 | return term; |
643 | } | 653 | } |
@@ -655,7 +665,8 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface, | |||
655 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, | 665 | while ((term = snd_usb_find_csint_desc(ctrl_iface->extra, |
656 | ctrl_iface->extralen, | 666 | ctrl_iface->extralen, |
657 | term, UAC_OUTPUT_TERMINAL))) { | 667 | term, UAC_OUTPUT_TERMINAL))) { |
658 | if (term->bTerminalID == terminal_id) | 668 | if (term->bLength >= sizeof(*term) && |
669 | term->bTerminalID == terminal_id) | ||
659 | return term; | 670 | return term; |
660 | } | 671 | } |
661 | 672 | ||
@@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, | |||
729 | format = le16_to_cpu(as->wFormatTag); /* remember the format value */ | 740 | format = le16_to_cpu(as->wFormatTag); /* remember the format value */ |
730 | 741 | ||
731 | iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, | 742 | iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, |
732 | as->bTerminalLink); | 743 | as->bTerminalLink, |
744 | false); | ||
733 | if (iterm) { | 745 | if (iterm) { |
734 | num_channels = iterm->bNrChannels; | 746 | num_channels = iterm->bNrChannels; |
735 | chconfig = le16_to_cpu(iterm->wChannelConfig); | 747 | chconfig = le16_to_cpu(iterm->wChannelConfig); |
@@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, | |||
764 | * to extract the clock | 776 | * to extract the clock |
765 | */ | 777 | */ |
766 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, | 778 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, |
767 | as->bTerminalLink); | 779 | as->bTerminalLink, |
780 | true); | ||
768 | if (input_term) { | 781 | if (input_term) { |
769 | clock = input_term->bCSourceID; | 782 | clock = input_term->bCSourceID; |
770 | if (!chconfig && (num_channels == input_term->bNrChannels)) | 783 | if (!chconfig && (num_channels == input_term->bNrChannels)) |
@@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, | |||
998 | * to extract the clock | 1011 | * to extract the clock |
999 | */ | 1012 | */ |
1000 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, | 1013 | input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf, |
1001 | as->bTerminalLink); | 1014 | as->bTerminalLink, |
1015 | true); | ||
1002 | if (input_term) { | 1016 | if (input_term) { |
1003 | clock = input_term->bCSourceID; | 1017 | clock = input_term->bCSourceID; |
1004 | goto found_clock; | 1018 | goto found_clock; |