summaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2013-04-04 15:43:57 -0400
committerClemens Ladisch <clemens@ladisch.de>2013-06-27 15:59:49 -0400
commitb1ce7ba619d9de53db7fad25f445ca9abc2b63df (patch)
tree09e6fd2e2f1d81e54e52789ad1baf3eee2992b81 /sound/usb
parent8e5ced83dd1c3090c96c4e0614703f0f2a5ba2f4 (diff)
ALSA: usb-audio: claim autodetected PCM interfaces all at once
snd_card_register() registers all devices newly added since the last call. However, the playback/capture streams are handled as one ALSA device, so the second /dev device will not be registered if the PCM streams are added in two steps. QUIRK_AUTODETECT caused the probe callback to be called once for each interface, which triggered this problem. Work around this by handling this like the composite quirk, i.e., autodetecting all other interfaces that might be used for PCM or MIDI. Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/quirks.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 5363bcca9494..5b01330b8452 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -337,8 +337,7 @@ static int create_auto_midi_quirk(struct snd_usb_audio *chip,
337 337
338static int create_autodetect_quirk(struct snd_usb_audio *chip, 338static int create_autodetect_quirk(struct snd_usb_audio *chip,
339 struct usb_interface *iface, 339 struct usb_interface *iface,
340 struct usb_driver *driver, 340 struct usb_driver *driver)
341 const struct snd_usb_audio_quirk *quirk)
342{ 341{
343 int err; 342 int err;
344 343
@@ -348,6 +347,41 @@ static int create_autodetect_quirk(struct snd_usb_audio *chip,
348 return err; 347 return err;
349} 348}
350 349
350static int create_autodetect_quirks(struct snd_usb_audio *chip,
351 struct usb_interface *iface,
352 struct usb_driver *driver,
353 const struct snd_usb_audio_quirk *quirk)
354{
355 int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber;
356 int ifcount, ifnum, err;
357
358 err = create_autodetect_quirk(chip, iface, driver);
359 if (err < 0)
360 return err;
361
362 /*
363 * ALSA PCM playback/capture devices cannot be registered in two steps,
364 * so we have to claim the other corresponding interface here.
365 */
366 ifcount = chip->dev->actconfig->desc.bNumInterfaces;
367 for (ifnum = 0; ifnum < ifcount; ifnum++) {
368 if (ifnum == probed_ifnum || quirk->ifnum >= 0)
369 continue;
370 iface = usb_ifnum_to_if(chip->dev, ifnum);
371 if (!iface ||
372 usb_interface_claimed(iface) ||
373 get_iface_desc(iface->altsetting)->bInterfaceClass !=
374 USB_CLASS_VENDOR_SPEC)
375 continue;
376
377 err = create_autodetect_quirk(chip, iface, driver);
378 if (err >= 0)
379 usb_driver_claim_interface(driver, iface, (void *)-1L);
380 }
381
382 return 0;
383}
384
351/* 385/*
352 * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface. 386 * Create a stream for an Edirol UA-700/UA-25/UA-4FX interface.
353 * The only way to detect the sample rate is by looking at wMaxPacketSize. 387 * The only way to detect the sample rate is by looking at wMaxPacketSize.
@@ -476,7 +510,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
476 static const quirk_func_t quirk_funcs[] = { 510 static const quirk_func_t quirk_funcs[] = {
477 [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk, 511 [QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
478 [QUIRK_COMPOSITE] = create_composite_quirk, 512 [QUIRK_COMPOSITE] = create_composite_quirk,
479 [QUIRK_AUTODETECT] = create_autodetect_quirk, 513 [QUIRK_AUTODETECT] = create_autodetect_quirks,
480 [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk, 514 [QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
481 [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk, 515 [QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
482 [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, 516 [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,