Revert "ALSA: usb-audio: Register card at the last interface"

This reverts commit 0506c4eae9 which is
commit 6392dcd1d0c7034ccf630ec55fc9e5810ecadf3b upstream.

It breaks the abi and is not needed for Android devices as udev is not
used with them.  If it is needed to be added later on, it can come back
in an abi-stable way.

Bug: 161946584
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I59b6698df99c1e4bfc67c496a59d070706114f71
This commit is contained in:
Greg Kroah-Hartman
2022-11-21 15:51:14 +00:00
parent 8f38fb79b5
commit 85725fbe42
4 changed files with 51 additions and 26 deletions

View File

@@ -691,7 +691,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id)
return false;
}
static int check_delayed_register_option(struct snd_usb_audio *chip)
static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
{
int i;
unsigned int id, inum;
@@ -700,31 +700,14 @@ static int check_delayed_register_option(struct snd_usb_audio *chip)
if (delayed_register[i] &&
sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
id == chip->usb_id)
return inum;
return iface < inum;
}
return -1;
return false;
}
static const struct usb_device_id usb_audio_ids[]; /* defined below */
/* look for the last interface that matches with our ids and remember it */
static void find_last_interface(struct snd_usb_audio *chip)
{
struct usb_host_config *config = chip->dev->actconfig;
struct usb_interface *intf;
int i;
if (!config)
return;
for (i = 0; i < config->desc.bNumInterfaces; i++) {
intf = config->interface[i];
if (usb_match_id(intf, usb_audio_ids))
chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber;
}
usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface);
}
/* look for the corresponding quirk */
static const struct snd_usb_audio_quirk *
get_alias_quirk(struct usb_device *dev, unsigned int id)
@@ -833,7 +816,6 @@ static int usb_audio_probe(struct usb_interface *intf,
err = -ENODEV;
goto __error;
}
find_last_interface(chip);
}
if (chip->num_interfaces >= MAX_CARD_INTERFACES) {
@@ -885,11 +867,11 @@ static int usb_audio_probe(struct usb_interface *intf,
chip->need_delayed_register = false; /* clear again */
}
/* register card if we reach to the last interface or to the specified
* one given via option
/* we are allowed to call snd_card_register() many times, but first
* check to see if a device needs to skip it or do anything special
*/
if (check_delayed_register_option(chip) == ifnum ||
chip->last_iface == ifnum) {
if (!snd_usb_registration_quirk(chip, ifnum) &&
!check_delayed_register_option(chip, ifnum)) {
err = snd_card_register(chip->card);
if (err < 0)
goto __error;

View File

@@ -1728,6 +1728,48 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
}
}
/*
* registration quirk:
* the registration is skipped if a device matches with the given ID,
* unless the interface reaches to the defined one. This is for delaying
* the registration until the last known interface, so that the card and
* devices appear at the same time.
*/
struct registration_quirk {
unsigned int usb_id; /* composed via USB_ID() */
unsigned int interface; /* the interface to trigger register */
};
#define REG_QUIRK_ENTRY(vendor, product, iface) \
{ .usb_id = USB_ID(vendor, product), .interface = (iface) }
static const struct registration_quirk registration_quirks[] = {
REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */
REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */
REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */
REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */
REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */
{ 0 } /* terminator */
};
/* return true if skipping registration */
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
{
const struct registration_quirk *q;
for (q = registration_quirks; q->usb_id; q++)
if (chip->usb_id == q->usb_id)
return iface < q->interface;
/* Register as normal */
return false;
}
/*
* driver behavior quirk flags
*/

View File

@@ -48,6 +48,8 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
struct audioformat *fp,
int stream);
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
#endif /* __USBAUDIO_QUIRKS_H */

View File

@@ -39,7 +39,6 @@ struct snd_usb_audio {
unsigned int quirk_flags;
unsigned int need_delayed_register:1; /* warn for delayed registration */
int num_interfaces;
int last_iface;
int num_suspended_intf;
int sample_rate_read_error;