Commit ea70ee05 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'full-roland-support' of git://git.alsa-project.org/alsa-kprivate into for-next

For adding support for many Roland and Yamaha devices:
* 'full-roland-support' of git://git.alsa-project.org/alsa-kprivate:
  ALSA: usb-audio: add quirks for Roland QUAD/OCTO-CAPTURE
  ALSA: usb-audio: claim autodetected PCM interfaces all at once
  ALSA: usb-audio: remove superfluous Roland quirks
  ALSA: usb-audio: add MIDI port names for some Roland devices
  ALSA: usb-audio: add support for many Roland/Yamaha devices
  ALSA: usb-audio: detect implicit feedback on Roland devices
  ALSA: usb-audio: store protocol version in struct audioformat
parents ad60d502 b7f33917
...@@ -21,6 +21,7 @@ struct audioformat { ...@@ -21,6 +21,7 @@ struct audioformat {
unsigned char endpoint; /* endpoint */ unsigned char endpoint; /* endpoint */
unsigned char ep_attr; /* endpoint attributes */ unsigned char ep_attr; /* endpoint attributes */
unsigned char datainterval; /* log_2 of data packet interval */ unsigned char datainterval; /* log_2 of data packet interval */
unsigned char protocol; /* UAC_VERSION_1/2 */
unsigned int maxpacksize; /* max. packet size */ unsigned int maxpacksize; /* max. packet size */
unsigned int rates; /* rate bitmasks */ unsigned int rates; /* rate bitmasks */
unsigned int rate_min, rate_max; /* min/max rates */ unsigned int rate_min, rate_max; /* min/max rates */
......
...@@ -407,9 +407,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, ...@@ -407,9 +407,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts, struct usb_host_interface *alts,
struct audioformat *fmt, int rate) struct audioformat *fmt, int rate)
{ {
struct usb_interface_descriptor *altsd = get_iface_desc(alts); switch (fmt->protocol) {
switch (altsd->bInterfaceProtocol) {
case UAC_VERSION_1: case UAC_VERSION_1:
default: default:
return set_sample_rate_v1(chip, iface, alts, fmt, rate); return set_sample_rate_v1(chip, iface, alts, fmt, rate);
......
...@@ -43,13 +43,12 @@ ...@@ -43,13 +43,12 @@
*/ */
static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
struct audioformat *fp, struct audioformat *fp,
unsigned int format, void *_fmt, unsigned int format, void *_fmt)
int protocol)
{ {
int sample_width, sample_bytes; int sample_width, sample_bytes;
u64 pcm_formats = 0; u64 pcm_formats = 0;
switch (protocol) { switch (fp->protocol) {
case UAC_VERSION_1: case UAC_VERSION_1:
default: { default: {
struct uac_format_type_i_discrete_descriptor *fmt = _fmt; struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
...@@ -360,11 +359,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip, ...@@ -360,11 +359,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
*/ */
static int parse_audio_format_i(struct snd_usb_audio *chip, static int parse_audio_format_i(struct snd_usb_audio *chip,
struct audioformat *fp, unsigned int format, struct audioformat *fp, unsigned int format,
struct uac_format_type_i_continuous_descriptor *fmt, struct uac_format_type_i_continuous_descriptor *fmt)
struct usb_host_interface *iface)
{ {
struct usb_interface_descriptor *altsd = get_iface_desc(iface);
int protocol = altsd->bInterfaceProtocol;
snd_pcm_format_t pcm_format; snd_pcm_format_t pcm_format;
int ret; int ret;
...@@ -387,8 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, ...@@ -387,8 +383,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
} }
fp->formats = pcm_format_to_bits(pcm_format); fp->formats = pcm_format_to_bits(pcm_format);
} else { } else {
fp->formats = parse_audio_format_i_type(chip, fp, format, fp->formats = parse_audio_format_i_type(chip, fp, format, fmt);
fmt, protocol);
if (!fp->formats) if (!fp->formats)
return -EINVAL; return -EINVAL;
} }
...@@ -398,11 +393,8 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, ...@@ -398,11 +393,8 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
* proprietary class specific descriptor. * proprietary class specific descriptor.
* audio class v2 uses class specific EP0 range requests for that. * audio class v2 uses class specific EP0 range requests for that.
*/ */
switch (protocol) { switch (fp->protocol) {
default: default:
snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
chip->dev->devnum, fp->iface, fp->altsetting, protocol);
/* fall through */
case UAC_VERSION_1: case UAC_VERSION_1:
fp->channels = fmt->bNrChannels; fp->channels = fmt->bNrChannels;
ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7); ret = parse_audio_format_rates_v1(chip, fp, (unsigned char *) fmt, 7);
...@@ -427,12 +419,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, ...@@ -427,12 +419,9 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
*/ */
static int parse_audio_format_ii(struct snd_usb_audio *chip, static int parse_audio_format_ii(struct snd_usb_audio *chip,
struct audioformat *fp, struct audioformat *fp,
int format, void *_fmt, int format, void *_fmt)
struct usb_host_interface *iface)
{ {
int brate, framesize, ret; int brate, framesize, ret;
struct usb_interface_descriptor *altsd = get_iface_desc(iface);
int protocol = altsd->bInterfaceProtocol;
switch (format) { switch (format) {
case UAC_FORMAT_TYPE_II_AC3: case UAC_FORMAT_TYPE_II_AC3:
...@@ -452,11 +441,8 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, ...@@ -452,11 +441,8 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
fp->channels = 1; fp->channels = 1;
switch (protocol) { switch (fp->protocol) {
default: default:
snd_printdd(KERN_WARNING "%d:%u:%d : invalid protocol version %d, assuming v1\n",
chip->dev->devnum, fp->iface, fp->altsetting, protocol);
/* fall through */
case UAC_VERSION_1: { case UAC_VERSION_1: {
struct uac_format_type_ii_discrete_descriptor *fmt = _fmt; struct uac_format_type_ii_discrete_descriptor *fmt = _fmt;
brate = le16_to_cpu(fmt->wMaxBitRate); brate = le16_to_cpu(fmt->wMaxBitRate);
...@@ -483,17 +469,17 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip, ...@@ -483,17 +469,17 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
int snd_usb_parse_audio_format(struct snd_usb_audio *chip, int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
struct audioformat *fp, unsigned int format, struct audioformat *fp, unsigned int format,
struct uac_format_type_i_continuous_descriptor *fmt, struct uac_format_type_i_continuous_descriptor *fmt,
int stream, struct usb_host_interface *iface) int stream)
{ {
int err; int err;
switch (fmt->bFormatType) { switch (fmt->bFormatType) {
case UAC_FORMAT_TYPE_I: case UAC_FORMAT_TYPE_I:
case UAC_FORMAT_TYPE_III: case UAC_FORMAT_TYPE_III:
err = parse_audio_format_i(chip, fp, format, fmt, iface); err = parse_audio_format_i(chip, fp, format, fmt);
break; break;
case UAC_FORMAT_TYPE_II: case UAC_FORMAT_TYPE_II:
err = parse_audio_format_ii(chip, fp, format, fmt, iface); err = parse_audio_format_ii(chip, fp, format, fmt);
break; break;
default: default:
snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n", snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
int snd_usb_parse_audio_format(struct snd_usb_audio *chip, int snd_usb_parse_audio_format(struct snd_usb_audio *chip,
struct audioformat *fp, unsigned int format, struct audioformat *fp, unsigned int format,
struct uac_format_type_i_continuous_descriptor *fmt, struct uac_format_type_i_continuous_descriptor *fmt,
int stream, struct usb_host_interface *iface); int stream);
#endif /* __USBAUDIO_FORMAT_H */ #endif /* __USBAUDIO_FORMAT_H */
...@@ -1575,8 +1575,41 @@ static struct port_info { ...@@ -1575,8 +1575,41 @@ static struct port_info {
EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
/* BOSS GT-PRO */
CONTROL_PORT(0x0582, 0x0089, 0, "%s Control"),
/* Edirol UM-3EX */ /* Edirol UM-3EX */
CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
/* Roland VG-99 */
CONTROL_PORT(0x0582, 0x00b2, 0, "%s Control"),
EXTERNAL_PORT(0x0582, 0x00b2, 1, "%s MIDI"),
/* Cakewalk Sonar V-Studio 100 */
EXTERNAL_PORT(0x0582, 0x00eb, 0, "%s MIDI"),
CONTROL_PORT(0x0582, 0x00eb, 1, "%s Control"),
/* Roland VB-99 */
CONTROL_PORT(0x0582, 0x0102, 0, "%s Control"),
EXTERNAL_PORT(0x0582, 0x0102, 1, "%s MIDI"),
/* Roland A-PRO */
EXTERNAL_PORT(0x0582, 0x010f, 0, "%s MIDI"),
CONTROL_PORT(0x0582, 0x010f, 1, "%s 1"),
CONTROL_PORT(0x0582, 0x010f, 2, "%s 2"),
/* Roland SD-50 */
ROLAND_SYNTH_PORT(0x0582, 0x0114, 0, "%s Synth", 128),
EXTERNAL_PORT(0x0582, 0x0114, 1, "%s MIDI"),
CONTROL_PORT(0x0582, 0x0114, 2, "%s Control"),
/* Roland OCTA-CAPTURE */
EXTERNAL_PORT(0x0582, 0x0120, 0, "%s MIDI"),
CONTROL_PORT(0x0582, 0x0120, 1, "%s Control"),
EXTERNAL_PORT(0x0582, 0x0121, 0, "%s MIDI"),
CONTROL_PORT(0x0582, 0x0121, 1, "%s Control"),
/* Roland SPD-SX */
CONTROL_PORT(0x0582, 0x0145, 0, "%s Control"),
EXTERNAL_PORT(0x0582, 0x0145, 1, "%s MIDI"),
/* Roland A-Series */
CONTROL_PORT(0x0582, 0x0156, 0, "%s Keyboard"),
EXTERNAL_PORT(0x0582, 0x0156, 1, "%s MIDI"),
/* Roland INTEGRA-7 */
ROLAND_SYNTH_PORT(0x0582, 0x015b, 0, "%s Synth", 128),
CONTROL_PORT(0x0582, 0x015b, 1, "%s Control"),
/* M-Audio MidiSport 8x8 */ /* M-Audio MidiSport 8x8 */
CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
...@@ -1947,6 +1980,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, ...@@ -1947,6 +1980,44 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); 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. * Creates the endpoints and their ports for Midiman devices.
*/ */
...@@ -2162,6 +2233,9 @@ int snd_usbmidi_create(struct snd_card *card, ...@@ -2162,6 +2233,9 @@ int snd_usbmidi_create(struct snd_card *card,
case QUIRK_MIDI_YAMAHA: case QUIRK_MIDI_YAMAHA:
err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]); err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
break; break;
case QUIRK_MIDI_ROLAND:
err = snd_usbmidi_detect_roland(umidi, &endpoints[0]);
break;
case QUIRK_MIDI_MIDIMAN: case QUIRK_MIDI_MIDIMAN:
umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops; umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
memcpy(&endpoints[0], quirk->data, memcpy(&endpoints[0], quirk->data,
......
...@@ -202,13 +202,11 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, ...@@ -202,13 +202,11 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts, struct usb_host_interface *alts,
struct audioformat *fmt) struct audioformat *fmt)
{ {
struct usb_interface_descriptor *altsd = get_iface_desc(alts);
/* if endpoint doesn't have pitch control, bail out */ /* if endpoint doesn't have pitch control, bail out */
if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL)) if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
return 0; return 0;
switch (altsd->bInterfaceProtocol) { switch (fmt->protocol) {
case UAC_VERSION_1: case UAC_VERSION_1:
default: default:
return init_pitch_v1(chip, iface, alts, fmt); return init_pitch_v1(chip, iface, alts, fmt);
...@@ -300,6 +298,35 @@ static int deactivate_endpoints(struct snd_usb_substream *subs) ...@@ -300,6 +298,35 @@ static int deactivate_endpoints(struct snd_usb_substream *subs)
return 0; return 0;
} }
static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
unsigned int altsetting,
struct usb_host_interface **alts,
unsigned int *ep)
{
struct usb_interface *iface;
struct usb_interface_descriptor *altsd;
struct usb_endpoint_descriptor *epd;
iface = usb_ifnum_to_if(dev, ifnum);
if (!iface || iface->num_altsetting < altsetting + 1)
return -ENOENT;
*alts = &iface->altsetting[altsetting];
altsd = get_iface_desc(*alts);
if (altsd->bAlternateSetting != altsetting ||
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
(altsd->bInterfaceSubClass != 2 &&
altsd->bInterfaceProtocol != 2 ) ||
altsd->bNumEndpoints < 1)
return -ENOENT;
epd = get_endpoint(*alts, 0);
if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB)
return -ENOENT;
*ep = epd->bEndpointAddress;
return 0;
}
/* /*
* find a matching format and set up the interface * find a matching format and set up the interface
*/ */
...@@ -395,6 +422,18 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) ...@@ -395,6 +422,18 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
goto add_sync_ep; goto add_sync_ep;
} }
} }
if (is_playback &&
attr == USB_ENDPOINT_SYNC_ASYNC &&
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
altsd->bInterfaceProtocol == 2 &&
altsd->bNumEndpoints == 1 &&
USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
altsd->bAlternateSetting,
&alts, &ep) >= 0) {
implicit_fb = 1;
goto add_sync_ep;
}
if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
(!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
......
This diff is collapsed.
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/audio.h> #include <linux/usb/audio.h>
#include <linux/usb/midi.h>
#include <sound/control.h> #include <sound/control.h>
#include <sound/core.h> #include <sound/core.h>
...@@ -175,6 +176,212 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, ...@@ -175,6 +176,212 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
return 0; 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)
{
int err;
err = create_auto_pcm_quirk(chip, iface, driver);
if (err == -ENODEV)
err = create_auto_midi_quirk(chip, iface, driver);
return err;
}
static int create_autodetect_quirks(struct snd_usb_audio *chip,
struct usb_interface *iface,
struct usb_driver *driver,
const struct snd_usb_audio_quirk *quirk)
{
int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber;
int ifcount, ifnum, err;
err = create_autodetect_quirk(chip, iface, driver);
if (err < 0)
return err;
/*
* ALSA PCM playback/capture devices cannot be registered in two steps,
* so we have to claim the other corresponding interface here.
*/
ifcount = chip->dev->actconfig->desc.bNumInterfaces;
for (ifnum = 0; ifnum < ifcount; ifnum++) {
if (ifnum == probed_ifnum || quirk->ifnum >= 0)
continue;
iface = usb_ifnum_to_if(chip->dev, ifnum);
if (!iface ||
usb_interface_claimed(iface) ||
get_iface_desc(iface->altsetting)->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)
continue;
err = create_autodetect_quirk(chip, iface, driver);
if (err >= 0)
usb_driver_claim_interface(driver, iface, (void *)-1L);
}
return 0;
}
/* /*
* Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. * 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. * The only way to detect the sample rate is by looking at wMaxPacketSize.
...@@ -303,9 +510,11 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, ...@@ -303,9 +510,11 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
static const quirk_func_t quirk_funcs[] = { static const quirk_func_t quirk_funcs[] = {
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
[QUIRK_COMPOSITE] = create_composite_quirk, [QUIRK_COMPOSITE] = create_composite_quirk,
[QUIRK_AUTODETECT] = create_autodetect_quirks,
[QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
[QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
[QUIRK_MIDI_YAMAHA] = 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_MIDIMAN] = create_any_midi_quirk,
[QUIRK_MIDI_NOVATION] = create_any_midi_quirk, [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
[QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk, [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
......
...@@ -493,10 +493,10 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) ...@@ -493,10 +493,10 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
altsd = get_iface_desc(alts); altsd = get_iface_desc(alts);
protocol = altsd->bInterfaceProtocol; protocol = altsd->bInterfaceProtocol;
/* skip invalid one */ /* skip invalid one */
if ((altsd->bInterfaceClass != USB_CLASS_AUDIO && if (((altsd->bInterfaceClass != USB_CLASS_AUDIO ||
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
(altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING && (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) || altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC)) &&
altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
altsd->bNumEndpoints < 1 || altsd->bNumEndpoints < 1 ||
le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0) le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
continue; continue;
...@@ -512,6 +512,15 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) ...@@ -512,6 +512,15 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
if (snd_usb_apply_interface_quirk(chip, iface_no, altno)) if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
continue; continue;
/*
* Roland audio streaming interfaces are marked with protocols
* 0/1/2, but are UAC 1 compatible.
*/
if (USB_ID_VENDOR(chip->usb_id) == 0x0582 &&
altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
protocol <= 2)
protocol = UAC_VERSION_1;
chconfig = 0; chconfig = 0;
/* get audio formats */ /* get audio formats */
switch (protocol) { switch (protocol) {
...@@ -635,6 +644,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) ...@@ -635,6 +644,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress; fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
fp->ep_attr = get_endpoint(alts, 0)->bmAttributes; fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
fp->datainterval = snd_usb_parse_datainterval(chip, alts); fp->datainterval = snd_usb_parse_datainterval(chip, alts);
fp->protocol = protocol;
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
fp->channels = num_channels; fp->channels = num_channels;
if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
...@@ -676,7 +686,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no) ...@@ -676,7 +686,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
} }
/* ok, let's parse further... */ /* ok, let's parse further... */
if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) { if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream) < 0) {
kfree(fp->rate_table); kfree(fp->rate_table);
kfree(fp->chmap); kfree(fp->chmap);
kfree(fp); kfree(fp);
......
...@@ -72,9 +72,11 @@ struct snd_usb_audio { ...@@ -72,9 +72,11 @@ struct snd_usb_audio {
enum quirk_type { enum quirk_type {
QUIRK_IGNORE_INTERFACE, QUIRK_IGNORE_INTERFACE,
QUIRK_COMPOSITE, QUIRK_COMPOSITE,
QUIRK_AUTODETECT,
QUIRK_MIDI_STANDARD_INTERFACE, QUIRK_MIDI_STANDARD_INTERFACE,
QUIRK_MIDI_FIXED_ENDPOINT, QUIRK_MIDI_FIXED_ENDPOINT,
QUIRK_MIDI_YAMAHA, QUIRK_MIDI_YAMAHA,
QUIRK_MIDI_ROLAND,
QUIRK_MIDI_MIDIMAN, QUIRK_MIDI_MIDIMAN,
QUIRK_MIDI_NOVATION, QUIRK_MIDI_NOVATION,
QUIRK_MIDI_RAW_BYTES, QUIRK_MIDI_RAW_BYTES,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment