Commit b2345a8a authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Fix the missing endpoints creations for quirks

The recent change in the endpoint management moved the endpoint object
creation from the stream open time to the parser of the audio
descriptor.  It works fine for the standard audio, but it overlooked
the other places that create audio streams via quirks
(QUIRK_AUDIO_FIXED_ENDPOINT) like the reported a few Pioneer devices;
those call snd_usb_add_audio_stream() manually, hence they miss the
endpoints, eventually resulting in the error at opening streams.
Moreover, now the sync EP setup was moved to the explicit call of
snd_usb_audioformat_set_sync_ep(), and this needs to be added for
those places, too.

This patch addresses those regressions for quirks.  It adds a local
helper function add_audio_stream_from_fixed_fmt(), which does the all
needed tasks, and replaces the calls of snd_usb_add_audio_stream()
with this new function.

Fixes: 54cb3190 ("ALSA: usb-audio: Create endpoint objects at parsing phase")
Reported-by: default avatarFrantišek Kučera <konference@frantovo.cz>
Link: https://lore.kernel.org/r/20210108075219.21463-2-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 7b622755
...@@ -120,6 +120,40 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip, ...@@ -120,6 +120,40 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
return 0; return 0;
} }
/* create the audio stream and the corresponding endpoints from the fixed
* audioformat object; this is used for quirks with the fixed EPs
*/
static int add_audio_stream_from_fixed_fmt(struct snd_usb_audio *chip,
struct audioformat *fp)
{
int stream, err;
stream = (fp->endpoint & USB_DIR_IN) ?
SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
snd_usb_audioformat_set_sync_ep(chip, fp);
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0)
return err;
err = snd_usb_add_endpoint(chip, fp->endpoint,
SND_USB_ENDPOINT_TYPE_DATA);
if (err < 0)
return err;
if (fp->sync_ep) {
err = snd_usb_add_endpoint(chip, fp->sync_ep,
fp->implicit_fb ?
SND_USB_ENDPOINT_TYPE_DATA :
SND_USB_ENDPOINT_TYPE_SYNC);
if (err < 0)
return err;
}
return 0;
}
/* /*
* create a stream for an endpoint/altsetting without proper descriptors * create a stream for an endpoint/altsetting without proper descriptors
*/ */
...@@ -131,8 +165,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, ...@@ -131,8 +165,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
struct audioformat *fp; struct audioformat *fp;
struct usb_host_interface *alts; struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd; struct usb_interface_descriptor *altsd;
int stream, err;
unsigned *rate_table = NULL; unsigned *rate_table = NULL;
int err;
fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL); fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
if (!fp) if (!fp)
...@@ -153,11 +187,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, ...@@ -153,11 +187,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
fp->rate_table = rate_table; fp->rate_table = rate_table;
} }
stream = (fp->endpoint & USB_DIR_IN)
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0)
goto error;
if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber || if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
fp->altset_idx >= iface->num_altsetting) { fp->altset_idx >= iface->num_altsetting) {
err = -EINVAL; err = -EINVAL;
...@@ -176,6 +205,13 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip, ...@@ -176,6 +205,13 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
fp->datainterval = snd_usb_parse_datainterval(chip, alts); fp->datainterval = snd_usb_parse_datainterval(chip, alts);
if (fp->maxpacksize == 0) if (fp->maxpacksize == 0)
fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize); fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
if (!fp->fmt_type)
fp->fmt_type = UAC_FORMAT_TYPE_I;
err = add_audio_stream_from_fixed_fmt(chip, fp);
if (err < 0)
goto error;
usb_set_interface(chip->dev, fp->iface, 0); usb_set_interface(chip->dev, fp->iface, 0);
snd_usb_init_pitch(chip, fp); snd_usb_init_pitch(chip, fp);
snd_usb_init_sample_rate(chip, fp, fp->rate_max); snd_usb_init_sample_rate(chip, fp, fp->rate_max);
...@@ -417,7 +453,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, ...@@ -417,7 +453,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
struct usb_host_interface *alts; struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd; struct usb_interface_descriptor *altsd;
struct audioformat *fp; struct audioformat *fp;
int stream, err; int err;
/* both PCM and MIDI interfaces have 2 or more altsettings */ /* both PCM and MIDI interfaces have 2 or more altsettings */
if (iface->num_altsetting < 2) if (iface->num_altsetting < 2)
...@@ -482,9 +518,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, ...@@ -482,9 +518,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
return -ENXIO; return -ENXIO;
} }
stream = (fp->endpoint & USB_DIR_IN) err = add_audio_stream_from_fixed_fmt(chip, fp);
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) { if (err < 0) {
list_del(&fp->list); /* unlink for avoiding double-free */ list_del(&fp->list); /* unlink for avoiding double-free */
kfree(fp); kfree(fp);
......
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