aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/stream.c')
-rw-r--r--sound/usb/stream.c36
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 */
632static void * 638static void *
633snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface, 639snd_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;