Skip to content

Commit aafe77c

Browse files
committed
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 <[email protected]>
1 parent ba7c2be commit aafe77c

File tree

5 files changed

+252
-3
lines changed

5 files changed

+252
-3
lines changed

sound/usb/midi.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
19471947
return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
19481948
}
19491949

1950+
/*
1951+
* Detects the endpoints and ports of Roland devices.
1952+
*/
1953+
static 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+
19501988
/*
19511989
* Creates the endpoints and their ports for Midiman devices.
19521990
*/
@@ -2162,6 +2200,9 @@ int snd_usbmidi_create(struct snd_card *card,
21622200
case QUIRK_MIDI_YAMAHA:
21632201
err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
21642202
break;
2203+
case QUIRK_MIDI_ROLAND:
2204+
err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
2205+
break;
21652206
case QUIRK_MIDI_MIDIMAN:
21662207
umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
21672208
memcpy(&endpoints[0], quirk->data,

sound/usb/quirks-table.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,17 @@ YAMAHA_DEVICE(0x7000, "DTX"),
455455
YAMAHA_DEVICE(0x7010, "UB99"),
456456
#undef YAMAHA_DEVICE
457457
#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+
},
458469

459470
/*
460471
* Roland/RolandED/Edirol/BOSS devices
@@ -2031,6 +2042,17 @@ YAMAHA_DEVICE(0x7010, "UB99"),
20312042
}
20322043
}
20332044
},
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+
},
20342056

20352057
/* Guillemot devices */
20362058
{

sound/usb/quirks.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/slab.h>
1919
#include <linux/usb.h>
2020
#include <linux/usb/audio.h>
21+
#include <linux/usb/midi.h>
2122

2223
#include <sound/control.h>
2324
#include <sound/core.h>
@@ -175,6 +176,178 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
175176
return 0;
176177
}
177178

179+
static 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+
221+
static 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+
250+
static 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 = {
256+
.type = QUIRK_MIDI_ROLAND
257+
};
258+
u8 *roland_desc = NULL;
259+
260+
/* might have a vendor-specific descriptor <06 24 F1 02 ...> */
261+
for (;;) {
262+
roland_desc = snd_usb_find_csint_desc(alts->extra,
263+
alts->extralen,
264+
roland_desc, 0xf1);
265+
if (!roland_desc)
266+
return -ENODEV;
267+
if (roland_desc[0] < 6 || roland_desc[3] != 2)
268+
continue;
269+
return create_any_midi_quirk(chip, iface, driver,
270+
&roland_midi_quirk);
271+
}
272+
}
273+
274+
static int create_std_midi_quirk(struct snd_usb_audio *chip,
275+
struct usb_interface *iface,
276+
struct usb_driver *driver,
277+
struct usb_host_interface *alts)
278+
{
279+
struct usb_ms_header_descriptor *mshd;
280+
struct usb_ms_endpoint_descriptor *msepd;
281+
282+
/* must have the MIDIStreaming interface header descriptor*/
283+
mshd = (struct usb_ms_header_descriptor *)alts->extra;
284+
if (alts->extralen < 7 ||
285+
mshd->bLength < 7 ||
286+
mshd->bDescriptorType != USB_DT_CS_INTERFACE ||
287+
mshd->bDescriptorSubtype != USB_MS_HEADER)
288+
return -ENODEV;
289+
/* must have the MIDIStreaming endpoint descriptor*/
290+
msepd = (struct usb_ms_endpoint_descriptor *)alts->endpoint[0].extra;
291+
if (alts->endpoint[0].extralen < 4 ||
292+
msepd->bLength < 4 ||
293+
msepd->bDescriptorType != USB_DT_CS_ENDPOINT ||
294+
msepd->bDescriptorSubtype != UAC_MS_GENERAL ||
295+
msepd->bNumEmbMIDIJack < 1 ||
296+
msepd->bNumEmbMIDIJack > 16)
297+
return -ENODEV;
298+
299+
return create_any_midi_quirk(chip, iface, driver, NULL);
300+
}
301+
302+
static int create_auto_midi_quirk(struct snd_usb_audio *chip,
303+
struct usb_interface *iface,
304+
struct usb_driver *driver)
305+
{
306+
struct usb_host_interface *alts;
307+
struct usb_interface_descriptor *altsd;
308+
struct usb_endpoint_descriptor *epd;
309+
int err;
310+
311+
alts = &iface->altsetting[0];
312+
altsd = get_iface_desc(alts);
313+
314+
/* must have at least one bulk/interrupt endpoint for streaming */
315+
if (altsd->bNumEndpoints < 1)
316+
return -ENODEV;
317+
epd = get_endpoint(alts, 0);
318+
if (!usb_endpoint_xfer_bulk(epd) ||
319+
!usb_endpoint_xfer_int(epd))
320+
return -ENODEV;
321+
322+
switch (USB_ID_VENDOR(chip->usb_id)) {
323+
case 0x0499: /* Yamaha */
324+
err = create_yamaha_midi_quirk(chip, iface, driver, alts);
325+
if (err < 0 && err != -ENODEV)
326+
return err;
327+
break;
328+
case 0x0582: /* Roland */
329+
err = create_roland_midi_quirk(chip, iface, driver, alts);
330+
if (err < 0 && err != -ENODEV)
331+
return err;
332+
break;
333+
}
334+
335+
return create_std_midi_quirk(chip, iface, driver, alts);
336+
}
337+
338+
static int create_autodetect_quirk(struct snd_usb_audio *chip,
339+
struct usb_interface *iface,
340+
struct usb_driver *driver,
341+
const struct snd_usb_audio_quirk *quirk)
342+
{
343+
int err;
344+
345+
err = create_auto_pcm_quirk(chip, iface, driver);
346+
if (err == -ENODEV)
347+
err = create_auto_midi_quirk(chip, iface, driver);
348+
return err;
349+
}
350+
178351
/*
179352
* Create a stream for an Edirol UA-700/UA-25/UA-4FX interface.
180353
* The only way to detect the sample rate is by looking at wMaxPacketSize.
@@ -303,9 +476,11 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
303476
static const quirk_func_t quirk_funcs[] = {
304477
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
305478
[QUIRK_COMPOSITE] = create_composite_quirk,
479+
[QUIRK_AUTODETECT] = create_autodetect_quirk,
306480
[QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
307481
[QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
308482
[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
483+
[QUIRK_MIDI_ROLAND] = create_any_midi_quirk,
309484
[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
310485
[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
311486
[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,

sound/usb/stream.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,10 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
493493
altsd = get_iface_desc(alts);
494494
protocol = altsd->bInterfaceProtocol;
495495
/* skip invalid one */
496-
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
496+
if (((altsd->bInterfaceClass != USB_CLASS_AUDIO ||
497+
(altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
498+
altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) &&
497499
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
498-
(altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
499-
altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
500500
altsd->bNumEndpoints < 1 ||
501501
le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
502502
continue;
@@ -512,6 +512,15 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
512512
if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
513513
continue;
514514

515+
/*
516+
* Roland audio streaming interfaces are marked with protocols
517+
* 0/1/2, but are UAC 1 compatible.
518+
*/
519+
if (USB_ID_VENDOR(chip->usb_id) == 0x0582 &&
520+
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
521+
protocol <= 2)
522+
protocol = UAC_VERSION_1;
523+
515524
chconfig = 0;
516525
/* get audio formats */
517526
switch (protocol) {

sound/usb/usbaudio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,11 @@ struct snd_usb_audio {
7272
enum quirk_type {
7373
QUIRK_IGNORE_INTERFACE,
7474
QUIRK_COMPOSITE,
75+
QUIRK_AUTODETECT,
7576
QUIRK_MIDI_STANDARD_INTERFACE,
7677
QUIRK_MIDI_FIXED_ENDPOINT,
7778
QUIRK_MIDI_YAMAHA,
79+
QUIRK_MIDI_ROLAND,
7880
QUIRK_MIDI_MIDIMAN,
7981
QUIRK_MIDI_NOVATION,
8082
QUIRK_MIDI_RAW_BYTES,

0 commit comments

Comments
 (0)