return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
 }
 
+/*
+ * Detects the endpoints and ports of Roland devices.
+ */
+static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
+                                    struct snd_usb_midi_endpoint_info* endpoint)
+{
+       struct usb_interface* intf;
+       struct usb_host_interface *hostif;
+       u8* cs_desc;
+
+       intf = umidi->iface;
+       if (!intf)
+               return -ENOENT;
+       hostif = intf->altsetting;
+       /*
+        * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>,
+        * some have standard class descriptors, or both kinds, or neither.
+        */
+       for (cs_desc = hostif->extra;
+            cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
+            cs_desc += cs_desc[0]) {
+               if (cs_desc[0] >= 6 &&
+                   cs_desc[1] == USB_DT_CS_INTERFACE &&
+                   cs_desc[2] == 0xf1 &&
+                   cs_desc[3] == 0x02) {
+                       endpoint->in_cables  = (1 << cs_desc[4]) - 1;
+                       endpoint->out_cables = (1 << cs_desc[5]) - 1;
+                       return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
+               } else if (cs_desc[0] >= 7 &&
+                          cs_desc[1] == USB_DT_CS_INTERFACE &&
+                          cs_desc[2] == UAC_HEADER) {
+                       return snd_usbmidi_get_ms_info(umidi, endpoint);
+               }
+       }
+
+       return -ENODEV;
+}
+
 /*
  * Creates the endpoints and their ports for Midiman devices.
  */
        case QUIRK_MIDI_YAMAHA:
                err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
                break;
+       case QUIRK_MIDI_ROLAND:
+               err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
+               break;
        case QUIRK_MIDI_MIDIMAN:
                umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
                memcpy(&endpoints[0], quirk->data,
 
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/audio.h>
+#include <linux/usb/midi.h>
 
 #include <sound/control.h>
 #include <sound/core.h>
        return 0;
 }
 
+static int create_auto_pcm_quirk(struct snd_usb_audio *chip,
+                                struct usb_interface *iface,
+                                struct usb_driver *driver)
+{
+       struct usb_host_interface *alts;
+       struct usb_interface_descriptor *altsd;
+       struct usb_endpoint_descriptor *epd;
+       struct uac1_as_header_descriptor *ashd;
+       struct uac_format_type_i_discrete_descriptor *fmtd;
+
+       /*
+        * Most Roland/Yamaha audio streaming interfaces have more or less
+        * standard descriptors, but older devices might lack descriptors, and
+        * future ones might change, so ensure that we fail silently if the
+        * interface doesn't look exactly right.
+        */
+
+       /* must have a non-zero altsetting for streaming */
+       if (iface->num_altsetting < 2)
+               return -ENODEV;
+       alts = &iface->altsetting[1];
+       altsd = get_iface_desc(alts);
+
+       /* must have an isochronous endpoint for streaming */
+       if (altsd->bNumEndpoints < 1)
+               return -ENODEV;
+       epd = get_endpoint(alts, 0);
+       if (!usb_endpoint_xfer_isoc(epd))
+               return -ENODEV;
+
+       /* must have format descriptors */
+       ashd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
+                                      UAC_AS_GENERAL);
+       fmtd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
+                                      UAC_FORMAT_TYPE);
+       if (!ashd || ashd->bLength < 7 ||
+           !fmtd || fmtd->bLength < 8)
+               return -ENODEV;
+
+       return create_standard_audio_quirk(chip, iface, driver, NULL);
+}
+
+static int create_yamaha_midi_quirk(struct snd_usb_audio *chip,
+                                   struct usb_interface *iface,
+                                   struct usb_driver *driver,
+                                   struct usb_host_interface *alts)
+{
+       static const struct snd_usb_audio_quirk yamaha_midi_quirk = {
+               .type = QUIRK_MIDI_YAMAHA
+       };
+       struct usb_midi_in_jack_descriptor *injd;
+       struct usb_midi_out_jack_descriptor *outjd;
+
+       /* must have some valid jack descriptors */
+       injd = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+                                      NULL, USB_MS_MIDI_IN_JACK);
+       outjd = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+                                       NULL, USB_MS_MIDI_OUT_JACK);
+       if (!injd && !outjd)
+               return -ENODEV;
+       if (injd && (injd->bLength < 5 ||
+                    (injd->bJackType != USB_MS_EMBEDDED &&
+                     injd->bJackType != USB_MS_EXTERNAL)))
+               return -ENODEV;
+       if (outjd && (outjd->bLength < 6 ||
+                     (outjd->bJackType != USB_MS_EMBEDDED &&
+                      outjd->bJackType != USB_MS_EXTERNAL)))
+               return -ENODEV;
+       return create_any_midi_quirk(chip, iface, driver, &yamaha_midi_quirk);
+}
+
+static int create_roland_midi_quirk(struct snd_usb_audio *chip,
+                                   struct usb_interface *iface,
+                                   struct usb_driver *driver,
+                                   struct usb_host_interface *alts)
+{
+       static const struct snd_usb_audio_quirk roland_midi_quirk = {
+               .type = QUIRK_MIDI_ROLAND
+       };
+       u8 *roland_desc = NULL;
+
+       /* might have a vendor-specific descriptor <06 24 F1 02 ...> */
+       for (;;) {
+               roland_desc = snd_usb_find_csint_desc(alts->extra,
+                                                     alts->extralen,
+                                                     roland_desc, 0xf1);
+               if (!roland_desc)
+                       return -ENODEV;
+               if (roland_desc[0] < 6 || roland_desc[3] != 2)
+                       continue;
+               return create_any_midi_quirk(chip, iface, driver,
+                                            &roland_midi_quirk);
+       }
+}
+
+static int create_std_midi_quirk(struct snd_usb_audio *chip,
+                                struct usb_interface *iface,
+                                struct usb_driver *driver,
+                                struct usb_host_interface *alts)
+{
+       struct usb_ms_header_descriptor *mshd;
+       struct usb_ms_endpoint_descriptor *msepd;
+
+       /* must have the MIDIStreaming interface header descriptor*/
+       mshd = (struct usb_ms_header_descriptor *)alts->extra;
+       if (alts->extralen < 7 ||
+           mshd->bLength < 7 ||
+           mshd->bDescriptorType != USB_DT_CS_INTERFACE ||
+           mshd->bDescriptorSubtype != USB_MS_HEADER)
+               return -ENODEV;
+       /* must have the MIDIStreaming endpoint descriptor*/
+       msepd = (struct usb_ms_endpoint_descriptor *)alts->endpoint[0].extra;
+       if (alts->endpoint[0].extralen < 4 ||
+           msepd->bLength < 4 ||
+           msepd->bDescriptorType != USB_DT_CS_ENDPOINT ||
+           msepd->bDescriptorSubtype != UAC_MS_GENERAL ||
+           msepd->bNumEmbMIDIJack < 1 ||
+           msepd->bNumEmbMIDIJack > 16)
+               return -ENODEV;
+
+       return create_any_midi_quirk(chip, iface, driver, NULL);
+}
+
+static int create_auto_midi_quirk(struct snd_usb_audio *chip,
+                                 struct usb_interface *iface,
+                                 struct usb_driver *driver)
+{
+       struct usb_host_interface *alts;
+       struct usb_interface_descriptor *altsd;
+       struct usb_endpoint_descriptor *epd;
+       int err;
+
+       alts = &iface->altsetting[0];
+       altsd = get_iface_desc(alts);
+
+       /* must have at least one bulk/interrupt endpoint for streaming */
+       if (altsd->bNumEndpoints < 1)
+               return -ENODEV;
+       epd = get_endpoint(alts, 0);
+       if (!usb_endpoint_xfer_bulk(epd) ||
+           !usb_endpoint_xfer_int(epd))
+               return -ENODEV;
+
+       switch (USB_ID_VENDOR(chip->usb_id)) {
+       case 0x0499: /* Yamaha */
+               err = create_yamaha_midi_quirk(chip, iface, driver, alts);
+               if (err < 0 && err != -ENODEV)
+                       return err;
+               break;
+       case 0x0582: /* Roland */
+               err = create_roland_midi_quirk(chip, iface, driver, alts);
+               if (err < 0 && err != -ENODEV)
+                       return err;
+               break;
+       }
+
+       return create_std_midi_quirk(chip, iface, driver, alts);
+}
+
+static int create_autodetect_quirk(struct snd_usb_audio *chip,
+                                  struct usb_interface *iface,
+                                  struct usb_driver *driver,
+                                  const struct snd_usb_audio_quirk *quirk)
+{
+       int err;
+
+       err = create_auto_pcm_quirk(chip, iface, driver);
+       if (err == -ENODEV)
+               err = create_auto_midi_quirk(chip, iface, driver);
+       return err;
+}
+
 /*
  * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface.  
  * The only way to detect the sample rate is by looking at wMaxPacketSize.
        static const quirk_func_t quirk_funcs[] = {
                [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
                [QUIRK_COMPOSITE] = create_composite_quirk,
+               [QUIRK_AUTODETECT] = create_autodetect_quirk,
                [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
                [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
                [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
+               [QUIRK_MIDI_ROLAND] = create_any_midi_quirk,
                [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
                [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
                [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,