aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/usb/midi.c41
-rw-r--r--sound/usb/quirks-table.h22
-rw-r--r--sound/usb/quirks.c175
-rw-r--r--sound/usb/stream.c15
-rw-r--r--sound/usb/usbaudio.h2
5 files changed, 252 insertions, 3 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 8e01fa4991c5..63dd0545a672 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1948,6 +1948,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
1948} 1948}
1949 1949
1950/* 1950/*
1951 * Detects the endpoints and ports of Roland devices.
1952 */
1953static int snd_usbmidi_detect_roland(struct snd_usb_midi* umidi,
1954 struct snd_usb_midi_endpoint_info* endpoint)
1955{
1956 struct usb_interface* intf;
1957 struct usb_host_interface *hostif;
1958 u8* cs_desc;
1959
1960 intf = umidi->iface;
1961 if (!intf)
1962 return -ENOENT;
1963 hostif = intf->altsetting;
1964 /*
1965 * Some devices have a descriptor <06 24 F1 02 <inputs> <outputs>>,
1966 * some have standard class descriptors, or both kinds, or neither.
1967 */
1968 for (cs_desc = hostif->extra;
1969 cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
1970 cs_desc += cs_desc[0]) {
1971 if (cs_desc[0] >= 6 &&
1972 cs_desc[1] == USB_DT_CS_INTERFACE &&
1973 cs_desc[2] == 0xf1 &&
1974 cs_desc[3] == 0x02) {
1975 endpoint->in_cables = (1 << cs_desc[4]) - 1;
1976 endpoint->out_cables = (1 << cs_desc[5]) - 1;
1977 return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
1978 } else if (cs_desc[0] >= 7 &&
1979 cs_desc[1] == USB_DT_CS_INTERFACE &&
1980 cs_desc[2] == UAC_HEADER) {
1981 return snd_usbmidi_get_ms_info(umidi, endpoint);
1982 }
1983 }
1984
1985 return -ENODEV;
1986}
1987
1988/*
1951 * Creates the endpoints and their ports for Midiman devices. 1989 * Creates the endpoints and their ports for Midiman devices.
1952 */ 1990 */
1953static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, 1991static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
@@ -2162,6 +2200,9 @@ int snd_usbmidi_create(struct snd_card *card,
2162 case QUIRK_MIDI_YAMAHA: 2200 case QUIRK_MIDI_YAMAHA:
2163 err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); 2201 err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
2164 break; 2202 break;
2203 case QUIRK_MIDI_ROLAND:
2204 err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
2205 break;
2165 case QUIRK_MIDI_MIDIMAN: 2206 case QUIRK_MIDI_MIDIMAN:
2166 umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; 2207 umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
2167 memcpy(&endpoints[0], quirk->data, 2208 memcpy(&endpoints[0], quirk->data,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 7f1722f82c89..b47517d47b08 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -455,6 +455,17 @@ YAMAHA_DEVICE(0x7000, "DTX"),
455YAMAHA_DEVICE(0x7010, "UB99"), 455YAMAHA_DEVICE(0x7010, "UB99"),
456#undef YAMAHA_DEVICE 456#undef YAMAHA_DEVICE
457#undef YAMAHA_INTERFACE 457#undef YAMAHA_INTERFACE
458/* this catches most recent vendor-specific Yamaha devices */
459{
460 .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
461 USB_DEVICE_ID_MATCH_INT_CLASS,
462 .idVendor = 0x0499,
463 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
464 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
465 .ifnum = QUIRK_ANY_INTERFACE,
466 .type = QUIRK_AUTODETECT
467 }
468},
458 469
459/* 470/*
460 * Roland/RolandED/Edirol/BOSS devices 471 * Roland/RolandED/Edirol/BOSS devices
@@ -2031,6 +2042,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2031 } 2042 }
2032 } 2043 }
2033}, 2044},
2045/* this catches most recent vendor-specific Roland devices */
2046{
2047 .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
2048 USB_DEVICE_ID_MATCH_INT_CLASS,
2049 .idVendor = 0x0582,
2050 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
2051 .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
2052 .ifnum = QUIRK_ANY_INTERFACE,
2053 .type = QUIRK_AUTODETECT
2054 }
2055},
2034 2056
2035/* Guillemot devices */ 2057/* Guillemot devices */
2036{ 2058{
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 3879eae7e874..5363bcca9494 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/usb.h> 19#include <linux/usb.h>
20#include <linux/usb/audio.h> 20#include <linux/usb/audio.h>
21#include <linux/usb/midi.h>
21 22
22#include <sound/control.h> 23#include <sound/control.h>
23#include <sound/core.h> 24#include <sound/core.h>
@@ -175,6 +176,178 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
175 return 0; 176 return 0;
176} 177}
177 178
179static int create_auto_pcm_quirk(struct snd_usb_audio *chip,
180 struct usb_interface *iface,
181 struct usb_driver *driver)
182{
183 struct usb_host_interface *alts;
184 struct usb_interface_descriptor *altsd;
185 struct usb_endpoint_descriptor *epd;
186 struct uac1_as_header_descriptor *ashd;
187 struct uac_format_type_i_discrete_descriptor *fmtd;
188
189 /*
190 * Most Roland/Yamaha audio streaming interfaces have more or less
191 * standard descriptors, but older devices might lack descriptors, and
192 * future ones might change, so ensure that we fail silently if the
193 * interface doesn't look exactly right.
194 */
195
196 /* must have a non-zero altsetting for streaming */
197 if (iface->num_altsetting < 2)
198 return -ENODEV;
199 alts = &iface->altsetting[1];
200 altsd = get_iface_desc(alts);
201
202 /* must have an isochronous endpoint for streaming */
203 if (altsd->bNumEndpoints < 1)
204 return -ENODEV;
205 epd = get_endpoint(alts, 0);
206 if (!usb_endpoint_xfer_isoc(epd))
207 return -ENODEV;
208
209 /* must have format descriptors */
210 ashd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
211 UAC_AS_GENERAL);
212 fmtd = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL,
213 UAC_FORMAT_TYPE);
214 if (!ashd || ashd->bLength < 7 ||
215 !fmtd || fmtd->bLength < 8)
216 return -ENODEV;
217
218 return create_standard_audio_quirk(chip, iface, driver, NULL);
219}
220
221static int create_yamaha_midi_quirk(struct snd_usb_audio *chip,
222 struct usb_interface *iface,
223 struct usb_driver *driver,
224 struct usb_host_interface *alts)
225{
226 static const struct snd_usb_audio_quirk yamaha_midi_quirk = {
227 .type = QUIRK_MIDI_YAMAHA
228 };
229 struct usb_midi_in_jack_descriptor *injd;
230 struct usb_midi_out_jack_descriptor *outjd;
231
232 /* must have some valid jack descriptors */
233 injd = snd_usb_find_csint_desc(alts->extra, alts->extralen,
234 NULL, USB_MS_MIDI_IN_JACK);
235 outjd = snd_usb_find_csint_desc(alts->extra, alts->extralen,
236 NULL, USB_MS_MIDI_OUT_JACK);
237 if (!injd && !outjd)
238 return -ENODEV;
239 if (injd && (injd->bLength < 5 ||
240 (injd->bJackType != USB_MS_EMBEDDED &&
241 injd->bJackType != USB_MS_EXTERNAL)))
242 return -ENODEV;
243 if (outjd && (outjd->bLength < 6 ||
244 (outjd->bJackType != USB_MS_EMBEDDED &&
245 outjd->bJackType != USB_MS_EXTERNAL)))
246 return -ENODEV;
247 return create_any_midi_quirk(chip, iface, driver, &yamaha_midi_quirk);
248}
249
250static int create_roland_midi_quirk(struct snd_usb_audio *chip,
251 struct usb_interface *iface,
252 struct usb_driver *driver,
253 struct usb_host_interface *alts)
254{
255 static const struct snd_usb_audio_quirk roland_midi_quirk = {