ALSA: usb-audio: add support for many Roland/Yamaha devices

Add quirks to detect the various vendor-specific descriptors used by
Roland and Yamaha in most of their recent USB audio and MIDI devices.

Together with the previous patch, this should add audio/MIDI support for
the following USB devices:
- Edirol motion dive .tokyo performance package
- Roland MC-808 Synthesizer
- Roland BK-7m Synthesizer
- Roland VIMA JM-5/8 Synthesizer
- Roland SP-555 Sequencer
- Roland V-Synth GT Synthesizer
- Roland Music Atelier AT-75/100/300/350C/500/800/900/900C Organ
- Edirol V-Mixer M-200i/300/380/400/480/R-1000
- BOSS GT-10B Effects Processor
- Roland Fantom G6/G7/G8 Keyboard
- Cakewalk Sonar V-Studio 20/100/700 Audio Interface
- Roland GW-8 Keyboard
- Roland AX-Synth Keyboard
- Roland JUNO-Di/STAGE/Gi Keyboard
- Roland VB-99 Effects Processor
- Cakewalk UM-2G MIDI Interface
- Roland A-500S Keyboard
- Roland SD-50 Synthesizer
- Roland OCTAPAD SPD-30 Controller
- Roland Lucina AX-09 Synthesizer
- BOSS BR-800 Digital Recorder
- Roland DUO/TRI-CAPTURE (EX) Audio Interface
- BOSS RC-300 Loop Station
- Roland JUPITER-50/80 Keyboard
- Roland R-26 Recorder
- Roland SPD-SX Controller
- BOSS JS-10 Audio Player
- Roland TD-11/15/30 Drum Module
- Roland A-49/88 Keyboard
- Roland INTEGRA-7 Synthesizer
- Roland R-88 Recorder

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 8e01fa4..63dd054 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1948,6 +1948,44 @@
 }
 
 /*
+ * 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.
  */
 static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
@@ -2162,6 +2200,9 @@
 	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,