Skip to content

Commit

Permalink
ALSA: usb-audio: claim autodetected PCM interfaces all at once
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Clemens Ladisch committed Jun 27, 2013
1 parent 8e5ced8 commit b1ce7ba
Showing 1 changed file with 37 additions and 3 deletions.
40 changes: 37 additions & 3 deletions sound/usb/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,7 @@ static int create_auto_midi_quirk(struct snd_usb_audio *chip,

static int create_autodetect_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
struct usb_driver *driver,
const struct snd_usb_audio_quirk *quirk)
struct usb_driver *driver)
{
int err;

Expand All @@ -348,6 +347,41 @@ static int create_autodetect_quirk(struct snd_usb_audio *chip,
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.
* The only way to detect the sample rate is by looking at wMaxPacketSize.
Expand Down Expand Up @@ -476,7 +510,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
static const quirk_func_t quirk_funcs[] = {
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
[QUIRK_COMPOSITE] = create_composite_quirk,
[QUIRK_AUTODETECT] = create_autodetect_quirk,
[QUIRK_AUTODETECT] = create_autodetect_quirks,
[QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
[QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
Expand Down

0 comments on commit b1ce7ba

Please sign in to comment.