diff options
| -rw-r--r-- | sound/usb/midi.c | 41 | ||||
| -rw-r--r-- | sound/usb/quirks-table.h | 22 | ||||
| -rw-r--r-- | sound/usb/quirks.c | 175 | ||||
| -rw-r--r-- | sound/usb/stream.c | 15 | ||||
| -rw-r--r-- | sound/usb/usbaudio.h | 2 |
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 | */ | ||
| 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 | |||
| 1988 | /* | ||
| 1951 | * Creates the endpoints and their ports for Midiman devices. | 1989 | * Creates the endpoints and their ports for Midiman devices. |
| 1952 | */ | 1990 | */ |
| 1953 | static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | 1991 | static 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"), | |||
| 455 | YAMAHA_DEVICE(0x7010, "UB99"), | 455 | YAMAHA_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 | ||
| 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 = { | ||
