All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/41] USB audio refactoring for better implicit feedback support
@ 2020-11-23  8:53 Takashi Iwai
  2020-11-23  8:53 ` [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints Takashi Iwai
                   ` (40 more replies)
  0 siblings, 41 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Hi,

here is a largish patch set for USB-audio.  Its main goal is to
address the long-standing issues wrt the implicit feedback mode.
With the current driver, when the implicit fb is used, the full duplex
doesn't work properly unless you start both streams *very* carefully.
This patch set tries to ease such the configuration mismatch and fix
many other bugs.

In short, with this patch set applied, USB-audio driver will try to
restrict the hw_params to match with the already opened counter-part
stream automatically.  So individual aplay and arecord invocation
should work now, as well as PulseAudio.

Also, the patch set includes more fixes, e.g. the generic detection of
the implicit feedback mode on UAC2/3, and the fix for the sample rate
selection on UAC2/3, as well as a few more quirks to follow the new
implicit fb model.

The latest patches are available in topic/usb-audio-refactoring
branch.

I specially thank Keith Milner and Dylan Robinson for their time spent
for lots of testing.  Without their patient help, I couldn't finish
those patches, as I myself don't own such devices.


Takashi

===

Dylan Robinson (1):
  ALSA: usb-audio: Fix MOTU M-Series quirks

Takashi Iwai (40):
  ALSA: usb-audio: Handle discrete rates properly in hw constraints
  ALSA: usb-audio: Don't call usb_set_interface() at trigger callback
  ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3
  ALSA: usb-audio: Check implicit feedback EP generically for UAC2
  ALSA: usb-audio: Add snd_usb_get_endpoint() helper
  ALSA: usb-audio: Set and clear sync EP link properly
  ALSA: usb-audio: Improve some debug prints
  ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list
  ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info()
  ALSA: usb-audio: Add hw constraint for implicit fb sync
  ALSA: usb-audio: Simplify hw_params rules
  ALSA: usb-audio: Drop debug.h
  ALSA: usb-audio: Avoid doubly initialization for implicit fb
  ALSA: usb-audio: Create endpoint objects at parsing phase
  ALSA: usb-audio: Drop keep_interface flag again
  ALSA: usb-audio: Add snd_usb_get_host_interface() helper
  ALSA: usb-audio: Don't set altsetting before initializing sample rate
  ALSA: usb-audio: Pass snd_usb_audio object to quirk functions
  ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments
  ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments
  ALSA: usb-audio: Stop both endpoints properly at error
  ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback()
  ALSA: usb-audio: Always set up the parameters after resume
  ALSA: usb-audio: Fix EP matching for continuous rates
  ALSA: usb-audio: Refactor endpoint management
  ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer
  ALSA: usb-audio: Constify audioformat pointer references
  ALSA: usb-audio: Use atomic_t for endpoint use_count
  ALSA: usb-audio: Refactoring endpoint URB deactivation
  ALSA: usb-audio: Drop unneeded snd_usb_substream fields
  ALSA: usb-audio: Unify the code for the next packet size calculation
  ALSA: usb-audio: Simplify rate_min/max and rates set up
  ALSA: usb-audio: Replace slave/master terms
  ALSA: usb-audio: Use unsigned char for iface and altsettings fields
  ALSA: usb-audio: Show sync endpoint information in proc outputs
  ALSA: usb-audio: Quirk for BOSS GT-001
  ALSA: usb-audio: Factor out the implicit feedback quirk code
  ALSA: usb-audio: Add generic implicit fb parsing
  ALSA: usb-audio: Add implicit_fb module option
  ALSA: usb-audio: Fix quirks for other BOSS devices

 Documentation/sound/alsa-configuration.rst |    5 +
 sound/usb/Makefile                         |    1 +
 sound/usb/card.c                           |   14 +-
 sound/usb/card.h                           |   53 +-
 sound/usb/clock.c                          |  152 ++--
 sound/usb/clock.h                          |   11 +-
 sound/usb/debug.h                          |   16 -
 sound/usb/endpoint.c                       |  943 +++++++++++++----------
 sound/usb/endpoint.h                       |   57 +-
 sound/usb/format.c                         |  125 +++-
 sound/usb/helper.c                         |   10 +
 sound/usb/helper.h                         |    3 +
 sound/usb/implicit.c                       |  402 ++++++++++
 sound/usb/implicit.h                       |   14 +
 sound/usb/mixer.c                          |   46 --
 sound/usb/pcm.c                            | 1117 ++++++++++------------------
 sound/usb/pcm.h                            |    7 +-
 sound/usb/proc.c                           |   35 +-
 sound/usb/quirks-table.h                   |    8 -
 sound/usb/quirks.c                         |   60 +-
 sound/usb/quirks.h                         |   10 +-
 sound/usb/stream.c                         |   24 +-
 sound/usb/usbaudio.h                       |    5 +-
 23 files changed, 1696 insertions(+), 1422 deletions(-)
 delete mode 100644 sound/usb/debug.h
 create mode 100644 sound/usb/implicit.c
 create mode 100644 sound/usb/implicit.h

-- 
2.16.4


^ permalink raw reply	[flat|nested] 52+ messages in thread

* [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 02/41] ALSA: usb-audio: Don't call usb_set_interface() at trigger callback Takashi Iwai
                   ` (39 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

In the current code, when the device provides the discrete sample rate
tables with unusual sample rates, the driver tries to gather the whole
values from the audioformat entries and create a hw-constraint rule to
restrict with this single rate list.  This is rather inefficient and
may overlook the rates that are associated only with the certain
audioformat entries.

This patch improves the hw constraint setup by rewriting the existing
hw_rule_rate().  The discrete sample rates (identified by rate_table
and nr_rates of format entry) are checked in the existing
hw_rule_rate() instead of extra rules; in the case of discrete rates,
the function compares with each rate table entry and calculates the
min/max values from there.  For the contiguous rates, the behavior
doesn't change.

Along with it, snd_usb_pcm_check_knot() and snb_usb_substream
rate_list field become superfluous, thus those are dropped.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h   |  1 -
 sound/usb/pcm.c    | 73 +++++++++++-------------------------------------------
 sound/usb/stream.c |  1 -
 3 files changed, 15 insertions(+), 60 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 5351d7183b1b..3cc668f98f43 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -157,7 +157,6 @@ struct snd_usb_substream {
 	u64 formats;			/* format bitmasks (all or'ed) */
 	unsigned int num_formats;		/* number of supported audio formats (list) */
 	struct list_head fmt_list;	/* format list */
-	struct snd_pcm_hw_constraint_list rate_list;	/* limited rates */
 	spinlock_t lock;
 
 	int last_frame_number;          /* stored frame number */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index a860303cc522..3265155df1b5 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1039,27 +1039,31 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 	struct snd_usb_substream *subs = rule->private;
 	struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
-	unsigned int rmin, rmax;
+	unsigned int rmin, rmax, r;
 	int changed;
+	int i;
 
 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
-	changed = 0;
-	rmin = rmax = 0;
+	rmin = UINT_MAX;
+	rmax = 0;
 	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!hw_check_valid_format(subs, params, fp))
 			continue;
-		if (changed++) {
-			if (rmin > fp->rate_min)
-				rmin = fp->rate_min;
-			if (rmax < fp->rate_max)
-				rmax = fp->rate_max;
+		if (fp->rate_table && fp->nr_rates) {
+			for (i = 0; i < fp->nr_rates; i++) {
+				r = fp->rate_table[i];
+				if (!snd_interval_test(it, r))
+					continue;
+				rmin = min(rmin, r);
+				rmax = max(rmax, r);
+			}
 		} else {
-			rmin = fp->rate_min;
-			rmax = fp->rate_max;
+			rmin = min(rmin, fp->rate_min);
+			rmax = max(rmax, fp->rate_max);
 		}
 	}
 
-	if (!changed) {
+	if (rmin > rmax) {
 		hwc_debug("  --> get empty\n");
 		it->empty = 1;
 		return -EINVAL;
@@ -1205,50 +1209,6 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 	return changed;
 }
 
-/*
- *  If the device supports unusual bit rates, does the request meet these?
- */
-static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
-				  struct snd_usb_substream *subs)
-{
-	struct audioformat *fp;
-	int *rate_list;
-	int count = 0, needs_knot = 0;
-	int err;
-
-	kfree(subs->rate_list.list);
-	subs->rate_list.list = NULL;
-
-	list_for_each_entry(fp, &subs->fmt_list, list) {
-		if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
-			return 0;
-		count += fp->nr_rates;
-		if (fp->rates & SNDRV_PCM_RATE_KNOT)
-			needs_knot = 1;
-	}
-	if (!needs_knot)
-		return 0;
-
-	subs->rate_list.list = rate_list =
-		kmalloc_array(count, sizeof(int), GFP_KERNEL);
-	if (!subs->rate_list.list)
-		return -ENOMEM;
-	subs->rate_list.count = count;
-	subs->rate_list.mask = 0;
-	count = 0;
-	list_for_each_entry(fp, &subs->fmt_list, list) {
-		int i;
-		for (i = 0; i < fp->nr_rates; i++)
-			rate_list[count++] = fp->rate_table[i];
-	}
-	err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-					 &subs->rate_list);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
 
 /*
  * set up the runtime hardware information.
@@ -1338,9 +1298,6 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 		if (err < 0)
 			return err;
 	}
-	err = snd_usb_pcm_check_knot(runtime, subs);
-	if (err < 0)
-		return err;
 
 	return snd_usb_autoresume(subs->stream->chip);
 }
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index ca76ba5b5c0b..f17913e0b5b4 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -47,7 +47,6 @@ static void free_substream(struct snd_usb_substream *subs)
 		return; /* not initialized */
 	list_for_each_entry_safe(fp, n, &subs->fmt_list, list)
 		audioformat_free(fp);
-	kfree(subs->rate_list.list);
 	kfree(subs->str_pd);
 	snd_media_stream_delete(subs);
 }
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 02/41] ALSA: usb-audio: Don't call usb_set_interface() at trigger callback
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
  2020-11-23  8:53 ` [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 03/41] ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3 Takashi Iwai
                   ` (38 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The PCM trigger callback is atomic, hence we must not call a function
like usb_set_interface() there.  Calling it from there would lead to a
kernel Oops.

Fix it by moving the usb_set_interface() call to set_sync_endpoint().

Also, apply the snd_usb_set_interface_quirk() for consistency, too.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 3265155df1b5..380d7275d187 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -232,21 +232,6 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
-		if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
-		    subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
-			err = usb_set_interface(subs->dev,
-						subs->sync_endpoint->iface,
-						subs->sync_endpoint->altsetting);
-			if (err < 0) {
-				clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
-				dev_err(&subs->dev->dev,
-					   "%d:%d: cannot set interface (%d)\n",
-					   subs->sync_endpoint->iface,
-					   subs->sync_endpoint->altsetting, err);
-				return -EIO;
-			}
-		}
-
 		dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
 
 		ep->sync_slave = subs->data_endpoint;
@@ -530,6 +515,19 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 
 	subs->data_endpoint->sync_master = subs->sync_endpoint;
 
+	if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
+	    subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
+		err = usb_set_interface(subs->dev,
+					subs->sync_endpoint->iface,
+					subs->sync_endpoint->altsetting);
+		if (err < 0)
+			return err;
+		dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
+			subs->sync_endpoint->iface,
+			subs->sync_endpoint->altsetting);
+		snd_usb_set_interface_quirk(dev);
+	}
+
 	return 0;
 }
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 03/41] ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
  2020-11-23  8:53 ` [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints Takashi Iwai
  2020-11-23  8:53 ` [PATCH 02/41] ALSA: usb-audio: Don't call usb_set_interface() at trigger callback Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 04/41] ALSA: usb-audio: Check implicit feedback EP generically for UAC2 Takashi Iwai
                   ` (37 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The current driver code assumes blindly that all found sample rates for
the same endpoint from the UAC2 and UAC3 descriptors can be used no
matter which altsetting, but actually this was wrong: some devices
accept only limited sample rates in each altsetting.  For determining
which altsetting supports which rate, we need to verify each sample rate
and check the validity via UAC2_AS_VAL_ALT_SETTINGS.  This control
reports back the available altsettings as a bitmap.

This patch implements the missing piece above, the verification and
reconstructs the sample rate tables based on the result.

An open question is how to deal with the altsettings that ended up
with no valid sample rates after verification.  At least, there is a
device that showed this problem although the sample rates did work in
the later usage (see bug link).  For now, we accept such an altset as
is, assuming that it's a firmware bug.

Reported-by: Dylan Robinson <dylan_robinson@motu.com>
Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
BugLink: https://bugzilla.suse.com/show_bug.cgi?id=1178203
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/clock.c  | 106 ++++++++++++++++++++++++++++++-----------------------
 sound/usb/clock.h  |   4 ++
 sound/usb/format.c |  93 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+), 45 deletions(-)

diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index f3ca59005d91..f174230d07d5 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -560,16 +560,60 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	return le32_to_cpu(data);
 }
 
+/*
+ * Try to set the given sample rate:
+ *
+ * Return 0 if the clock source is read-only, the actual rate on success,
+ * or a negative error code.
+ *
+ * This function gets called from format.c to validate each sample rate, too.
+ * Hence no message is shown upon error
+ */
+int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
+				 const struct audioformat *fmt,
+				 int clock, int rate)
+{
+	bool writeable;
+	u32 bmControls;
+	__le32 data;
+	int err;
+
+	if (fmt->protocol == UAC_VERSION_3) {
+		struct uac3_clock_source_descriptor *cs_desc;
+
+		cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock);
+		bmControls = le32_to_cpu(cs_desc->bmControls);
+	} else {
+		struct uac_clock_source_descriptor *cs_desc;
+
+		cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
+		bmControls = cs_desc->bmControls;
+	}
+
+	writeable = uac_v2v3_control_is_writeable(bmControls,
+						  UAC2_CS_CONTROL_SAM_FREQ);
+	if (!writeable)
+		return 0;
+
+	data = cpu_to_le32(rate);
+	err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
+			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			      UAC2_CS_CONTROL_SAM_FREQ << 8,
+			      snd_usb_ctrl_intf(chip) | (clock << 8),
+			      &data, sizeof(data));
+	if (err < 0)
+		return err;
+
+	return get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock);
+}
+
 static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-			      struct usb_host_interface *alts,
-			      struct audioformat *fmt, int rate)
+				struct usb_host_interface *alts,
+				struct audioformat *fmt, int rate)
 {
 	struct usb_device *dev = chip->dev;
-	__le32 data;
-	int err, cur_rate, prev_rate;
+	int cur_rate, prev_rate;
 	int clock;
-	bool writeable;
-	u32 bmControls;
 
 	/* First, try to find a valid clock. This may trigger
 	 * automatic clock selection if the current clock is not
@@ -592,50 +636,22 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	if (prev_rate == rate)
 		goto validation;
 
-	if (fmt->protocol == UAC_VERSION_3) {
-		struct uac3_clock_source_descriptor *cs_desc;
-
-		cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock);
-		bmControls = le32_to_cpu(cs_desc->bmControls);
-	} else {
-		struct uac_clock_source_descriptor *cs_desc;
-
-		cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
-		bmControls = cs_desc->bmControls;
+	cur_rate = snd_usb_set_sample_rate_v2v3(chip, fmt, clock, rate);
+	if (cur_rate < 0) {
+		usb_audio_err(chip,
+			      "%d:%d: cannot set freq %d (v2/v3): err %d\n",
+			      iface, fmt->altsetting, rate, cur_rate);
+		return cur_rate;
 	}
 
-	writeable = uac_v2v3_control_is_writeable(bmControls,
-						  UAC2_CS_CONTROL_SAM_FREQ);
-	if (writeable) {
-		data = cpu_to_le32(rate);
-		err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
-				      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				      UAC2_CS_CONTROL_SAM_FREQ << 8,
-				      snd_usb_ctrl_intf(chip) | (clock << 8),
-				      &data, sizeof(data));
-		if (err < 0) {
-			usb_audio_err(chip,
-				"%d:%d: cannot set freq %d (v2/v3): err %d\n",
-				iface, fmt->altsetting, rate, err);
-			return err;
-		}
-
-		cur_rate = get_sample_rate_v2v3(chip, iface,
-						fmt->altsetting, clock);
-	} else {
+	if (!cur_rate)
 		cur_rate = prev_rate;
-	}
 
 	if (cur_rate != rate) {
-		if (!writeable) {
-			usb_audio_warn(chip,
-				 "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
-				 iface, fmt->altsetting, rate, cur_rate);
-			return -ENXIO;
-		}
-		usb_audio_dbg(chip,
-			"current rate %d is different from the runtime rate %d\n",
-			cur_rate, rate);
+		usb_audio_warn(chip,
+			       "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
+			       fmt->iface, fmt->altsetting, rate, cur_rate);
+		return -ENXIO;
 	}
 
 	/* Some devices doesn't respond to sample rate changes while the
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index 68df0fbe09d0..97597f5a3c18 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -9,4 +9,8 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 int snd_usb_clock_find_source(struct snd_usb_audio *chip,
 			      struct audioformat *fmt, bool validate);
 
+int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
+				 const struct audioformat *fmt,
+				 int clock, int rate);
+
 #endif /* __USBAUDIO_CLOCK_H */
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 3bfead393aa3..3348032daa16 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -417,6 +417,97 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
 	return -ENODEV;
 }
 
+/* check whether the given altsetting is supported for the already set rate */
+static bool check_valid_altsetting_v2v3(struct snd_usb_audio *chip, int iface,
+					int altsetting)
+{
+	struct usb_device *dev = chip->dev;
+	__le64 raw_data = 0;
+	u64 data;
+	int err;
+
+	/* we assume 64bit is enough for any altsettings */
+	if (snd_BUG_ON(altsetting >= 64 - 8))
+		return false;
+
+	err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			      UAC2_AS_VAL_ALT_SETTINGS << 8,
+			      iface, &raw_data, sizeof(raw_data));
+	if (err < 0)
+		return false;
+
+	data = le64_to_cpu(raw_data);
+	/* first byte contains the bitmap size */
+	if ((data & 0xff) * 8 < altsetting)
+		return false;
+	if (data & (1ULL << (altsetting + 8)))
+		return true;
+
+	return false;
+}
+
+/*
+ * Validate each sample rate with the altsetting
+ * Rebuild the rate table if only partial values are valid
+ */
+static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
+					   struct audioformat *fp,
+					   int clock)
+{
+	struct usb_device *dev = chip->dev;
+	unsigned int *table;
+	unsigned int nr_rates;
+	unsigned int rate_min = 0x7fffffff;
+	unsigned int rate_max = 0;
+	unsigned int rates = 0;
+	int i, err;
+
+	table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
+	if (!table)
+		return -ENOMEM;
+
+	/* clear the interface altsetting at first */
+	usb_set_interface(dev, fp->iface, 0);
+
+	nr_rates = 0;
+	for (i = 0; i < fp->nr_rates; i++) {
+		err = snd_usb_set_sample_rate_v2v3(chip, fp, clock,
+						   fp->rate_table[i]);
+		if (err < 0)
+			continue;
+
+		if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting)) {
+			table[nr_rates++] = fp->rate_table[i];
+			if (rate_min > fp->rate_table[i])
+				rate_min = fp->rate_table[i];
+			if (rate_max < fp->rate_table[i])
+				rate_max = fp->rate_table[i];
+			rates |= snd_pcm_rate_to_rate_bit(fp->rate_table[i]);
+		}
+	}
+
+	if (!nr_rates) {
+		usb_audio_dbg(chip,
+			      "No valid sample rate available for %d:%d, assuming a firmware bug\n",
+			      fp->iface, fp->altsetting);
+		nr_rates = fp->nr_rates; /* continue as is */
+	}
+
+	if (fp->nr_rates == nr_rates) {
+		kfree(table);
+		return 0;
+	}
+
+	kfree(fp->rate_table);
+	fp->rate_table = table;
+	fp->nr_rates = nr_rates;
+	fp->rate_min = rate_min;
+	fp->rate_max = rate_max;
+	fp->rates = rates;
+	return 0;
+}
+
 /*
  * parse the format descriptor and stores the possible sample rates
  * on the audioformat table (audio class v2 and v3).
@@ -509,6 +600,8 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
 	 * allocated, so the rates will be stored */
 	parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);
 
+	ret = validate_sample_rate_table_v2v3(chip, fp, clock);
+
 err_free:
 	kfree(data);
 err:
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 04/41] ALSA: usb-audio: Check implicit feedback EP generically for UAC2
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (2 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 03/41] ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3 Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 05/41] ALSA: usb-audio: Add snd_usb_get_endpoint() helper Takashi Iwai
                   ` (36 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

It seems that many UAC2 devices are with the implicit feedback, but
they couldn't be probed properly because the assumption the driver
takes currently isn't applied: they have the single endpoint for both
data and implicit-fb streams, while we checked only the classical sync
endpoints assigned to the next altsetting in the same interface.

This patch extends the search to match with those typical cases where
the implicit fb stream is found in the next interface number.

While we're at it, slightly refactor the code, not returning 0/-ERROR
but use the standard bool to success/failur, which is more intuitive
in this particular case.

Reported-by: Dylan Robinson <dylan_robinson@motu.com>
Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 83 +++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 66 insertions(+), 17 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 380d7275d187..2b11c2c837bf 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -272,33 +272,70 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
-				     unsigned int altsetting,
-				     struct usb_host_interface **alts,
-				     unsigned int *ep)
+/* Check whether the given iface:altsetting points to an implicit fb source */
+static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum,
+				       unsigned int altsetting,
+				       struct usb_host_interface **altsp,
+				       unsigned int *ep)
 {
 	struct usb_interface *iface;
+	struct usb_host_interface *alts;
+	struct usb_interface_descriptor *altsd;
+	struct usb_endpoint_descriptor *epd;
+
+	iface = usb_ifnum_to_if(dev, ifnum);
+	if (!iface)
+		return false;
+	alts = usb_altnum_to_altsetting(iface, altsetting);
+	if (!alts)
+		return false;
+	altsd = get_iface_desc(alts);
+	if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
+	    altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING ||
+	    altsd->bInterfaceProtocol != UAC_VERSION_2 ||
+	    altsd->bNumEndpoints < 1)
+		return false;
+	epd = get_endpoint(alts, 0);
+	if (!usb_endpoint_is_isoc_in(epd) ||
+	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
+					USB_ENDPOINT_USAGE_IMPLICIT_FB)
+		return false;
+	*ep = epd->bEndpointAddress;
+	*altsp = alts;
+	return true;
+}
+
+/* Like the function above, but specific to Roland with vendor class and hack */
+static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum,
+				      unsigned int altsetting,
+				      struct usb_host_interface **altsp,
+				      unsigned int *ep)
+{
+	struct usb_interface *iface;
+	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct usb_endpoint_descriptor *epd;
 
 	iface = usb_ifnum_to_if(dev, ifnum);
-	if (!iface || iface->num_altsetting < altsetting + 1)
-		return -ENOENT;
-	*alts = &iface->altsetting[altsetting];
-	altsd = get_iface_desc(*alts);
-	if (altsd->bAlternateSetting != altsetting ||
-	    altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
+	if (!iface)
+		return false;
+	alts = usb_altnum_to_altsetting(iface, altsetting);
+	if (!alts)
+		return false;
+	altsd = get_iface_desc(alts);
+	if (altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
 	    (altsd->bInterfaceSubClass != 2 &&
-	     altsd->bInterfaceProtocol != 2   ) ||
+	     altsd->bInterfaceProtocol != 2) ||
 	    altsd->bNumEndpoints < 1)
-		return -ENOENT;
-	epd = get_endpoint(*alts, 0);
+		return false;
+	epd = get_endpoint(alts, 0);
 	if (!usb_endpoint_is_isoc_in(epd) ||
 	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
 					USB_ENDPOINT_USAGE_IMPLICIT_FB)
-		return -ENOENT;
+		return false;
 	*ep = epd->bEndpointAddress;
-	return 0;
+	*altsp = alts;
+	return true;
 }
 
 /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
@@ -375,6 +412,19 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 		return 0;
 	}
 
+	/* Generic UAC2 implicit feedback */
+	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+	    altsd->bInterfaceClass == USB_CLASS_AUDIO &&
+	    altsd->bInterfaceProtocol == UAC_VERSION_2 &&
+	    altsd->bNumEndpoints == 1) {
+		ifnum = altsd->bInterfaceNumber + 1;
+		if (search_generic_implicit_fb(dev, ifnum,
+					       altsd->bAlternateSetting,
+					       &alts, &ep))
+			goto add_sync_ep;
+	}
+
+	/* Roland/BOSS implicit feedback with vendor spec class */
 	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
 	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
 	    altsd->bInterfaceProtocol == 2 &&
@@ -382,9 +432,8 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	    USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
 	    search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
 				      altsd->bAlternateSetting,
-				      &alts, &ep) >= 0) {
+				      &alts, &ep))
 		goto add_sync_ep;
-	}
 
 	/* No quirk */
 	return 0;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 05/41] ALSA: usb-audio: Add snd_usb_get_endpoint() helper
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (3 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 04/41] ALSA: usb-audio: Check implicit feedback EP generically for UAC2 Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 06/41] ALSA: usb-audio: Set and clear sync EP link properly Takashi Iwai
                   ` (35 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Factor out the code to obtain snd_usb_endpoint object matching with
the given endpoint.  It'll be used in the later patch to add the
implicit feedback hw-constraint.

No functional change by this patch itself.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c | 36 +++++++++++++++++++++++++++---------
 sound/usb/endpoint.h |  4 ++++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index e2f9ce2f5b8b..cf00871fd278 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -439,6 +439,26 @@ static void snd_complete_urb(struct urb *urb)
 	clear_bit(ctx->index, &ep->active_mask);
 }
 
+/*
+ * Get the existing endpoint object corresponding EP, iface and alt numbers
+ * Returns NULL if not present.
+ * Call inside chip->mutex locking for avoiding the race.
+ */
+struct snd_usb_endpoint *
+snd_usb_get_endpoint(struct snd_usb_audio *chip,
+		     int ep_num, int iface, int altsetting)
+{
+	struct snd_usb_endpoint *ep;
+
+	list_for_each_entry(ep, &chip->ep_list, list) {
+		if (ep->ep_num == ep_num &&
+		    ep->iface == iface &&
+		    ep->altsetting == altsetting)
+			return ep;
+	}
+	return NULL;
+}
+
 /**
  * snd_usb_add_endpoint: Add an endpoint to an USB audio chip
  *
@@ -470,15 +490,13 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 
 	mutex_lock(&chip->mutex);
 
-	list_for_each_entry(ep, &chip->ep_list, list) {
-		if (ep->ep_num == ep_num &&
-		    ep->iface == alts->desc.bInterfaceNumber &&
-		    ep->altsetting == alts->desc.bAlternateSetting) {
-			usb_audio_dbg(ep->chip,
-				      "Re-using EP %x in iface %d,%d @%p\n",
-					ep_num, ep->iface, ep->altsetting, ep);
-			goto __exit_unlock;
-		}
+	ep = snd_usb_get_endpoint(chip, ep_num,
+				  alts->desc.bInterfaceNumber,
+				  alts->desc.bAlternateSetting);
+	if (ep) {
+		usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d @%p\n",
+			      ep_num, ep->iface, ep->altsetting, ep);
+		goto __exit_unlock;
 	}
 
 	usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n",
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index d23fa0a8c11b..61487095a766 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -5,6 +5,10 @@
 #define SND_USB_ENDPOINT_TYPE_DATA     0
 #define SND_USB_ENDPOINT_TYPE_SYNC     1
 
+struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip,
+					      int ep_num, int iface,
+					      int altsetting);
+
 struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 					      struct usb_host_interface *alts,
 					      int ep_num, int direction, int type);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 06/41] ALSA: usb-audio: Set and clear sync EP link properly
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (4 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 05/41] ALSA: usb-audio: Add snd_usb_get_endpoint() helper Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 07/41] ALSA: usb-audio: Improve some debug prints Takashi Iwai
                   ` (34 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The sync EP setup isn't cleared at stopping the stream but expected to
be cleared at the next stream start.  This may leave the sync link
setup stale and can spoof wrongly when full duplex streams were
running in the implicit fb sync.  Let's initialize them properly at
start and end of the stream.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 2b11c2c837bf..8800ec627a73 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -238,6 +238,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
 		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
+			ep->sync_slave = NULL;
 			return err;
 		}
 	}
@@ -253,8 +254,10 @@ static void sync_pending_stops(struct snd_usb_substream *subs)
 
 static void stop_endpoints(struct snd_usb_substream *subs)
 {
-	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
+	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
 		snd_usb_endpoint_stop(subs->sync_endpoint);
+		subs->sync_endpoint->sync_slave = NULL;
+	}
 
 	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
 		snd_usb_endpoint_stop(subs->data_endpoint);
@@ -471,26 +474,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	bool implicit_fb;
 	int err;
 
-	/* we need a sync pipe in async OUT or adaptive IN mode */
-	/* check the number of EP, since some devices have broken
-	 * descriptors which fool us.  if it has only one EP,
-	 * assume it as adaptive-out or sync-in.
-	 */
 	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 
-	if ((is_playback && (attr != USB_ENDPOINT_SYNC_ASYNC)) ||
-		(!is_playback && (attr != USB_ENDPOINT_SYNC_ADAPTIVE))) {
-
-		/*
-		 * In these modes the notion of sync_endpoint is irrelevant.
-		 * Reset pointers to avoid using stale data from previously
-		 * used settings, e.g. when configuration and endpoints were
-		 * changed
-		 */
-
-		subs->sync_endpoint = NULL;
-		subs->data_endpoint->sync_master = NULL;
-	}
+	subs->sync_endpoint = NULL;
+	subs->data_endpoint->sync_master = NULL;
 
 	err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr);
 	if (err < 0)
@@ -939,6 +926,11 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 		sync_pending_stops(subs);
 		snd_usb_endpoint_deactivate(subs->sync_endpoint);
 		snd_usb_endpoint_deactivate(subs->data_endpoint);
+		if (subs->data_endpoint) {
+			subs->data_endpoint->sync_master = NULL;
+			subs->data_endpoint = NULL;
+		}
+		subs->sync_endpoint = NULL;
 		snd_usb_unlock_shutdown(subs->stream->chip);
 	}
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 07/41] ALSA: usb-audio: Improve some debug prints
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (5 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 06/41] ALSA: usb-audio: Set and clear sync EP link properly Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 08/41] ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list Takashi Iwai
                   ` (33 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

There are a few rooms for improvements wrt the debug prints:
- The EP debug print is shown only at starting, not at stopping
- The EP debug print contains useless object addresses
- Some helpers show the urb and the EP object addresses, too

This patch addresses those shortcomings.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c |  8 ++++----
 sound/usb/pcm.c      | 11 ++++++++---
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index cf00871fd278..8205a64a734e 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -367,8 +367,8 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
 		if (err < 0)
 			usb_audio_err(ep->chip,
-				"Unable to submit urb #%d: %d (urb %p)\n",
-				ctx->index, err, ctx->urb);
+				      "Unable to submit urb #%d: %d at %s\n",
+				      ctx->index, err, __func__);
 		else
 			set_bit(ctx->index, &ep->active_mask);
 	}
@@ -494,8 +494,8 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 				  alts->desc.bInterfaceNumber,
 				  alts->desc.bAlternateSetting);
 	if (ep) {
-		usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d @%p\n",
-			      ep_num, ep->iface, ep->altsetting, ep);
+		usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d\n",
+			      ep_num, ep->iface, ep->altsetting);
 		goto __exit_unlock;
 	}
 
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 8800ec627a73..8f4fe65d5c37 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -218,7 +218,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->data_endpoint;
 
-		dev_dbg(&subs->dev->dev, "Starting data EP @%p\n", ep);
+		dev_dbg(&subs->dev->dev, "Starting data EP 0x%x\n", ep->ep_num);
 
 		ep->data_subs = subs;
 		err = snd_usb_endpoint_start(ep);
@@ -232,7 +232,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
-		dev_dbg(&subs->dev->dev, "Starting sync EP @%p\n", ep);
+		dev_dbg(&subs->dev->dev, "Starting sync EP 0x%x\n", ep->ep_num);
 
 		ep->sync_slave = subs->data_endpoint;
 		err = snd_usb_endpoint_start(ep);
@@ -255,12 +255,17 @@ static void sync_pending_stops(struct snd_usb_substream *subs)
 static void stop_endpoints(struct snd_usb_substream *subs)
 {
 	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
+		dev_dbg(&subs->dev->dev, "Stopping sync EP 0x%x\n",
+			subs->sync_endpoint->ep_num);
 		snd_usb_endpoint_stop(subs->sync_endpoint);
 		subs->sync_endpoint->sync_slave = NULL;
 	}
 
-	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
+	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
+		dev_dbg(&subs->dev->dev, "Stopping data EP 0x%x\n",
+			subs->data_endpoint->ep_num);
 		snd_usb_endpoint_stop(subs->data_endpoint);
+	}
 }
 
 /* PCM sync_stop callback */
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 08/41] ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (6 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 07/41] ALSA: usb-audio: Improve some debug prints Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 09/41] ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info() Takashi Iwai
                   ` (32 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Instead of parsing and evaluating the sync endpoint and the implicit
feedback mode at each time the audio stream is opened, let's parse it
once at the probe time, as the all needed information can be obtained
statically from the descriptor or from the quirk.

This patch extends audioformat struct to record the sync endpoint,
interface and altsetting as well as the implicit feedback flag, which
are filled at parsing the streams.  Then, set_sync_endpoint() is much
simplified just to follow the already parsed data.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h   |   4 ++
 sound/usb/pcm.c    | 149 +++++++++++++++++++++++++++++++++--------------------
 sound/usb/pcm.h    |   2 +
 sound/usb/stream.c |   2 +
 4 files changed, 100 insertions(+), 57 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 3cc668f98f43..898a283576df 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -22,6 +22,10 @@ struct audioformat {
 	unsigned char attributes;	/* corresponding attributes of cs endpoint */
 	unsigned char endpoint;		/* endpoint */
 	unsigned char ep_attr;		/* endpoint attributes */
+	bool implicit_fb;		/* implicit feedback endpoint */
+	unsigned char sync_ep;		/* sync endpoint number */
+	unsigned char sync_iface;	/* sync EP interface */
+	unsigned char sync_altsetting;	/* sync EP alternate setting */
 	unsigned char datainterval;	/* log_2 of data packet interval */
 	unsigned char protocol;		/* UAC_VERSION_1/2/3 */
 	unsigned int maxpacksize;	/* max. packet size */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 8f4fe65d5c37..fea2764163b4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -349,21 +349,18 @@ static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum,
 /* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
  * applies. Returns 1 if a quirk was found.
  */
-static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
-					 struct usb_device *dev,
-					 struct usb_interface_descriptor *altsd,
-					 unsigned int attr)
+static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
+					 struct audioformat *fmt,
+					 struct usb_interface *iface,
+					 struct usb_host_interface *alts)
 {
-	struct usb_host_interface *alts;
-	struct usb_interface *iface;
+	struct usb_device *dev = chip->dev;
+	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+	unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 	unsigned int ep;
 	unsigned int ifnum;
 
-	/* Implicit feedback sync EPs consumers are always playback EPs */
-	if (subs->direction != SNDRV_PCM_STREAM_PLAYBACK)
-		return 0;
-
-	switch (subs->stream->chip->usb_id) {
+	switch (chip->usb_id) {
 	case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
 	case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
 	case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */
@@ -437,11 +434,13 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
 	    altsd->bInterfaceProtocol == 2 &&
 	    altsd->bNumEndpoints == 1 &&
-	    USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ &&
-	    search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1,
-				      altsd->bAlternateSetting,
-				      &alts, &ep))
-		goto add_sync_ep;
+	    USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) {
+		ifnum = altsd->bInterfaceNumber + 1;
+		if (search_roland_implicit_fb(dev, ifnum,
+					      altsd->bAlternateSetting,
+					      &alts, &ep))
+			goto add_sync_ep;
+	}
 
 	/* No quirk */
 	return 0;
@@ -450,56 +449,59 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 	iface = usb_ifnum_to_if(dev, ifnum);
 
 	if (!iface || iface->num_altsetting < 2)
-		return -EINVAL;
+		return 0;
 
 	alts = &iface->altsetting[1];
 
 add_sync_ep:
-	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
-						   alts, ep, !subs->direction,
-						   SND_USB_ENDPOINT_TYPE_DATA);
-	if (!subs->sync_endpoint)
-		return -EINVAL;
-
-	subs->sync_endpoint->is_implicit_feedback = 1;
-
-	subs->data_endpoint->sync_master = subs->sync_endpoint;
+	fmt->sync_ep = ep;
+	fmt->sync_iface = ifnum;
+	fmt->sync_altsetting = alts->desc.bAlternateSetting;
+	fmt->implicit_fb = 1;
+	dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n",
+		fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
+		fmt->sync_altsetting);
 
 	return 1;
 }
 
-static int set_sync_endpoint(struct snd_usb_substream *subs,
-			     struct audioformat *fmt,
-			     struct usb_device *dev,
-			     struct usb_host_interface *alts,
-			     struct usb_interface_descriptor *altsd)
+int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
+				    struct audioformat *fmt)
 {
-	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int ep, attr;
-	bool implicit_fb;
+	struct usb_device *dev = chip->dev;
+	struct usb_interface *iface;
+	struct usb_host_interface *alts;
+	struct usb_interface_descriptor *altsd;
+	unsigned int ep, attr, sync_attr;
+	bool is_playback;
 	int err;
 
-	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
-
-	subs->sync_endpoint = NULL;
-	subs->data_endpoint->sync_master = NULL;
-
-	err = set_sync_ep_implicit_fb_quirk(subs, dev, altsd, attr);
-	if (err < 0)
-		return err;
-
-	/* endpoint set by quirk */
-	if (err > 0)
+	iface = usb_ifnum_to_if(dev, fmt->iface);
+	if (!iface)
+		return 0;
+	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
+	if (!alts)
 		return 0;
+	altsd = get_iface_desc(alts);
+
+	is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
+	if (is_playback) {
+		err = audioformat_implicit_fb_quirk(chip, fmt, iface, alts);
+		if (err > 0)
+			return 0;
+	}
 
 	if (altsd->bNumEndpoints < 2)
 		return 0;
 
+	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 	if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC ||
 			     attr == USB_ENDPOINT_SYNC_ADAPTIVE)) ||
 	    (!is_playback && attr != USB_ENDPOINT_SYNC_ADAPTIVE))
 		return 0;
 
+	sync_attr = get_endpoint(alts, 1)->bmAttributes;
+
 	/*
 	 * In case of illegal SYNC_NONE for OUT endpoint, we keep going to see
 	 * if we don't find a sync endpoint, as on M-Audio Transit. In case of
@@ -510,7 +512,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	/* ... and check descriptor size before accessing bSynchAddress
 	   because there is a version of the SB Audigy 2 NX firmware lacking
 	   the audio fields in the endpoint descriptors */
-	if ((get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
+	if ((sync_attr & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_ISOC ||
 	    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
 	     get_endpoint(alts, 1)->bSynchAddress != 0)) {
 		dev_err(&dev->dev,
@@ -537,22 +539,57 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 		return -EINVAL;
 	}
 
-	implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
-			== USB_ENDPOINT_USAGE_IMPLICIT_FB;
+	fmt->sync_ep = ep;
+	fmt->sync_iface = altsd->bInterfaceNumber;
+	fmt->sync_altsetting = altsd->bAlternateSetting;
+	if ((sync_attr & USB_ENDPOINT_USAGE_MASK) == USB_ENDPOINT_USAGE_IMPLICIT_FB)
+		fmt->implicit_fb = 1;
+
+	dev_dbg(&dev->dev, "%d:%d: found sync_ep=0x%x, iface=%d, alt=%d, implicit_fb=%d\n",
+		fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
+		fmt->sync_altsetting, fmt->implicit_fb);
+
+	return 0;
+}
+
+static int set_sync_endpoint(struct snd_usb_substream *subs,
+			     struct audioformat *fmt)
+{
+	struct usb_device *dev = subs->dev;
+	struct usb_interface *iface;
+	struct usb_host_interface *alts;
+	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
+	unsigned int ep;
+	int err;
+
+	subs->sync_endpoint = NULL;
+	subs->data_endpoint->sync_master = NULL;
+
+	ep = fmt->sync_ep;
+	if (!ep)
+		return 0;
+
+	iface = usb_ifnum_to_if(dev, fmt->sync_iface);
+	if (!iface)
+		return 0;
+
+	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
+	if (!alts)
+		return 0;
 
 	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
 						   alts, ep, !subs->direction,
-						   implicit_fb ?
-							SND_USB_ENDPOINT_TYPE_DATA :
-							SND_USB_ENDPOINT_TYPE_SYNC);
-
+						   fmt->implicit_fb ?
+						   SND_USB_ENDPOINT_TYPE_DATA :
+						   SND_USB_ENDPOINT_TYPE_SYNC);
 	if (!subs->sync_endpoint) {
-		if (is_playback && attr == USB_ENDPOINT_SYNC_NONE)
+		if (is_playback &&
+		    (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE)
 			return 0;
 		return -EINVAL;
 	}
 
-	subs->sync_endpoint->is_implicit_feedback = implicit_fb;
+	subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb;
 
 	subs->data_endpoint->sync_master = subs->sync_endpoint;
 
@@ -579,7 +616,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 {
 	struct usb_device *dev = subs->dev;
 	struct usb_host_interface *alts;
-	struct usb_interface_descriptor *altsd;
 	struct usb_interface *iface;
 	int err;
 
@@ -589,7 +625,6 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
 	if (WARN_ON(!alts))
 		return -EINVAL;
-	altsd = get_iface_desc(alts);
 
 	if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
 		return 0;
@@ -639,7 +674,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	if (!subs->data_endpoint)
 		return -EINVAL;
 
-	err = set_sync_endpoint(subs, fmt, dev, alts, altsd);
+	err = set_sync_endpoint(subs, fmt);
 	if (err < 0)
 		return err;
 
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index 9833627c1eca..362782c2df5c 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -14,5 +14,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
 		       struct audioformat *fmt);
 void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
 
+int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
+				    struct audioformat *fmt);
 
 #endif /* __USBAUDIO_PCM_H */
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index f17913e0b5b4..7087ee2c8174 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1193,6 +1193,8 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 			continue;
 		}
 
+		snd_usb_audioformat_set_sync_ep(chip, fp);
+
 		dev_dbg(&dev->dev, "%u:%d: add audio endpoint %#x\n", iface_no, altno, fp->endpoint);
 		if (protocol == UAC_VERSION_3)
 			err = snd_usb_add_audio_stream_v3(chip, stream, fp, pd);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 09/41] ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info()
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (7 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 08/41] ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 10/41] ALSA: usb-audio: Add hw constraint for implicit fb sync Takashi Iwai
                   ` (31 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

This is a preliminary work for the upcoming hw-constraint change for
the implicit feedback mode.

Currently snd_usb_autoresume() is called at the end of
setup_hwinfo().  It's a bit confusing; because of this implicit
refcount usage, the caller side needs to call snd_usb_autosuspend()
later in the error path although it's not seen inside the function.
Instead, it's clearer to call both snd_usb_autoresume() and suspend()
in the very same function.

It's only refactoring and no functional changes.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index fea2764163b4..78933b6571d0 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1378,7 +1378,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 			return err;
 	}
 
-	return snd_usb_autoresume(subs->stream->chip);
+	return 0;
 }
 
 static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
@@ -1402,11 +1402,14 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
 	subs->dsd_dop.marker = 1;
 
 	ret = setup_hw_info(runtime, subs);
-	if (ret == 0) {
-		ret = snd_media_stream_init(subs, as->pcm, direction);
-		if (ret)
-			snd_usb_autosuspend(subs->stream->chip);
-	}
+	if (ret < 0)
+		return ret;
+	ret = snd_usb_autoresume(subs->stream->chip);
+	if (ret < 0)
+		return ret;
+	ret = snd_media_stream_init(subs, as->pcm, direction);
+	if (ret < 0)
+		snd_usb_autosuspend(subs->stream->chip);
 	return ret;
 }
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 10/41] ALSA: usb-audio: Add hw constraint for implicit fb sync
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (8 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 09/41] ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info() Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 11/41] ALSA: usb-audio: Simplify hw_params rules Takashi Iwai
                   ` (30 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

In the current code, there is no check at the stream open time whether
the endpoint is being already used by others.  In the normal
operations, this shouldn't happen, but in the case of the implicit
feedback mode, it's a common problem with the full duplex operation,
because the capture stream is always opened by the playback stream as
an implicit sync source.

Although we recently introduced the check of such a conflict of
parameters at the PCM hw_params time, it doesn't give any hint at the
hw_params itself and just gives the error.  This isn't quite
comfortable, and it caused problems on many applications.

This patch attempts to make the parameter handling easier by
introducing the strict hw constraint matching with the counterpart
stream that is being used.  That said, when an implicit feedback
playback stream is running before a capture stream is opened, the
capture stream carries the PCM hw-constraint to allow only the same
sample rate, format, periods and period frames as the running playback
stream.  If not opened or there is no conflict of endpoints, the
behavior remains as same as before.

Note that this kind of "weak link" should work for most cases, but
this is no concrete solution; e.g. if an application changes the hw
params multiple times while another stream is opened, this would lead
to inconsistencies.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     |   9 ++++
 sound/usb/endpoint.c |  72 ++++++++++++++++++-------
 sound/usb/pcm.c      | 148 +++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 175 insertions(+), 54 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 898a283576df..1f61be98a31d 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -114,6 +114,14 @@ struct snd_usb_endpoint {
 					   in a stream */
 	bool is_implicit_feedback;      /* This endpoint is used as implicit feedback */
 
+	/* for hw constraints */
+	unsigned int cur_rate;
+	snd_pcm_format_t cur_format;
+	unsigned int cur_channels;
+	unsigned int cur_period_frames;
+	unsigned int cur_period_bytes;
+	unsigned int cur_buffer_periods;
+
 	spinlock_t lock;
 	struct list_head list;
 };
@@ -144,6 +152,7 @@ struct snd_usb_substream {
 	unsigned int stream_offset_adj;	/* Bytes to drop from beginning of stream (for non-compliant devices) */
 
 	unsigned int running: 1;	/* running status */
+	unsigned int fixed_hw:1;	/* fixed hw constraints due to sync EP */
 
 	unsigned int hwptr_done;	/* processed byte position in the buffer */
 	unsigned int transfer_done;		/* processed frames since last period update */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 8205a64a734e..94490d706013 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -459,6 +459,9 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip,
 	return NULL;
 }
 
+#define ep_type_name(type) \
+	(type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync")
+
 /**
  * snd_usb_add_endpoint: Add an endpoint to an USB audio chip
  *
@@ -500,9 +503,9 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 	}
 
 	usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n",
-		    is_playback ? "playback" : "capture",
-		    type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync",
-		    ep_num);
+		      is_playback ? "playback" : "capture",
+		      ep_type_name(type),
+		      ep_num);
 
 	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
 	if (!ep)
@@ -644,13 +647,14 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
  * Check data endpoint for format differences
  */
 static bool check_ep_params(struct snd_usb_endpoint *ep,
-			      snd_pcm_format_t pcm_format,
-			      unsigned int channels,
-			      unsigned int period_bytes,
-			      unsigned int frames_per_period,
-			      unsigned int periods_per_buffer,
-			      struct audioformat *fmt,
-			      struct snd_usb_endpoint *sync_ep)
+			    snd_pcm_format_t pcm_format,
+			    unsigned int channels,
+			    unsigned int period_bytes,
+			    unsigned int frames_per_period,
+			    unsigned int periods_per_buffer,
+			    unsigned int rate,
+			    struct audioformat *fmt,
+			    struct snd_usb_endpoint *sync_ep)
 {
 	unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
 	unsigned int max_packs_per_period, urbs_per_period, urb_packs;
@@ -660,6 +664,14 @@ static bool check_ep_params(struct snd_usb_endpoint *ep,
 			       usb_pipeout(ep->pipe));
 	bool ret = 1;
 
+	/* matching with the saved parameters? */
+	if (ep->cur_rate == rate &&
+	    ep->cur_format == pcm_format &&
+	    ep->cur_channels == channels &&
+	    ep->cur_period_frames == frames_per_period &&
+	    ep->cur_buffer_periods == periods_per_buffer)
+		return true;
+
 	if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
 		/*
 		 * When operating in DSD DOP mode, the size of a sample frame
@@ -917,7 +929,8 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 	 * as their corresponding capture endpoint.
 	 */
 	if (usb_pipein(ep->pipe) ||
-			snd_usb_endpoint_implicit_feedback_sink(ep)) {
+	    ep->is_implicit_feedback ||
+	    snd_usb_endpoint_implicit_feedback_sink(ep)) {
 
 		urb_packs = packs_per_ms;
 		/*
@@ -1076,12 +1089,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 {
 	int err;
 
+	usb_audio_dbg(ep->chip,
+		      "Setting params for ep %x (type %s, count %d), rate=%d, format=%s, channels=%d, period_bytes=%d, periods=%d\n",
+		      ep->ep_num, ep_type_name(ep->type), ep->use_count,
+		      rate, snd_pcm_format_name(pcm_format), channels,
+		      period_bytes, buffer_periods);
+
 	if (ep->use_count != 0) {
 		bool check = ep->is_implicit_feedback &&
-			check_ep_params(ep, pcm_format,
-					     channels, period_bytes,
-					     period_frames, buffer_periods,
-					     fmt, sync_ep);
+			check_ep_params(ep, pcm_format, channels, period_bytes,
+					period_frames, buffer_periods, rate,
+					fmt, sync_ep);
 
 		if (!check) {
 			usb_audio_warn(ep->chip,
@@ -1134,11 +1152,22 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 		err = -EINVAL;
 	}
 
-	usb_audio_dbg(ep->chip,
-		"Setting params for ep #%x (type %d, %d urbs), ret=%d\n",
-		ep->ep_num, ep->type, ep->nurbs, err);
+	usb_audio_dbg(ep->chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err);
 
-	return err;
+	if (err < 0)
+		return err;
+
+	/* record the current set up in the endpoint (for implicit fb) */
+	spin_lock_irq(&ep->lock);
+	ep->cur_rate = rate;
+	ep->cur_channels = channels;
+	ep->cur_format = pcm_format;
+	ep->cur_period_frames = period_frames;
+	ep->cur_period_bytes = period_bytes;
+	ep->cur_buffer_periods = buffer_periods;
+	spin_unlock_irq(&ep->lock);
+
+	return 0;
 }
 
 /**
@@ -1273,6 +1302,11 @@ void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 
 	deactivate_urbs(ep, true);
 	wait_clear_urbs(ep);
+
+	/* clear the saved hw params */
+	spin_lock_irq(&ep->lock);
+	ep->cur_rate = 0;
+	spin_unlock_irq(&ep->lock);
 }
 
 /**
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 78933b6571d0..6d1f5277cd90 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -81,30 +81,33 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
 /*
  * find a matching audio format
  */
-static struct audioformat *find_format(struct snd_usb_substream *subs)
+static struct audioformat *find_format(struct list_head *fmt_list_head,
+				       snd_pcm_format_t format,
+				       unsigned int rate,
+				       unsigned int channels,
+				       struct snd_usb_substream *subs)
 {
 	struct audioformat *fp;
 	struct audioformat *found = NULL;
 	int cur_attr = 0, attr;
 
-	list_for_each_entry(fp, &subs->fmt_list, list) {
-		if (!(fp->formats & pcm_format_to_bits(subs->pcm_format)))
+	list_for_each_entry(fp, fmt_list_head, list) {
+		if (!(fp->formats & pcm_format_to_bits(format)))
 			continue;
-		if (fp->channels != subs->channels)
+		if (fp->channels != channels)
 			continue;
-		if (subs->cur_rate < fp->rate_min ||
-		    subs->cur_rate > fp->rate_max)
+		if (rate < fp->rate_min || rate > fp->rate_max)
 			continue;
-		if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
+		if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
 			unsigned int i;
 			for (i = 0; i < fp->nr_rates; i++)
-				if (fp->rate_table[i] == subs->cur_rate)
+				if (fp->rate_table[i] == rate)
 					break;
 			if (i >= fp->nr_rates)
 				continue;
 		}
 		attr = fp->ep_attr & USB_ENDPOINT_SYNCTYPE;
-		if (! found) {
+		if (!found) {
 			found = fp;
 			cur_attr = attr;
 			continue;
@@ -114,7 +117,7 @@ static struct audioformat *find_format(struct snd_usb_substream *subs)
 		 * this is a workaround for the case like
 		 * M-audio audiophile USB.
 		 */
-		if (attr != cur_attr) {
+		if (subs && attr != cur_attr) {
 			if ((attr == USB_ENDPOINT_SYNC_ASYNC &&
 			     subs->direction == SNDRV_PCM_STREAM_PLAYBACK) ||
 			    (attr == USB_ENDPOINT_SYNC_ADAPTIVE &&
@@ -138,6 +141,12 @@ static struct audioformat *find_format(struct snd_usb_substream *subs)
 	return found;
 }
 
+static struct audioformat *find_substream_format(struct snd_usb_substream *subs)
+{
+	return find_format(&subs->fmt_list, subs->pcm_format, subs->cur_rate,
+			   subs->channels, subs);
+}
+
 static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
 			 struct usb_host_interface *alts,
 			 struct audioformat *fmt)
@@ -744,7 +753,6 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
  */
 static int configure_sync_endpoint(struct snd_usb_substream *subs)
 {
-	int ret;
 	struct audioformat *fp;
 	struct audioformat *sync_fp = NULL;
 	int cur_score = 0;
@@ -752,16 +760,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
 	struct snd_usb_substream *sync_subs =
 		&subs->stream->substream[subs->direction ^ 1];
 
-	if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA ||
-	    !subs->stream)
-		return snd_usb_endpoint_set_params(subs->sync_endpoint,
-						   subs->pcm_format,
-						   subs->channels,
-						   subs->period_bytes,
-						   0, 0,
-						   subs->cur_rate,
-						   subs->cur_audiofmt,
-						   NULL);
+	if (subs->fixed_hw ||
+	    !subs->sync_endpoint->is_implicit_feedback) {
+		sync_fp = subs->cur_audiofmt;
+		goto configure;
+	}
+
+	sync_fp = find_format(&sync_subs->fmt_list, subs->pcm_format,
+			      subs->cur_rate, subs->channels, NULL);
+	if (sync_fp)
+		goto configure;
 
 	/* Try to find the best matching audioformat. */
 	list_for_each_entry(fp, &sync_subs->fmt_list, list) {
@@ -794,16 +802,16 @@ static int configure_sync_endpoint(struct snd_usb_substream *subs)
 			__func__, subs->period_bytes, sync_period_bytes);
 	}
 
-	ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
-					  subs->pcm_format,
-					  sync_fp->channels,
-					  sync_period_bytes,
-					  0, 0,
-					  subs->cur_rate,
-					  sync_fp,
-					  NULL);
-
-	return ret;
+ configure:
+	return snd_usb_endpoint_set_params(subs->sync_endpoint,
+					   subs->pcm_format,
+					   sync_fp->channels,
+					   sync_period_bytes,
+					   subs->period_frames,
+					   subs->buffer_periods,
+					   subs->cur_rate,
+					   sync_fp,
+					   NULL);
 }
 
 /*
@@ -912,7 +920,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	subs->channels = params_channels(hw_params);
 	subs->cur_rate = params_rate(hw_params);
 
-	fmt = find_format(subs);
+	fmt = find_substream_format(subs);
 	if (!fmt) {
 		dev_dbg(&subs->dev->dev,
 			"cannot set format: format = %#x, rate = %d, channels = %d\n",
@@ -956,12 +964,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 {
 	struct snd_usb_substream *subs = substream->runtime->private_data;
+	struct snd_usb_audio *chip = subs->stream->chip;
 
 	snd_media_stop_pipeline(subs);
 	subs->cur_audiofmt = NULL;
 	subs->cur_rate = 0;
 	subs->period_bytes = 0;
-	if (!snd_usb_lock_shutdown(subs->stream->chip)) {
+	if (!snd_usb_lock_shutdown(chip)) {
 		stop_endpoints(subs);
 		sync_pending_stops(subs);
 		snd_usb_endpoint_deactivate(subs->sync_endpoint);
@@ -971,7 +980,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 			subs->data_endpoint = NULL;
 		}
 		subs->sync_endpoint = NULL;
-		snd_usb_unlock_shutdown(subs->stream->chip);
+		snd_usb_unlock_shutdown(chip);
 	}
 
 	return 0;
@@ -1288,6 +1297,64 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 	return changed;
 }
 
+/* apply PCM hw constraints from the concurrent sync EP */
+static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
+					 struct snd_usb_substream *subs)
+{
+	struct snd_usb_audio *chip = subs->stream->chip;
+	struct snd_usb_endpoint *ep;
+	struct audioformat *fp;
+	int err;
+
+	subs->fixed_hw = 0;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
+		ep = snd_usb_get_endpoint(chip, fp->endpoint, fp->iface,
+					  fp->altsetting);
+		if (ep && ep->cur_rate)
+			goto found;
+		if (!fp->implicit_fb)
+			continue;
+		/* for the implicit fb, check the sync ep as well */
+		ep = snd_usb_get_endpoint(chip, fp->sync_ep, fp->sync_iface,
+					  fp->sync_altsetting);
+		if (ep && ep->cur_rate)
+			goto found;
+	}
+	return 0;
+
+ found:
+	if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate,
+			 ep->cur_channels, NULL)) {
+		usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n",
+			      ep->ep_num);
+		return 0;
+	}
+
+	usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n",
+		      ep->ep_num);
+	usb_audio_dbg(chip, "rate=%d, format=%s, channels=%d, period_size=%d, periods=%d\n",
+		      ep->cur_rate, snd_pcm_format_name(ep->cur_format),
+		      ep->cur_channels, ep->cur_period_frames,
+		      ep->cur_buffer_periods);
+
+	runtime->hw.formats = pcm_format_to_bits(ep->cur_format);
+	runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate;
+	runtime->hw.channels_min = runtime->hw.channels_max =
+		ep->cur_channels;
+	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+	runtime->hw.periods_min = runtime->hw.periods_max =
+		ep->cur_buffer_periods;
+	subs->fixed_hw = 1;
+
+	err = snd_pcm_hw_constraint_minmax(runtime,
+					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+					   ep->cur_period_frames,
+					   ep->cur_period_frames);
+	if (err < 0)
+		return err;
+
+	return 1; /* notify the finding */
+}
 
 /*
  * set up the runtime hardware information.
@@ -1295,11 +1362,20 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 
 static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
 {
+	struct snd_usb_audio *chip = subs->stream->chip;
 	struct audioformat *fp;
 	unsigned int pt, ptmin;
-	int param_period_time_if_needed;
+	int param_period_time_if_needed = -1;
 	int err;
 
+	mutex_lock(&chip->mutex);
+	err = apply_hw_constraint_from_sync(runtime, subs);
+	mutex_unlock(&chip->mutex);
+	if (err < 0)
+		return err;
+	if (err > 0) /* found the matching? */
+		goto add_extra_rules;
+
 	runtime->hw.formats = subs->formats;
 
 	runtime->hw.rate_min = 0x7fffffff;
@@ -1350,6 +1426,8 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 				  -1);
 	if (err < 0)
 		return err;
+
+add_extra_rules:
 	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 				  hw_rule_channels, subs,
 				  SNDRV_PCM_HW_PARAM_FORMAT,
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 11/41] ALSA: usb-audio: Simplify hw_params rules
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (9 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 10/41] ALSA: usb-audio: Add hw constraint for implicit fb sync Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 12/41] ALSA: usb-audio: Drop debug.h Takashi Iwai
                   ` (29 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Several hw_params functions narrows the interval via min/max rule in
the very similar way, so factor out those into a helper function and
use commonly.

No functional changes, just minor code refactoring.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 110 ++++++++++++++++++++------------------------------------
 1 file changed, 38 insertions(+), 72 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 6d1f5277cd90..ecc6bf9b42f0 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1121,6 +1121,36 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
 	return 1;
 }
 
+static int apply_hw_params_minmax(struct snd_interval *it, unsigned int rmin,
+				  unsigned int rmax)
+{
+	int changed;
+
+	if (rmin > rmax) {
+		hwc_debug("  --> get empty\n");
+		it->empty = 1;
+		return -EINVAL;
+	}
+
+	changed = 0;
+	if (it->min < rmin) {
+		it->min = rmin;
+		it->openmin = 0;
+		changed = 1;
+	}
+	if (it->max > rmax) {
+		it->max = rmax;
+		it->openmax = 0;
+		changed = 1;
+	}
+	if (snd_interval_checkempty(it)) {
+		it->empty = 1;
+		return -EINVAL;
+	}
+	hwc_debug("  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
+	return changed;
+}
+
 static int hw_rule_rate(struct snd_pcm_hw_params *params,
 			struct snd_pcm_hw_rule *rule)
 {
@@ -1128,7 +1158,6 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 	struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	unsigned int rmin, rmax, r;
-	int changed;
 	int i;
 
 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
@@ -1151,29 +1180,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 		}
 	}
 
-	if (rmin > rmax) {
-		hwc_debug("  --> get empty\n");
-		it->empty = 1;
-		return -EINVAL;
-	}
-
-	changed = 0;
-	if (it->min < rmin) {
-		it->min = rmin;
-		it->openmin = 0;
-		changed = 1;
-	}
-	if (it->max > rmax) {
-		it->max = rmax;
-		it->openmax = 0;
-		changed = 1;
-	}
-	if (snd_interval_checkempty(it)) {
-		it->empty = 1;
-		return -EINVAL;
-	}
-	hwc_debug("  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
-	return changed;
+	return apply_hw_params_minmax(it, rmin, rmax);
 }
 
 
@@ -1184,48 +1191,18 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 	struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 	unsigned int rmin, rmax;
-	int changed;
 
 	hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
-	changed = 0;
-	rmin = rmax = 0;
+	rmin = UINT_MAX;
+	rmax = 0;
 	list_for_each_entry(fp, &subs->fmt_list, list) {
 		if (!hw_check_valid_format(subs, params, fp))
 			continue;
-		if (changed++) {
-			if (rmin > fp->channels)
-				rmin = fp->channels;
-			if (rmax < fp->channels)
-				rmax = fp->channels;
-		} else {
-			rmin = fp->channels;
-			rmax = fp->channels;
-		}
+		rmin = min(rmin, fp->channels);
+		rmax = max(rmax, fp->channels);
 	}
 
-	if (!changed) {
-		hwc_debug("  --> get empty\n");
-		it->empty = 1;
-		return -EINVAL;
-	}
-
-	changed = 0;
-	if (it->min < rmin) {
-		it->min = rmin;
-		it->openmin = 0;
-		changed = 1;
-	}
-	if (it->max > rmax) {
-		it->max = rmax;
-		it->openmax = 0;
-		changed = 1;
-	}
-	if (snd_interval_checkempty(it)) {
-		it->empty = 1;
-		return -EINVAL;
-	}
-	hwc_debug("  --> (%d, %d) (changed = %d)\n", it->min, it->max, changed);
-	return changed;
+	return apply_hw_params_minmax(it, rmin, rmax);
 }
 
 static int hw_rule_format(struct snd_pcm_hw_params *params,
@@ -1267,7 +1244,6 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 	struct snd_interval *it;
 	unsigned char min_datainterval;
 	unsigned int pmin;
-	int changed;
 
 	it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_TIME);
 	hwc_debug("hw_rule_period_time: (%u,%u)\n", it->min, it->max);
@@ -1283,18 +1259,8 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 		return -EINVAL;
 	}
 	pmin = 125 * (1 << min_datainterval);
-	changed = 0;
-	if (it->min < pmin) {
-		it->min = pmin;
-		it->openmin = 0;
-		changed = 1;
-	}
-	if (snd_interval_checkempty(it)) {
-		it->empty = 1;
-		return -EINVAL;
-	}
-	hwc_debug("  --> (%u,%u) (changed = %d)\n", it->min, it->max, changed);
-	return changed;
+
+	return apply_hw_params_minmax(it, pmin, UINT_MAX);
 }
 
 /* apply PCM hw constraints from the concurrent sync EP */
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 12/41] ALSA: usb-audio: Drop debug.h
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (10 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 11/41] ALSA: usb-audio: Simplify hw_params rules Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 13/41] ALSA: usb-audio: Avoid doubly initialization for implicit fb Takashi Iwai
                   ` (28 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The file debug.h contains a simple macro for debug prints, and it's
used only in two places, the format parser and the hw_params rules.
The former actually should print a more informative message instead,
so the only users are the hw_parmas rules.

This patch moves the contents of debug.h into the hw_params rules
local code and remove the unneeded includes.  Also, the debug print in
the format parser is replaced with the information print with more
useful information, and the raw printk() call is replaced with
pr_debug().

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.c   |  1 -
 sound/usb/debug.h  | 16 ----------------
 sound/usb/format.c |  5 +++--
 sound/usb/pcm.c    | 11 ++++++++++-
 4 files changed, 13 insertions(+), 20 deletions(-)
 delete mode 100644 sound/usb/debug.h

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4457214a3ae6..096dd8e3c64b 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -49,7 +49,6 @@
 #include "quirks.h"
 #include "endpoint.h"
 #include "helper.h"
-#include "debug.h"
 #include "pcm.h"
 #include "format.h"
 #include "power.h"
diff --git a/sound/usb/debug.h b/sound/usb/debug.h
deleted file mode 100644
index 7dd983c35001..000000000000
--- a/sound/usb/debug.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __USBAUDIO_DEBUG_H
-#define __USBAUDIO_DEBUG_H
-
-/*
- * h/w constraints
- */
-
-#ifdef HW_CONST_DEBUG
-#define hwc_debug(fmt, args...) printk(KERN_DEBUG fmt, ##args)
-#else
-#define hwc_debug(fmt, args...) do { } while(0)
-#endif
-
-#endif /* __USBAUDIO_DEBUG_H */
-
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 3348032daa16..7641716f0c6c 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -16,7 +16,6 @@
 #include "card.h"
 #include "quirks.h"
 #include "helper.h"
-#include "debug.h"
 #include "clock.h"
 #include "format.h"
 
@@ -227,7 +226,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
 			fp->nr_rates++;
 		}
 		if (!fp->nr_rates) {
-			hwc_debug("All rates were zero. Skipping format!\n");
+			usb_audio_info(chip,
+				       "%u:%d: All rates were zero\n",
+				       fp->iface, fp->altsetting);
 			return -EINVAL;
 		}
 	} else {
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index ecc6bf9b42f0..d83a6a6ac023 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -17,7 +17,6 @@
 #include "usbaudio.h"
 #include "card.h"
 #include "quirks.h"
-#include "debug.h"
 #include "endpoint.h"
 #include "helper.h"
 #include "pcm.h"
@@ -1061,6 +1060,16 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 	return ret;
 }
 
+/*
+ * h/w constraints
+ */
+
+#ifdef HW_CONST_DEBUG
+#define hwc_debug(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define hwc_debug(fmt, args...) do { } while(0)
+#endif
+
 static const struct snd_pcm_hardware snd_usb_hardware =
 {
 	.info =			SNDRV_PCM_INFO_MMAP |
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 13/41] ALSA: usb-audio: Avoid doubly initialization for implicit fb
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (11 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 12/41] ALSA: usb-audio: Drop debug.h Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase Takashi Iwai
                   ` (27 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The implicit feedback mode initializes both the main data stream and
the sync data stream.  When a sync stream was already opened, this
would result in the doubly initialization and might screw up things.

Add the check of already opened sync streams and skip the unnecessary
initialization.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index d83a6a6ac023..8ae7d2fdba0d 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -601,8 +601,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 
 	subs->data_endpoint->sync_master = subs->sync_endpoint;
 
-	if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
-	    subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) {
+	if (!subs->sync_endpoint->use_count &&
+	    (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
+	     subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) {
 		err = usb_set_interface(subs->dev,
 					subs->sync_endpoint->iface,
 					subs->sync_endpoint->altsetting);
@@ -625,6 +626,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	struct usb_device *dev = subs->dev;
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;
+	struct snd_usb_endpoint *ep;
 	int err;
 
 	iface = usb_ifnum_to_if(dev, fmt->iface);
@@ -637,6 +639,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
 		return 0;
 
+	/* shared EP with implicit fb */
+	if (fmt->implicit_fb && !subs->need_setup_fmt) {
+		ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint,
+					  fmt->iface, fmt->altsetting);
+		if (ep && ep->use_count > 0)
+			goto add_data_ep;
+	}
+
 	/* close the old interface */
 	if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
 		if (!subs->stream->chip->keep_iface) {
@@ -673,6 +683,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 		snd_usb_set_interface_quirk(dev);
 	}
 
+	subs->need_setup_ep = true;
+
+ add_data_ep:
 	subs->interface = fmt->iface;
 	subs->altset_idx = fmt->altset_idx;
 	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
@@ -686,9 +699,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	if (err < 0)
 		return err;
 
-	err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt);
-	if (err < 0)
-		return err;
+	if (subs->need_setup_ep) {
+		err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt);
+		if (err < 0)
+			return err;
+	}
 
 	subs->cur_audiofmt = fmt;
 
@@ -940,10 +955,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	if (ret < 0)
 		goto unlock;
 
-	subs->interface = fmt->iface;
-	subs->altset_idx = fmt->altset_idx;
-	subs->need_setup_ep = true;
-
  unlock:
 	snd_usb_unlock_shutdown(subs->stream->chip);
 	if (ret < 0)
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (12 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 13/41] ALSA: usb-audio: Avoid doubly initialization for implicit fb Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2021-01-03 17:09   ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working František Kučera
  2020-11-23  8:53 ` [PATCH 15/41] ALSA: usb-audio: Drop keep_interface flag again Takashi Iwai
                   ` (26 subsequent siblings)
  40 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Currently snd_usb_endpoint objects are created at first when the
substream is opened and tries to assign the endpoints corresponding to
the matching audioformat.  But since basically the all endpoints have
been already parsed and the information have been obtained, we may
create the endpoint objects statically at the init phase.  It's easier
to manage for the implicit fb case, for example.

This patch changes the endpoint object management and lets the parser
to create the all endpoint objects.

This change shouldn't bring any functional changes.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c | 87 ++++++++++++++++++++--------------------------------
 sound/usb/endpoint.h | 10 +++---
 sound/usb/pcm.c      | 27 ++++++++--------
 sound/usb/stream.c   | 16 ++++++++++
 4 files changed, 67 insertions(+), 73 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 94490d706013..eb459db511f8 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -440,22 +440,19 @@ static void snd_complete_urb(struct urb *urb)
 }
 
 /*
- * Get the existing endpoint object corresponding EP, iface and alt numbers
+ * Get the existing endpoint object corresponding EP
  * Returns NULL if not present.
- * Call inside chip->mutex locking for avoiding the race.
  */
 struct snd_usb_endpoint *
-snd_usb_get_endpoint(struct snd_usb_audio *chip,
-		     int ep_num, int iface, int altsetting)
+snd_usb_get_endpoint(struct snd_usb_audio *chip, int ep_num)
 {
 	struct snd_usb_endpoint *ep;
 
 	list_for_each_entry(ep, &chip->ep_list, list) {
-		if (ep->ep_num == ep_num &&
-		    ep->iface == iface &&
-		    ep->altsetting == altsetting)
+		if (ep->ep_num == ep_num)
 			return ep;
 	}
+
 	return NULL;
 }
 
@@ -466,14 +463,13 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip,
  * snd_usb_add_endpoint: Add an endpoint to an USB audio chip
  *
  * @chip: The chip
- * @alts: The USB host interface
  * @ep_num: The number of the endpoint to use
- * @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE
  * @type: SND_USB_ENDPOINT_TYPE_DATA or SND_USB_ENDPOINT_TYPE_SYNC
  *
  * If the requested endpoint has not been added to the given chip before,
- * a new instance is created. Otherwise, a pointer to the previoulsy
- * created instance is returned. In case of any error, NULL is returned.
+ * a new instance is created.
+ *
+ * Returns zero on success or a negative error code.
  *
  * New endpoints will be added to chip->ep_list and must be freed by
  * calling snd_usb_endpoint_free().
@@ -481,74 +477,59 @@ snd_usb_get_endpoint(struct snd_usb_audio *chip,
  * For SND_USB_ENDPOINT_TYPE_SYNC, the caller needs to guarantee that
  * bNumEndpoints > 1 beforehand.
  */
-struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
-					      struct usb_host_interface *alts,
-					      int ep_num, int direction, int type)
+int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type)
 {
 	struct snd_usb_endpoint *ep;
-	int is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
-
-	if (WARN_ON(!alts))
-		return NULL;
+	bool is_playback;
 
-	mutex_lock(&chip->mutex);
-
-	ep = snd_usb_get_endpoint(chip, ep_num,
-				  alts->desc.bInterfaceNumber,
-				  alts->desc.bAlternateSetting);
-	if (ep) {
-		usb_audio_dbg(ep->chip, "Re-using EP %x in iface %d,%d\n",
-			      ep_num, ep->iface, ep->altsetting);
-		goto __exit_unlock;
-	}
+	ep = snd_usb_get_endpoint(chip, ep_num);
+	if (ep)
+		return 0;
 
-	usb_audio_dbg(chip, "Creating new %s %s endpoint #%x\n",
-		      is_playback ? "playback" : "capture",
+	usb_audio_dbg(chip, "Creating new %s endpoint #%x\n",
 		      ep_type_name(type),
 		      ep_num);
-
 	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
 	if (!ep)
-		goto __exit_unlock;
+		return -ENOMEM;
 
 	ep->chip = chip;
 	spin_lock_init(&ep->lock);
 	ep->type = type;
 	ep->ep_num = ep_num;
-	ep->iface = alts->desc.bInterfaceNumber;
-	ep->altsetting = alts->desc.bAlternateSetting;
 	INIT_LIST_HEAD(&ep->ready_playback_urbs);
-	ep_num &= USB_ENDPOINT_NUMBER_MASK;
 
+	is_playback = ((ep_num & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+	ep_num &= USB_ENDPOINT_NUMBER_MASK;
 	if (is_playback)
 		ep->pipe = usb_sndisocpipe(chip->dev, ep_num);
 	else
 		ep->pipe = usb_rcvisocpipe(chip->dev, ep_num);
 
-	if (type == SND_USB_ENDPOINT_TYPE_SYNC) {
-		if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		    get_endpoint(alts, 1)->bRefresh >= 1 &&
-		    get_endpoint(alts, 1)->bRefresh <= 9)
-			ep->syncinterval = get_endpoint(alts, 1)->bRefresh;
+	list_add_tail(&ep->list, &chip->ep_list);
+	return 0;
+}
+
+/* Set up syncinterval and maxsyncsize for a sync EP */
+void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip,
+				       struct snd_usb_endpoint *ep,
+				       struct usb_host_interface *alts)
+{
+	struct usb_endpoint_descriptor *desc = get_endpoint(alts, 1);
+
+	if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) {
+		if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+		    desc->bRefresh >= 1 && desc->bRefresh <= 9)
+			ep->syncinterval = desc->bRefresh;
 		else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL)
 			ep->syncinterval = 1;
-		else if (get_endpoint(alts, 1)->bInterval >= 1 &&
-			 get_endpoint(alts, 1)->bInterval <= 16)
-			ep->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
+		else if (desc->bInterval >= 1 && desc->bInterval <= 16)
+			ep->syncinterval = desc->bInterval - 1;
 		else
 			ep->syncinterval = 3;
 
-		ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
+		ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize);
 	}
-
-	list_add_tail(&ep->list, &chip->ep_list);
-
-	ep->is_implicit_feedback = 0;
-
-__exit_unlock:
-	mutex_unlock(&chip->mutex);
-
-	return ep;
 }
 
 /*
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 61487095a766..76b6de7de991 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -6,12 +6,9 @@
 #define SND_USB_ENDPOINT_TYPE_SYNC     1
 
 struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip,
-					      int ep_num, int iface,
-					      int altsetting);
+					      int ep_num);
 
-struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
-					      struct usb_host_interface *alts,
-					      int ep_num, int direction, int type);
+int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type);
 
 int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 				snd_pcm_format_t pcm_format,
@@ -34,6 +31,9 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip,
+				       struct snd_usb_endpoint *ep,
+				       struct usb_host_interface *alts);
 
 void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 			     struct snd_usb_endpoint *sender,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 8ae7d2fdba0d..03b1a02bcff4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -585,11 +585,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	if (!alts)
 		return 0;
 
-	subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
-						   alts, ep, !subs->direction,
-						   fmt->implicit_fb ?
-						   SND_USB_ENDPOINT_TYPE_DATA :
-						   SND_USB_ENDPOINT_TYPE_SYNC);
+	subs->sync_endpoint = snd_usb_get_endpoint(subs->stream->chip, ep);
 	if (!subs->sync_endpoint) {
 		if (is_playback &&
 		    (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE)
@@ -597,10 +593,14 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 		return -EINVAL;
 	}
 
+	subs->sync_endpoint->iface = fmt->sync_iface;
+	subs->sync_endpoint->altsetting = fmt->sync_altsetting;
 	subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb;
 
 	subs->data_endpoint->sync_master = subs->sync_endpoint;
 
+	snd_usb_endpoint_set_syncinterval(subs->stream->chip, subs->sync_endpoint, alts);
+
 	if (!subs->sync_endpoint->use_count &&
 	    (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
 	     subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) {
@@ -641,8 +641,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 
 	/* shared EP with implicit fb */
 	if (fmt->implicit_fb && !subs->need_setup_fmt) {
-		ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint,
-					  fmt->iface, fmt->altsetting);
+		ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint);
 		if (ep && ep->use_count > 0)
 			goto add_data_ep;
 	}
@@ -688,12 +687,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
  add_data_ep:
 	subs->interface = fmt->iface;
 	subs->altset_idx = fmt->altset_idx;
-	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
-						   alts, fmt->endpoint, subs->direction,
-						   SND_USB_ENDPOINT_TYPE_DATA);
-
+	subs->data_endpoint = snd_usb_get_endpoint(subs->stream->chip,
+						   fmt->endpoint);
 	if (!subs->data_endpoint)
 		return -EINVAL;
+	subs->data_endpoint->iface = fmt->iface;
+	subs->data_endpoint->altsetting = fmt->altsetting;
 
 	err = set_sync_endpoint(subs, fmt);
 	if (err < 0)
@@ -1294,15 +1293,13 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 
 	subs->fixed_hw = 0;
 	list_for_each_entry(fp, &subs->fmt_list, list) {
-		ep = snd_usb_get_endpoint(chip, fp->endpoint, fp->iface,
-					  fp->altsetting);
+		ep = snd_usb_get_endpoint(chip, fp->endpoint);
 		if (ep && ep->cur_rate)
 			goto found;
 		if (!fp->implicit_fb)
 			continue;
 		/* for the implicit fb, check the sync ep as well */
-		ep = snd_usb_get_endpoint(chip, fp->sync_ep, fp->sync_iface,
-					  fp->sync_altsetting);
+		ep = snd_usb_get_endpoint(chip, fp->sync_ep);
 		if (ep && ep->cur_rate)
 			goto found;
 	}
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 7087ee2c8174..816fd3e5aada 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1206,6 +1206,22 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 			kfree(pd);
 			return err;
 		}
+
+		/* add endpoints */
+		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;
+		}
+
 		/* try to set the interface... */
 		usb_set_interface(chip->dev, iface_no, altno);
 		snd_usb_init_pitch(chip, iface_no, alts, fp);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 15/41] ALSA: usb-audio: Drop keep_interface flag again
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (13 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 16/41] ALSA: usb-audio: Add snd_usb_get_host_interface() helper Takashi Iwai
                   ` (25 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

This behavior turned out to be invalid from the USB spec POV and
shouldn't be applied.  As it's an optional flag that is set only via
an card control element that must be hardly used, let's drop it
again.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/mixer.c    | 46 ----------------------------------------------
 sound/usb/pcm.c      | 17 +++++++----------
 sound/usb/usbaudio.h |  3 ---
 3 files changed, 7 insertions(+), 59 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 81e987eaf063..12b15ed59eaa 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -3454,48 +3454,6 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 	return 0;
 }
 
-static int keep_iface_ctl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
-
-	ucontrol->value.integer.value[0] = mixer->chip->keep_iface;
-	return 0;
-}
-
-static int keep_iface_ctl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
-	bool keep_iface = !!ucontrol->value.integer.value[0];
-
-	if (mixer->chip->keep_iface == keep_iface)
-		return 0;
-	mixer->chip->keep_iface = keep_iface;
-	return 1;
-}
-
-static const struct snd_kcontrol_new keep_iface_ctl = {
-	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
-	.name = "Keep Interface",
-	.info = snd_ctl_boolean_mono_info,
-	.get = keep_iface_ctl_get,
-	.put = keep_iface_ctl_put,
-};
-
-static int create_keep_iface_ctl(struct usb_mixer_interface *mixer)
-{
-	struct snd_kcontrol *kctl = snd_ctl_new1(&keep_iface_ctl, mixer);
-
-	/* need only one control per card */
-	if (snd_ctl_find_id(mixer->chip->card, &kctl->id)) {
-		snd_ctl_free_one(kctl);
-		return 0;
-	}
-
-	return snd_ctl_add(mixer->chip->card, kctl);
-}
-
 int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 			 int ignore_error)
 {
@@ -3548,10 +3506,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 	if (err < 0)
 		goto _error;
 
-	err = create_keep_iface_ctl(mixer);
-	if (err < 0)
-		goto _error;
-
 	err = snd_usb_mixer_apply_create_quirk(mixer);
 	if (err < 0)
 		goto _error;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 03b1a02bcff4..392aa1cba61c 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -648,14 +648,12 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 
 	/* close the old interface */
 	if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
-		if (!subs->stream->chip->keep_iface) {
-			err = usb_set_interface(subs->dev, subs->interface, 0);
-			if (err < 0) {
-				dev_err(&dev->dev,
-					"%d:%d: return to setting 0 failed (%d)\n",
-					fmt->iface, fmt->altsetting, err);
-				return -EIO;
-			}
+		err = usb_set_interface(subs->dev, subs->interface, 0);
+		if (err < 0) {
+			dev_err(&dev->dev,
+				"%d:%d: return to setting 0 failed (%d)\n",
+				fmt->iface, fmt->altsetting, err);
+			return -EIO;
 		}
 		subs->interface = -1;
 		subs->altset_idx = 0;
@@ -1483,8 +1481,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
 
 	snd_media_stop_pipeline(subs);
 
-	if (!as->chip->keep_iface &&
-	    subs->interface >= 0 &&
+	if (subs->interface >= 0 &&
 	    !snd_usb_lock_shutdown(subs->stream->chip)) {
 		usb_set_interface(subs->dev, subs->interface, 0);
 		subs->interface = -1;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 0805b7f21272..aa017a93f7bd 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -53,9 +53,6 @@ struct snd_usb_audio {
 
 	int setup;			/* from the 'device_setup' module param */
 	bool autoclock;			/* from the 'autoclock' module param */
-	bool keep_iface;		/* keep interface/altset after closing
-					 * or parameter change
-					 */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
 	struct media_device *media_dev;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 16/41] ALSA: usb-audio: Add snd_usb_get_host_interface() helper
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (14 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 15/41] ALSA: usb-audio: Drop keep_interface flag again Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 17/41] ALSA: usb-audio: Don't set altsetting before initializing sample rate Takashi Iwai
                   ` (24 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Add a helper function to retrieve the usb_host_interface object from
the given interface and altsetting number pair, which is a commonly
used procedure in the driver code.

No functional changes, just minor code refactoring.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/helper.c | 10 ++++++++++
 sound/usb/helper.h |  3 +++
 sound/usb/pcm.c    | 38 +++++++++++---------------------------
 3 files changed, 24 insertions(+), 27 deletions(-)

diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index cf92d7110773..a4410267bf70 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -121,3 +121,13 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 	return 0;
 }
 
+struct usb_host_interface *
+snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting)
+{
+	struct usb_interface *iface;
+
+	iface = usb_ifnum_to_if(chip->dev, ifnum);
+	if (!iface)
+		return NULL;
+	return usb_altnum_to_altsetting(iface, altsetting);
+}
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index f5b4c6647e4d..e2b51ec96ec6 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -14,6 +14,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 					 struct usb_host_interface *alts);
 
+struct usb_host_interface *
+snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
+
 /*
  * retrieve usb_interface descriptor from the host interface
  * (conditional for compatibility with the older API)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 392aa1cba61c..b0961ebd71f4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -289,20 +289,16 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
 }
 
 /* Check whether the given iface:altsetting points to an implicit fb source */
-static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum,
+static bool search_generic_implicit_fb(struct snd_usb_audio *chip, int ifnum,
 				       unsigned int altsetting,
 				       struct usb_host_interface **altsp,
 				       unsigned int *ep)
 {
-	struct usb_interface *iface;
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct usb_endpoint_descriptor *epd;
 
-	iface = usb_ifnum_to_if(dev, ifnum);
-	if (!iface)
-		return false;
-	alts = usb_altnum_to_altsetting(iface, altsetting);
+	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
 	if (!alts)
 		return false;
 	altsd = get_iface_desc(alts);
@@ -322,20 +318,16 @@ static bool search_generic_implicit_fb(struct usb_device *dev, int ifnum,
 }
 
 /* Like the function above, but specific to Roland with vendor class and hack */
-static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum,
+static bool search_roland_implicit_fb(struct snd_usb_audio *chip, int ifnum,
 				      unsigned int altsetting,
 				      struct usb_host_interface **altsp,
 				      unsigned int *ep)
 {
-	struct usb_interface *iface;
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct usb_endpoint_descriptor *epd;
 
-	iface = usb_ifnum_to_if(dev, ifnum);
-	if (!iface)
-		return false;
-	alts = usb_altnum_to_altsetting(iface, altsetting);
+	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
 	if (!alts)
 		return false;
 	altsd = get_iface_desc(alts);
@@ -359,11 +351,11 @@ static bool search_roland_implicit_fb(struct usb_device *dev, int ifnum,
  */
 static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 					 struct audioformat *fmt,
-					 struct usb_interface *iface,
 					 struct usb_host_interface *alts)
 {
 	struct usb_device *dev = chip->dev;
 	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+	struct usb_interface *iface;
 	unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 	unsigned int ep;
 	unsigned int ifnum;
@@ -431,7 +423,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	    altsd->bInterfaceProtocol == UAC_VERSION_2 &&
 	    altsd->bNumEndpoints == 1) {
 		ifnum = altsd->bInterfaceNumber + 1;
-		if (search_generic_implicit_fb(dev, ifnum,
+		if (search_generic_implicit_fb(chip, ifnum,
 					       altsd->bAlternateSetting,
 					       &alts, &ep))
 			goto add_sync_ep;
@@ -444,7 +436,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	    altsd->bNumEndpoints == 1 &&
 	    USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) {
 		ifnum = altsd->bInterfaceNumber + 1;
-		if (search_roland_implicit_fb(dev, ifnum,
+		if (search_roland_implicit_fb(chip, ifnum,
 					      altsd->bAlternateSetting,
 					      &alts, &ep))
 			goto add_sync_ep;
@@ -477,24 +469,20 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 				    struct audioformat *fmt)
 {
 	struct usb_device *dev = chip->dev;
-	struct usb_interface *iface;
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	unsigned int ep, attr, sync_attr;
 	bool is_playback;
 	int err;
 
-	iface = usb_ifnum_to_if(dev, fmt->iface);
-	if (!iface)
-		return 0;
-	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
+	alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting);
 	if (!alts)
 		return 0;
 	altsd = get_iface_desc(alts);
 
 	is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
 	if (is_playback) {
-		err = audioformat_implicit_fb_quirk(chip, fmt, iface, alts);
+		err = audioformat_implicit_fb_quirk(chip, fmt, alts);
 		if (err > 0)
 			return 0;
 	}
@@ -564,7 +552,6 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 			     struct audioformat *fmt)
 {
 	struct usb_device *dev = subs->dev;
-	struct usb_interface *iface;
 	struct usb_host_interface *alts;
 	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
 	unsigned int ep;
@@ -577,11 +564,8 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	if (!ep)
 		return 0;
 
-	iface = usb_ifnum_to_if(dev, fmt->sync_iface);
-	if (!iface)
-		return 0;
-
-	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
+	alts = snd_usb_get_host_interface(subs->stream->chip, fmt->sync_iface,
+					  fmt->altsetting);
 	if (!alts)
 		return 0;
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 17/41] ALSA: usb-audio: Don't set altsetting before initializing sample rate
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (15 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 16/41] ALSA: usb-audio: Add snd_usb_get_host_interface() helper Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 18/41] ALSA: usb-audio: Pass snd_usb_audio object to quirk functions Takashi Iwai
                   ` (23 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Setting the active altsetting at changing sample rate seems
unrecommended.  The host should deselect the altsetting at first
before that, then select it again.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/stream.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 816fd3e5aada..4501e042a944 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1223,9 +1223,10 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 		}
 
 		/* try to set the interface... */
-		usb_set_interface(chip->dev, iface_no, altno);
+		usb_set_interface(chip->dev, iface_no, 0);
 		snd_usb_init_pitch(chip, iface_no, alts, fp);
 		snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+		usb_set_interface(chip->dev, iface_no, altno);
 	}
 	return 0;
 }
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 18/41] ALSA: usb-audio: Pass snd_usb_audio object to quirk functions
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (16 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 17/41] ALSA: usb-audio: Don't set altsetting before initializing sample rate Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 19/41] ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments Takashi Iwai
                   ` (22 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

A preliminary patch for the later big change.  Just a minor code
refactoring.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/clock.c  |  4 ++--
 sound/usb/pcm.c    | 17 +++++++++--------
 sound/usb/quirks.c | 10 ++++------
 sound/usb/quirks.h |  4 ++--
 4 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index f174230d07d5..3298a654ce96 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -658,9 +658,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	 * interface is active. */
 	if (rate != prev_rate) {
 		usb_set_interface(dev, iface, 0);
-		snd_usb_set_interface_quirk(dev);
+		snd_usb_set_interface_quirk(chip);
 		usb_set_interface(dev, iface, fmt->altsetting);
-		snd_usb_set_interface_quirk(dev);
+		snd_usb_set_interface_quirk(chip);
 	}
 
 validation:
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b0961ebd71f4..2518d4c82ad5 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -553,6 +553,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 {
 	struct usb_device *dev = subs->dev;
 	struct usb_host_interface *alts;
+	struct snd_usb_audio *chip = subs->stream->chip;
 	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
 	unsigned int ep;
 	int err;
@@ -569,7 +570,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 	if (!alts)
 		return 0;
 
-	subs->sync_endpoint = snd_usb_get_endpoint(subs->stream->chip, ep);
+	subs->sync_endpoint = snd_usb_get_endpoint(chip, ep);
 	if (!subs->sync_endpoint) {
 		if (is_playback &&
 		    (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE)
@@ -596,7 +597,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 		dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
 			subs->sync_endpoint->iface,
 			subs->sync_endpoint->altsetting);
-		snd_usb_set_interface_quirk(dev);
+		snd_usb_set_interface_quirk(chip);
 	}
 
 	return 0;
@@ -608,6 +609,7 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
 static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 {
 	struct usb_device *dev = subs->dev;
+	struct snd_usb_audio *chip = subs->stream->chip;
 	struct usb_host_interface *alts;
 	struct usb_interface *iface;
 	struct snd_usb_endpoint *ep;
@@ -625,7 +627,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 
 	/* shared EP with implicit fb */
 	if (fmt->implicit_fb && !subs->need_setup_fmt) {
-		ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint);
+		ep = snd_usb_get_endpoint(chip, fmt->endpoint);
 		if (ep && ep->use_count > 0)
 			goto add_data_ep;
 	}
@@ -648,7 +650,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 
 	/* set interface */
 	if (iface->cur_altsetting != alts) {
-		err = snd_usb_select_mode_quirk(subs, fmt);
+		err = snd_usb_select_mode_quirk(chip, fmt);
 		if (err < 0)
 			return -EIO;
 
@@ -661,7 +663,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 		}
 		dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
 			fmt->iface, fmt->altsetting);
-		snd_usb_set_interface_quirk(dev);
+		snd_usb_set_interface_quirk(chip);
 	}
 
 	subs->need_setup_ep = true;
@@ -669,8 +671,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
  add_data_ep:
 	subs->interface = fmt->iface;
 	subs->altset_idx = fmt->altset_idx;
-	subs->data_endpoint = snd_usb_get_endpoint(subs->stream->chip,
-						   fmt->endpoint);
+	subs->data_endpoint = snd_usb_get_endpoint(chip, fmt->endpoint);
 	if (!subs->data_endpoint)
 		return -EINVAL;
 	subs->data_endpoint->iface = fmt->iface;
@@ -681,7 +682,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 		return err;
 
 	if (subs->need_setup_ep) {
-		err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt);
+		err = snd_usb_init_pitch(chip, fmt->iface, alts, fmt);
 		if (err < 0)
 			return err;
 	}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index c50be2f75f70..bb4c1ae0a4a7 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1553,13 +1553,13 @@ static bool is_itf_usb_dsd_dac(unsigned int id)
 	return false;
 }
 
-int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
+int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
 			      struct audioformat *fmt)
 {
-	struct usb_device *dev = subs->dev;
+	struct usb_device *dev = chip->dev;
 	int err;
 
-	if (is_itf_usb_dsd_dac(subs->stream->chip->usb_id)) {
+	if (is_itf_usb_dsd_dac(chip->usb_id)) {
 		/* First switch to alt set 0, otherwise the mode switch cmd
 		 * will not be accepted by the DAC
 		 */
@@ -1622,10 +1622,8 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 		ep->tenor_fb_quirk = 1;
 }
 
-void snd_usb_set_interface_quirk(struct usb_device *dev)
+void snd_usb_set_interface_quirk(struct snd_usb_audio *chip)
 {
-	struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev);
-
 	if (!chip)
 		return;
 	/*
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index c76cf24a640a..011f22cf2bf6 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -35,12 +35,12 @@ int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
 
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
-void snd_usb_set_interface_quirk(struct usb_device *dev);
+void snd_usb_set_interface_quirk(struct snd_usb_audio *chip);
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
 			   __u8 request, __u8 requesttype, __u16 value,
 			   __u16 index, void *data, __u16 size);
 
-int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
+int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
 			      struct audioformat *fmt);
 
 u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 19/41] ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (17 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 18/41] ALSA: usb-audio: Pass snd_usb_audio object to quirk functions Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 20/41] ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments Takashi Iwai
                   ` (21 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

A preliminary change for the later big changes.  This is a minor code
refactoring to drop the unnecessary arguments that can be retrieved in
a different way.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/clock.c  | 29 +++++++++++++++--------------
 sound/usb/clock.h  |  3 +--
 sound/usb/pcm.c    |  2 --
 sound/usb/quirks.c |  2 +-
 sound/usb/stream.c |  2 +-
 5 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 3298a654ce96..f25da11fce3a 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -481,15 +481,18 @@ int snd_usb_clock_find_source(struct snd_usb_audio *chip,
 	}
 }
 
-static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
-			      struct usb_host_interface *alts,
+static int set_sample_rate_v1(struct snd_usb_audio *chip,
 			      struct audioformat *fmt, int rate)
 {
 	struct usb_device *dev = chip->dev;
+	struct usb_host_interface *alts;
 	unsigned int ep;
 	unsigned char data[3];
 	int err, crate;
 
+	alts = snd_usb_get_host_interface(chip, fmt->iface, fmt->altsetting);
+	if (!alts)
+		return -EINVAL;
 	if (get_iface_desc(alts)->bNumEndpoints < 1)
 		return -EINVAL;
 	ep = get_endpoint(alts, 0)->bEndpointAddress;
@@ -507,7 +510,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 			      data, sizeof(data));
 	if (err < 0) {
 		dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
-			iface, fmt->altsetting, rate, ep);
+			fmt->iface, fmt->altsetting, rate, ep);
 		return err;
 	}
 
@@ -525,7 +528,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 			      data, sizeof(data));
 	if (err < 0) {
 		dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
-			iface, fmt->altsetting, ep);
+			fmt->iface, fmt->altsetting, ep);
 		chip->sample_rate_read_error++;
 		return 0; /* some devices don't support reading */
 	}
@@ -607,8 +610,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
 	return get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock);
 }
 
-static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-				struct usb_host_interface *alts,
+static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
 				struct audioformat *fmt, int rate)
 {
 	struct usb_device *dev = chip->dev;
@@ -632,7 +634,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 			return clock;
 	}
 
-	prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock);
+	prev_rate = get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock);
 	if (prev_rate == rate)
 		goto validation;
 
@@ -640,7 +642,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	if (cur_rate < 0) {
 		usb_audio_err(chip,
 			      "%d:%d: cannot set freq %d (v2/v3): err %d\n",
-			      iface, fmt->altsetting, rate, cur_rate);
+			      fmt->iface, fmt->altsetting, rate, cur_rate);
 		return cur_rate;
 	}
 
@@ -657,9 +659,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	/* Some devices doesn't respond to sample rate changes while the
 	 * interface is active. */
 	if (rate != prev_rate) {
-		usb_set_interface(dev, iface, 0);
+		usb_set_interface(dev, fmt->iface, 0);
 		snd_usb_set_interface_quirk(chip);
-		usb_set_interface(dev, iface, fmt->altsetting);
+		usb_set_interface(dev, fmt->iface, fmt->altsetting);
 		snd_usb_set_interface_quirk(chip);
 	}
 
@@ -670,14 +672,13 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
 	return 0;
 }
 
-int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
-			     struct usb_host_interface *alts,
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip,
 			     struct audioformat *fmt, int rate)
 {
 	switch (fmt->protocol) {
 	case UAC_VERSION_1:
 	default:
-		return set_sample_rate_v1(chip, iface, alts, fmt, rate);
+		return set_sample_rate_v1(chip, fmt, rate);
 
 	case UAC_VERSION_3:
 		if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
@@ -688,7 +689,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 		}
 		fallthrough;
 	case UAC_VERSION_2:
-		return set_sample_rate_v2v3(chip, iface, alts, fmt, rate);
+		return set_sample_rate_v2v3(chip, fmt, rate);
 	}
 }
 
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index 97597f5a3c18..8d406ed294d6 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -2,8 +2,7 @@
 #ifndef __USBAUDIO_CLOCK_H
 #define __USBAUDIO_CLOCK_H
 
-int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
-			     struct usb_host_interface *alts,
+int snd_usb_init_sample_rate(struct snd_usb_audio *chip,
 			     struct audioformat *fmt, int rate);
 
 int snd_usb_clock_find_source(struct snd_usb_audio *chip,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 2518d4c82ad5..38b461bdca86 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1017,8 +1017,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 		iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
 		alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
 		ret = snd_usb_init_sample_rate(subs->stream->chip,
-					       subs->cur_audiofmt->iface,
-					       alts,
 					       subs->cur_audiofmt,
 					       subs->cur_rate);
 		if (ret < 0)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index bb4c1ae0a4a7..018c6f241ffb 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -178,7 +178,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
 	usb_set_interface(chip->dev, fp->iface, 0);
 	snd_usb_init_pitch(chip, fp->iface, alts, fp);
-	snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
+	snd_usb_init_sample_rate(chip, fp, fp->rate_max);
 	return 0;
 
  error:
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 4501e042a944..23e881985123 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1225,7 +1225,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 		/* try to set the interface... */
 		usb_set_interface(chip->dev, iface_no, 0);
 		snd_usb_init_pitch(chip, iface_no, alts, fp);
-		snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+		snd_usb_init_sample_rate(chip, fp, fp->rate_max);
 		usb_set_interface(chip->dev, iface_no, altno);
 	}
 	return 0;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 20/41] ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (18 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 19/41] ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 21/41] ALSA: usb-audio: Stop both endpoints properly at error Takashi Iwai
                   ` (20 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

A preliminary change for the later big changes.  This is a minor code
refactoring to drop the unnecessary arguments that can be retrieved in
a different way.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c    | 23 +++++++++--------------
 sound/usb/pcm.h    |  3 +--
 sound/usb/quirks.c |  2 +-
 sound/usb/stream.c |  2 +-
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 38b461bdca86..0998be109af3 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -146,8 +146,7 @@ static struct audioformat *find_substream_format(struct snd_usb_substream *subs)
 			   subs->channels, subs);
 }
 
-static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
-			 struct usb_host_interface *alts,
+static int init_pitch_v1(struct snd_usb_audio *chip,
 			 struct audioformat *fmt)
 {
 	struct usb_device *dev = chip->dev;
@@ -155,9 +154,7 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
 	unsigned char data[1];
 	int err;
 
-	if (get_iface_desc(alts)->bNumEndpoints < 1)
-		return -EINVAL;
-	ep = get_endpoint(alts, 0)->bEndpointAddress;
+	ep = fmt->endpoint;
 
 	data[0] = 1;
 	err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
@@ -166,15 +163,14 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
 			      data, sizeof(data));
 	if (err < 0) {
 		usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n",
-			      iface, ep);
+			      fmt->iface, ep);
 		return err;
 	}
 
 	return 0;
 }
 
-static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
-			 struct usb_host_interface *alts,
+static int init_pitch_v2(struct snd_usb_audio *chip,
 			 struct audioformat *fmt)
 {
 	struct usb_device *dev = chip->dev;
@@ -188,7 +184,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
 			      data, sizeof(data));
 	if (err < 0) {
 		usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n",
-			      iface, fmt->altsetting);
+			      fmt->iface, fmt->altsetting);
 		return err;
 	}
 
@@ -198,8 +194,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
 /*
  * initialize the pitch control and sample rate
  */
-int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
-		       struct usb_host_interface *alts,
+int snd_usb_init_pitch(struct snd_usb_audio *chip,
 		       struct audioformat *fmt)
 {
 	/* if endpoint doesn't have pitch control, bail out */
@@ -209,10 +204,10 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
 	switch (fmt->protocol) {
 	case UAC_VERSION_1:
 	default:
-		return init_pitch_v1(chip, iface, alts, fmt);
+		return init_pitch_v1(chip, fmt);
 
 	case UAC_VERSION_2:
-		return init_pitch_v2(chip, iface, alts, fmt);
+		return init_pitch_v2(chip, fmt);
 	}
 }
 
@@ -682,7 +677,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 		return err;
 
 	if (subs->need_setup_ep) {
-		err = snd_usb_init_pitch(chip, fmt->iface, alts, fmt);
+		err = snd_usb_init_pitch(chip, fmt);
 		if (err < 0)
 			return err;
 	}
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index 362782c2df5c..a4f784225abc 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -9,8 +9,7 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
 int snd_usb_pcm_suspend(struct snd_usb_stream *as);
 int snd_usb_pcm_resume(struct snd_usb_stream *as);
 
-int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
-		       struct usb_host_interface *alts,
+int snd_usb_init_pitch(struct snd_usb_audio *chip,
 		       struct audioformat *fmt);
 void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
 
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 018c6f241ffb..013ab93fb640 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -177,7 +177,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 	if (fp->maxpacksize == 0)
 		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
 	usb_set_interface(chip->dev, fp->iface, 0);
-	snd_usb_init_pitch(chip, fp->iface, alts, fp);
+	snd_usb_init_pitch(chip, fp);
 	snd_usb_init_sample_rate(chip, fp, fp->rate_max);
 	return 0;
 
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 23e881985123..7f58c7625cd4 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1224,7 +1224,7 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 
 		/* try to set the interface... */
 		usb_set_interface(chip->dev, iface_no, 0);
-		snd_usb_init_pitch(chip, iface_no, alts, fp);
+		snd_usb_init_pitch(chip, fp);
 		snd_usb_init_sample_rate(chip, fp, fp->rate_max);
 		usb_set_interface(chip->dev, iface_no, altno);
 	}
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 21/41] ALSA: usb-audio: Stop both endpoints properly at error
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (19 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 20/41] ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 22/41] ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback() Takashi Iwai
                   ` (19 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

start_endpoints() may leave the data endpoint running if an error
happens at starting the sync endpoint.  We should stop both streams
properly, instead.

While we're at it, move the debug prints into the endpoint.c that is a
more suitable place.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c |  6 ++++++
 sound/usb/pcm.c      | 39 +++++++++++++++++----------------------
 2 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index eb459db511f8..0cc7e9c01263 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1172,6 +1172,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (atomic_read(&ep->chip->shutdown))
 		return -EBADFD;
 
+	usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n",
+		      ep_type_name(ep->type), ep->ep_num, ep->use_count);
+
 	/* already running? */
 	if (++ep->use_count != 1)
 		return 0;
@@ -1254,6 +1257,9 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 	if (!ep)
 		return;
 
+	usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (count %d)\n",
+		      ep_type_name(ep->type), ep->ep_num, ep->use_count);
+
 	if (snd_BUG_ON(ep->use_count == 0))
 		return;
 
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0998be109af3..c4e39aa92a84 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -211,6 +211,17 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip,
 	}
 }
 
+static void stop_endpoints(struct snd_usb_substream *subs)
+{
+	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
+		snd_usb_endpoint_stop(subs->sync_endpoint);
+		subs->sync_endpoint->sync_slave = NULL;
+	}
+
+	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
+		snd_usb_endpoint_stop(subs->data_endpoint);
+}
+
 static int start_endpoints(struct snd_usb_substream *subs)
 {
 	int err;
@@ -221,13 +232,11 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->data_endpoint;
 
-		dev_dbg(&subs->dev->dev, "Starting data EP 0x%x\n", ep->ep_num);
-
 		ep->data_subs = subs;
 		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
-			return err;
+			goto error;
 		}
 	}
 
@@ -235,18 +244,20 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
-		dev_dbg(&subs->dev->dev, "Starting sync EP 0x%x\n", ep->ep_num);
-
 		ep->sync_slave = subs->data_endpoint;
 		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
 			ep->sync_slave = NULL;
-			return err;
+			goto error;
 		}
 	}
 
 	return 0;
+
+ error:
+	stop_endpoints(subs);
+	return err;
 }
 
 static void sync_pending_stops(struct snd_usb_substream *subs)
@@ -255,22 +266,6 @@ static void sync_pending_stops(struct snd_usb_substream *subs)
 	snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
 }
 
-static void stop_endpoints(struct snd_usb_substream *subs)
-{
-	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
-		dev_dbg(&subs->dev->dev, "Stopping sync EP 0x%x\n",
-			subs->sync_endpoint->ep_num);
-		snd_usb_endpoint_stop(subs->sync_endpoint);
-		subs->sync_endpoint->sync_slave = NULL;
-	}
-
-	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
-		dev_dbg(&subs->dev->dev, "Stopping data EP 0x%x\n",
-			subs->data_endpoint->ep_num);
-		snd_usb_endpoint_stop(subs->data_endpoint);
-	}
-}
-
 /* PCM sync_stop callback */
 static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
 {
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 22/41] ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback()
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (20 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 21/41] ALSA: usb-audio: Stop both endpoints properly at error Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 23/41] ALSA: usb-audio: Always set up the parameters after resume Takashi Iwai
                   ` (18 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The prepare_data_urb and retire_data_urb fields of the endpoint object
are set dynamically at PCM trigger start/stop.  Those are evaluated in
the endpoint handler, but there can be a race, especially if two
different PCM substreams are handling the same endpoint for the
implicit feedback case.  Also, the data_subs field of the endpoint is
set and accessed dynamically, too, which has the same risk.

As a slight improvement for the concurrency, this patch introduces the
function to set the callbacks and the data in a shot with the memory
barrier.  In the reader side, it's also fetched with the memory
barrier.

There is still a room of race if prepare and retire callbacks are set
during executing the URB completion.  But such an inconsistency may
happen only for the implicit fb source, i.e. it's only about the
capture stream.  And luckily, the capture stream never sets the
prepare callback, hence the problem doesn't happen practically.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c | 60 +++++++++++++++++++++++++++++++++++-----------------
 sound/usb/endpoint.h |  7 ++++++
 sound/usb/pcm.c      | 33 ++++++++++++++++-------------
 3 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 0cc7e9c01263..7012fdafc3d8 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -169,11 +169,20 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
 	return ret;
 }
 
+static void call_retire_callback(struct snd_usb_endpoint *ep,
+				 struct urb *urb)
+{
+	struct snd_usb_substream *data_subs;
+
+	data_subs = READ_ONCE(ep->data_subs);
+	if (data_subs && ep->retire_data_urb)
+		ep->retire_data_urb(data_subs, urb);
+}
+
 static void retire_outbound_urb(struct snd_usb_endpoint *ep,
 				struct snd_urb_ctx *urb_ctx)
 {
-	if (ep->retire_data_urb)
-		ep->retire_data_urb(ep->data_subs, urb_ctx->urb);
+	call_retire_callback(ep, urb_ctx->urb);
 }
 
 static void retire_inbound_urb(struct snd_usb_endpoint *ep,
@@ -189,8 +198,7 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
 	if (ep->sync_slave)
 		snd_usb_handle_sync_urb(ep->sync_slave, ep, urb);
 
-	if (ep->retire_data_urb)
-		ep->retire_data_urb(ep->data_subs, urb);
+	call_retire_callback(ep, urb);
 }
 
 static void prepare_silent_urb(struct snd_usb_endpoint *ep,
@@ -244,17 +252,17 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
 {
 	struct urb *urb = ctx->urb;
 	unsigned char *cp = urb->transfer_buffer;
+	struct snd_usb_substream *data_subs;
 
 	urb->dev = ep->chip->dev; /* we need to set this at each time */
 
 	switch (ep->type) {
 	case SND_USB_ENDPOINT_TYPE_DATA:
-		if (ep->prepare_data_urb) {
-			ep->prepare_data_urb(ep->data_subs, urb);
-		} else {
-			/* no data provider, so send silence */
+		data_subs = READ_ONCE(ep->data_subs);
+		if (data_subs && ep->prepare_data_urb)
+			ep->prepare_data_urb(data_subs, urb);
+		else /* no data provider, so send silence */
 			prepare_silent_urb(ep, ctx);
-		}
 		break;
 
 	case SND_USB_ENDPOINT_TYPE_SYNC:
@@ -381,7 +389,7 @@ static void snd_complete_urb(struct urb *urb)
 {
 	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_endpoint *ep = ctx->ep;
-	struct snd_pcm_substream *substream;
+	struct snd_usb_substream *data_subs;
 	unsigned long flags;
 	int err;
 
@@ -430,10 +438,9 @@ static void snd_complete_urb(struct urb *urb)
 		return;
 
 	usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
-	if (ep->data_subs && ep->data_subs->pcm_substream) {
-		substream = ep->data_subs->pcm_substream;
-		snd_pcm_stop_xrun(substream);
-	}
+	data_subs = READ_ONCE(ep->data_subs);
+	if (data_subs && data_subs->pcm_substream)
+		snd_pcm_stop_xrun(data_subs->pcm_substream);
 
 exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);
@@ -532,6 +539,24 @@ void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip,
 	}
 }
 
+/*
+ * Set data endpoint callbacks and the assigned data stream
+ *
+ * Called at PCM trigger and cleanups.
+ * Pass NULL to deactivate each callback.
+ */
+void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
+				   void (*prepare)(struct snd_usb_substream *subs,
+						   struct urb *urb),
+				   void (*retire)(struct snd_usb_substream *subs,
+						  struct urb *urb),
+				   struct snd_usb_substream *data_subs)
+{
+	ep->prepare_data_urb = prepare;
+	ep->retire_data_urb = retire;
+	WRITE_ONCE(ep->data_subs, data_subs);
+}
+
 /*
  *  wait until all urbs are processed.
  */
@@ -554,10 +579,8 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
 			alive, ep->ep_num);
 	clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
-	ep->data_subs = NULL;
 	ep->sync_slave = NULL;
-	ep->retire_data_urb = NULL;
-	ep->prepare_data_urb = NULL;
+	snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
 
 	return 0;
 }
@@ -607,8 +630,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 	int i;
 
 	/* route incoming urbs to nirvana */
-	ep->retire_data_urb = NULL;
-	ep->prepare_data_urb = NULL;
+	snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
 
 	/* stop urbs */
 	deactivate_urbs(ep, force);
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 76b6de7de991..e2fddb3dcf7a 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -20,6 +20,13 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 				struct audioformat *fmt,
 				struct snd_usb_endpoint *sync_ep);
 
+void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
+				   void (*prepare)(struct snd_usb_substream *subs,
+						   struct urb *urb),
+				   void (*retire)(struct snd_usb_substream *subs,
+						  struct urb *urb),
+				   struct snd_usb_substream *data_subs);
+
 int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index c4e39aa92a84..32237623de96 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -232,7 +232,6 @@ static int start_endpoints(struct snd_usb_substream *subs)
 	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
 		struct snd_usb_endpoint *ep = subs->data_endpoint;
 
-		ep->data_subs = subs;
 		err = snd_usb_endpoint_start(ep);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
@@ -1830,18 +1829,24 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
 		subs->trigger_tstamp_pending_update = true;
 		fallthrough;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
-		subs->data_endpoint->retire_data_urb = retire_playback_urb;
+		snd_usb_endpoint_set_callback(subs->data_endpoint,
+					      prepare_playback_urb,
+					      retire_playback_urb,
+					      subs);
 		subs->running = 1;
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
+		snd_usb_endpoint_set_callback(subs->data_endpoint,
+					      NULL, NULL, NULL);
 		subs->running = 0;
 		return 0;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->data_endpoint->prepare_data_urb = NULL;
 		/* keep retire_data_urb for delay calculation */
-		subs->data_endpoint->retire_data_urb = retire_playback_urb;
+		snd_usb_endpoint_set_callback(subs->data_endpoint,
+					      NULL,
+					      retire_playback_urb,
+					      subs);
 		subs->running = 0;
 		return 0;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -1867,23 +1872,21 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 		err = start_endpoints(subs);
 		if (err < 0)
 			return err;
-
-		subs->data_endpoint->retire_data_urb = retire_capture_urb;
+		fallthrough;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		snd_usb_endpoint_set_callback(subs->data_endpoint,
+					      NULL, retire_capture_urb,
+					      subs);
 		subs->running = 1;
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
-		subs->data_endpoint->retire_data_urb = NULL;
-		subs->running = 0;
-		return 0;
+		fallthrough;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->data_endpoint->retire_data_urb = NULL;
+		snd_usb_endpoint_set_callback(subs->data_endpoint,
+					      NULL, NULL, NULL);
 		subs->running = 0;
 		return 0;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->data_endpoint->retire_data_urb = retire_capture_urb;
-		subs->running = 1;
-		return 0;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 		if (subs->stream->chip->setup_fmt_after_resume_quirk) {
 			stop_endpoints(subs);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 23/41] ALSA: usb-audio: Always set up the parameters after resume
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (21 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 22/41] ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback() Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 24/41] ALSA: usb-audio: Fix EP matching for continuous rates Takashi Iwai
                   ` (17 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The commit 92adc96f8eec ("ALSA: usb-audio: set the interface format
after resume on Dell WD19") introduced the workaround for the broken
setup after the resume specifically on a Dell dock model.  However,
the full setup should have been performed after the resume on all
devices, as we can't guarantee the same state.  So this patch removes
the conditional check and applies the workaround always.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c          | 20 ++++++--------------
 sound/usb/quirks-table.h |  8 --------
 sound/usb/quirks.c       | 11 -----------
 sound/usb/usbaudio.h     |  1 -
 4 files changed, 6 insertions(+), 34 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 32237623de96..ac6385a4eb70 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1835,6 +1835,9 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
 					      subs);
 		subs->running = 1;
 		return 0;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		subs->need_setup_fmt = true;
+		fallthrough;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
 		snd_usb_endpoint_set_callback(subs->data_endpoint,
@@ -1849,13 +1852,6 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
 					      subs);
 		subs->running = 0;
 		return 0;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		if (subs->stream->chip->setup_fmt_after_resume_quirk) {
-			stop_endpoints(subs);
-			subs->need_setup_fmt = true;
-			return 0;
-		}
-		break;
 	}
 
 	return -EINVAL;
@@ -1879,6 +1875,9 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 					      subs);
 		subs->running = 1;
 		return 0;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		subs->need_setup_fmt = true;
+		fallthrough;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
 		fallthrough;
@@ -1887,13 +1886,6 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 					      NULL, NULL, NULL);
 		subs->running = 0;
 		return 0;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		if (subs->stream->chip->setup_fmt_after_resume_quirk) {
-			stop_endpoints(subs);
-			subs->need_setup_fmt = true;
-			return 0;
-		}
-		break;
 	}
 
 	return -EINVAL;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 3c1697f6b60c..85b99c6d3c61 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3256,14 +3256,6 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
 		}
 	}
 },
-/* Dell WD19 Dock */
-{
-	USB_DEVICE(0x0bda, 0x402e),
-	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
-		.ifnum = QUIRK_ANY_INTERFACE,
-		.type = QUIRK_SETUP_FMT_AFTER_RESUME
-	}
-},
 /* MOTU Microbook II */
 {
 	USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 013ab93fb640..7e7f258011ff 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -508,16 +508,6 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
 	return snd_usb_create_mixer(chip, quirk->ifnum, 0);
 }
 
-
-static int setup_fmt_after_resume_quirk(struct snd_usb_audio *chip,
-				       struct usb_interface *iface,
-				       struct usb_driver *driver,
-				       const struct snd_usb_audio_quirk *quirk)
-{
-	chip->setup_fmt_after_resume_quirk = 1;
-	return 1;	/* Continue with creating streams and mixer */
-}
-
 static int setup_disable_autosuspend(struct snd_usb_audio *chip,
 				       struct usb_interface *iface,
 				       struct usb_driver *driver,
@@ -565,7 +555,6 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
 		[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
 		[QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
-		[QUIRK_SETUP_FMT_AFTER_RESUME] = setup_fmt_after_resume_quirk,
 		[QUIRK_SETUP_DISABLE_AUTOSUSPEND] = setup_disable_autosuspend,
 	};
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index aa017a93f7bd..cc338e8e2597 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -35,7 +35,6 @@ struct snd_usb_audio {
 	wait_queue_head_t shutdown_wait;
 	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
 	unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
-	unsigned int setup_fmt_after_resume_quirk:1; /* setup the format to interface after resume */
 	unsigned int need_delayed_register:1; /* warn for delayed registration */
 	int num_interfaces;
 	int num_suspended_intf;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 24/41] ALSA: usb-audio: Fix EP matching for continuous rates
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (22 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 23/41] ALSA: usb-audio: Always set up the parameters after resume Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 25/41] ALSA: usb-audio: Refactor endpoint management Takashi Iwai
                   ` (16 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The function to evaluate the match of the parameters with an EP
assumes only the discrete rate tables and doesn't handle the
continuous rates properly.

This patch fixes match_endpoint_audioformats() to handle the
continuous rates.  Also the almost useless debug prints there are
dropped.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 37 +++++++++++++------------------------
 1 file changed, 13 insertions(+), 24 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index ac6385a4eb70..45a692512d27 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -695,41 +695,30 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
 				       struct audioformat *match, int rate,
 				       snd_pcm_format_t pcm_format)
 {
-	int i;
-	int score = 0;
+	int i, score;
 
-	if (fp->channels < 1) {
-		dev_dbg(&subs->dev->dev,
-			"%s: (fmt @%p) no channels\n", __func__, fp);
+	if (fp->channels < 1)
 		return 0;
-	}
 
-	if (!(fp->formats & pcm_format_to_bits(pcm_format))) {
-		dev_dbg(&subs->dev->dev,
-			"%s: (fmt @%p) no match for format %d\n", __func__,
-			fp, pcm_format);
+	if (!(fp->formats & pcm_format_to_bits(pcm_format)))
 		return 0;
-	}
 
-	for (i = 0; i < fp->nr_rates; i++) {
-		if (fp->rate_table[i] == rate) {
-			score++;
-			break;
+	if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
+		if (rate < fp->rate_min || rate > fp->rate_max)
+			return 0;
+	} else {
+		for (i = 0; i < fp->nr_rates; i++) {
+			if (fp->rate_table[i] == rate)
+				break;
 		}
-	}
-	if (!score) {
-		dev_dbg(&subs->dev->dev,
-			"%s: (fmt @%p) no match for rate %d\n", __func__,
-			fp, rate);
-		return 0;
+		if (i >= fp->nr_rates)
+			return 0;
 	}
 
+	score = 1;
 	if (fp->channels == match->channels)
 		score++;
 
-	dev_dbg(&subs->dev->dev,
-		"%s: (fmt @%p) score %d\n", __func__, fp, score);
-
 	return score;
 }
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 25/41] ALSA: usb-audio: Refactor endpoint management
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (23 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 24/41] ALSA: usb-audio: Fix EP matching for continuous rates Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 26/41] ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer Takashi Iwai
                   ` (15 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

This is an intensive surgery for the endpoint and stream management
for achieving more robust and clean code.

The goals of this patch are:
- More clear endpoint resource changes
- The interface altsetting control in a single place
Below are brief description of the whole changes.

First off, most of the endpoint operations are moved into endpoint.c,
so that the snd_usb_endpoint object is only referred in other places.
The endpoint object is acquired and released via the new functions
snd_usb_endpoint_open() and snd_usb_endpoint_close() that are called
at PCM hw_params and hw_free callbacks, respectively.  Those are
ref-counted and EPs can manage the multiple opens.

The open callback receives the audioformat and hw_params arguments,
and those are used for initializing the EP parameters; especially the
endpoint, interface and altset numbers are read from there, as well as
the PCM parameters like the format, rate and channels.  Those are
stored in snd_usb_endpoint object.  If it's the secondary open, the
function checks whether the given parameters are compatible with the
already opened EP setup, too.

The coupling with a sync EP (including an implicit feedback sync) is
done by the sole snd_usb_endpoint_set_sync() call.

The configuration of each endpoint is done in a single shot via
snd_usb_endpoint_configure() call.  This is the place where most of
PCM configurations are done.  A few flags and special handling in the
snd_usb_substream are dropped along with this change.

A significant difference wrt the configuration from the previous code
is the order of USB host interface setups.  Now the interface is
always disabled at beginning and (re-)enabled at the last step of
snd_usb_endpoint_configure(), in order to be compliant with the
standard UAC2/3.  For UAC1, the interface is set before the parameter
setups since there seem devices that require it (e.g. Yamaha THR10),
just like how it was done in the previous driver code.

The start/stop are almost same as before, also single-shots.  The URB
callbacks need to be set via snd_usb_endpoint_set_callback() like the
previous code at the trigger phase, too.

Finally, the flag for the re-setup is set at the device suspend
through the full EP list, instead of PCM trigger.  This catches the
overlooked cases where the PCM hasn't been running yet but the device
needs the full setup after resume.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.c     |   8 +-
 sound/usb/card.h     |  11 +-
 sound/usb/clock.c    |  13 +-
 sound/usb/endpoint.c | 662 ++++++++++++++++++++++++++-------------------------
 sound/usb/endpoint.h |  40 ++--
 sound/usb/pcm.c      | 616 +++++++++++++++++++----------------------------
 6 files changed, 616 insertions(+), 734 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 096dd8e3c64b..58958afcec93 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -980,6 +980,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct snd_usb_stream *as;
+	struct snd_usb_endpoint *ep;
 	struct usb_mixer_interface *mixer;
 	struct list_head *p;
 
@@ -987,11 +988,10 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 		return 0;
 
 	if (!chip->num_suspended_intf++) {
-		list_for_each_entry(as, &chip->pcm_list, list) {
+		list_for_each_entry(as, &chip->pcm_list, list)
 			snd_usb_pcm_suspend(as);
-			as->substream[0].need_setup_ep =
-				as->substream[1].need_setup_ep = true;
-		}
+		list_for_each_entry(ep, &chip->ep_list, list)
+			snd_usb_endpoint_suspend(ep);
 		list_for_each(p, &chip->midi_list)
 			snd_usbmidi_suspend(p);
 		list_for_each_entry(mixer, &chip->mixer_list, list)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 1f61be98a31d..66a249ae138f 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -26,6 +26,7 @@ struct audioformat {
 	unsigned char sync_ep;		/* sync endpoint number */
 	unsigned char sync_iface;	/* sync EP interface */
 	unsigned char sync_altsetting;	/* sync EP alternate setting */
+	unsigned char sync_ep_idx;	/* sync EP array index */
 	unsigned char datainterval;	/* log_2 of data packet interval */
 	unsigned char protocol;		/* UAC_VERSION_1/2/3 */
 	unsigned int maxpacksize;	/* max. packet size */
@@ -58,6 +59,7 @@ struct snd_urb_ctx {
 struct snd_usb_endpoint {
 	struct snd_usb_audio *chip;
 
+	int opened;		/* open refcount; protect with chip->mutex */
 	int use_count;
 	int ep_num;		/* the referenced endpoint number */
 	int type;		/* SND_USB_ENDPOINT_TYPE_* */
@@ -110,14 +112,18 @@ struct snd_usb_endpoint {
 	unsigned char silence_value;
 	unsigned int stride;
 	int iface, altsetting;
+	unsigned char ep_idx;		/* endpoint array index */
 	int skip_packets;		/* quirks for devices to ignore the first n packets
 					   in a stream */
-	bool is_implicit_feedback;      /* This endpoint is used as implicit feedback */
+	bool implicit_fb_sync;		/* syncs with implicit feedback */
+	bool need_setup;		/* (re-)need for configure? */
 
 	/* for hw constraints */
+	struct audioformat *cur_audiofmt;
 	unsigned int cur_rate;
 	snd_pcm_format_t cur_format;
 	unsigned int cur_channels;
+	unsigned int cur_frame_bytes;
 	unsigned int cur_period_frames;
 	unsigned int cur_period_bytes;
 	unsigned int cur_buffer_periods;
@@ -152,7 +158,6 @@ struct snd_usb_substream {
 	unsigned int stream_offset_adj;	/* Bytes to drop from beginning of stream (for non-compliant devices) */
 
 	unsigned int running: 1;	/* running status */
-	unsigned int fixed_hw:1;	/* fixed hw constraints due to sync EP */
 
 	unsigned int hwptr_done;	/* processed byte position in the buffer */
 	unsigned int transfer_done;		/* processed frames since last period update */
@@ -163,8 +168,6 @@ struct snd_usb_substream {
 	struct snd_usb_endpoint *data_endpoint;
 	struct snd_usb_endpoint *sync_endpoint;
 	unsigned long flags;
-	bool need_setup_ep;		/* (re)configure EP at prepare? */
-	bool need_setup_fmt;		/* (re)configure fmt after resume? */
 	unsigned int speed;		/* USB_SPEED_XXX */
 
 	u64 formats;			/* format bitmasks (all or'ed) */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index f25da11fce3a..b869a711afbf 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -613,7 +613,6 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
 static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
 				struct audioformat *fmt, int rate)
 {
-	struct usb_device *dev = chip->dev;
 	int cur_rate, prev_rate;
 	int clock;
 
@@ -656,15 +655,6 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
 		return -ENXIO;
 	}
 
-	/* Some devices doesn't respond to sample rate changes while the
-	 * interface is active. */
-	if (rate != prev_rate) {
-		usb_set_interface(dev, fmt->iface, 0);
-		snd_usb_set_interface_quirk(chip);
-		usb_set_interface(dev, fmt->iface, fmt->altsetting);
-		snd_usb_set_interface_quirk(chip);
-	}
-
 validation:
 	/* validate clock after rate change */
 	if (!uac_clock_source_is_valid(chip, fmt, clock))
@@ -675,6 +665,9 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
 int snd_usb_init_sample_rate(struct snd_usb_audio *chip,
 			     struct audioformat *fmt, int rate)
 {
+	usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n",
+		      fmt->iface, fmt->altsetting, rate, fmt->clock);
+
 	switch (fmt->protocol) {
 	case UAC_VERSION_1:
 	default:
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7012fdafc3d8..eee74313603e 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -18,6 +18,7 @@
 #include "card.h"
 #include "endpoint.h"
 #include "pcm.h"
+#include "clock.h"
 #include "quirks.h"
 
 #define EP_FLAG_RUNNING		1
@@ -116,10 +117,7 @@ static const char *usb_error_string(int err)
  */
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
 {
-	return  ep->sync_master &&
-		ep->sync_master->type == SND_USB_ENDPOINT_TYPE_DATA &&
-		ep->type == SND_USB_ENDPOINT_TYPE_DATA &&
-		usb_pipeout(ep->pipe);
+	return  ep->implicit_fb_sync && usb_pipeout(ep->pipe);
 }
 
 /*
@@ -185,18 +183,24 @@ static void retire_outbound_urb(struct snd_usb_endpoint *ep,
 	call_retire_callback(ep, urb_ctx->urb);
 }
 
+static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
+				    struct snd_usb_endpoint *sender,
+				    const struct urb *urb);
+
 static void retire_inbound_urb(struct snd_usb_endpoint *ep,
 			       struct snd_urb_ctx *urb_ctx)
 {
 	struct urb *urb = urb_ctx->urb;
+	struct snd_usb_endpoint *sync_slave;
 
 	if (unlikely(ep->skip_packets > 0)) {
 		ep->skip_packets--;
 		return;
 	}
 
-	if (ep->sync_slave)
-		snd_usb_handle_sync_urb(ep->sync_slave, ep, urb);
+	sync_slave = READ_ONCE(ep->sync_slave);
+	if (sync_slave)
+		snd_usb_handle_sync_urb(sync_slave, ep, urb);
 
 	call_retire_callback(ep, urb);
 }
@@ -518,25 +522,155 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type)
 }
 
 /* Set up syncinterval and maxsyncsize for a sync EP */
-void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip,
-				       struct snd_usb_endpoint *ep,
-				       struct usb_host_interface *alts)
+static void endpoint_set_syncinterval(struct snd_usb_audio *chip,
+				      struct snd_usb_endpoint *ep)
 {
-	struct usb_endpoint_descriptor *desc = get_endpoint(alts, 1);
-
-	if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC) {
-		if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		    desc->bRefresh >= 1 && desc->bRefresh <= 9)
-			ep->syncinterval = desc->bRefresh;
-		else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL)
-			ep->syncinterval = 1;
-		else if (desc->bInterval >= 1 && desc->bInterval <= 16)
-			ep->syncinterval = desc->bInterval - 1;
-		else
-			ep->syncinterval = 3;
+	struct usb_host_interface *alts;
+	struct usb_endpoint_descriptor *desc;
+
+	alts = snd_usb_get_host_interface(chip, ep->iface, ep->altsetting);
+	if (!alts)
+		return;
+
+	desc = get_endpoint(alts, ep->ep_idx);
+	if (desc->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+	    desc->bRefresh >= 1 && desc->bRefresh <= 9)
+		ep->syncinterval = desc->bRefresh;
+	else if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL)
+		ep->syncinterval = 1;
+	else if (desc->bInterval >= 1 && desc->bInterval <= 16)
+		ep->syncinterval = desc->bInterval - 1;
+	else
+		ep->syncinterval = 3;
+
+	ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize);
+}
+
+static bool endpoint_compatible(struct snd_usb_endpoint *ep,
+				const struct audioformat *fp,
+				const struct snd_pcm_hw_params *params)
+{
+	if (!ep->opened)
+		return false;
+	if (ep->cur_audiofmt != fp)
+		return false;
+	if (ep->cur_rate != params_rate(params) ||
+	    ep->cur_format != params_format(params) ||
+	    ep->cur_period_frames != params_period_size(params) ||
+	    ep->cur_buffer_periods != params_periods(params))
+		return false;
+	return true;
+}
+
+/*
+ * Check whether the given fp and hw params are compatbile with the current
+ * setup of the target EP for implicit feedback sync
+ */
+bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
+				 struct snd_usb_endpoint *ep,
+				 const struct audioformat *fp,
+				 const struct snd_pcm_hw_params *params)
+{
+	bool ret;
+
+	mutex_lock(&chip->mutex);
+	ret = endpoint_compatible(ep, fp, params);
+	mutex_unlock(&chip->mutex);
+	return ret;
+}
+
+/*
+ * snd_usb_endpoint_open: Open the endpoint
+ *
+ * Called from hw_params to assign the endpoint to the substream.
+ * It's reference-counted, and only the first opener is allowed to set up
+ * arbitrary parameters.  The later opener must be compatible with the
+ * former opened parameters.
+ * The endpoint needs to be closed via snd_usb_endpoint_close() later.
+ *
+ * Note that this function doesn't configure the endpoint.  The substream
+ * needs to set it up later via snd_usb_endpoint_configure().
+ */
+struct snd_usb_endpoint *
+snd_usb_endpoint_open(struct snd_usb_audio *chip,
+		      struct audioformat *fp,
+		      const struct snd_pcm_hw_params *params,
+		      bool is_sync_ep)
+{
+	struct snd_usb_endpoint *ep;
+	int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;
 
-		ep->syncmaxsize = le16_to_cpu(desc->wMaxPacketSize);
+	mutex_lock(&chip->mutex);
+	ep = snd_usb_get_endpoint(chip, ep_num);
+	if (!ep) {
+		usb_audio_err(chip, "Cannot find EP 0x%x to open\n", ep_num);
+		goto unlock;
 	}
+
+	if (!ep->opened) {
+		if (is_sync_ep) {
+			ep->iface = fp->sync_iface;
+			ep->altsetting = fp->sync_altsetting;
+			ep->ep_idx = fp->sync_ep_idx;
+		} else {
+			ep->iface = fp->iface;
+			ep->altsetting = fp->altsetting;
+			ep->ep_idx = 0;
+		}
+		usb_audio_dbg(chip, "Open EP 0x%x, iface=%d:%d, idx=%d\n",
+			      ep_num, ep->iface, ep->altsetting, ep->ep_idx);
+
+		ep->cur_audiofmt = fp;
+		ep->cur_channels = fp->channels;
+		ep->cur_rate = params_rate(params);
+		ep->cur_format = params_format(params);
+		ep->cur_frame_bytes = snd_pcm_format_physical_width(ep->cur_format) *
+			ep->cur_channels / 8;
+		ep->cur_period_frames = params_period_size(params);
+		ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes;
+		ep->cur_buffer_periods = params_periods(params);
+
+		if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
+			endpoint_set_syncinterval(chip, ep);
+
+		ep->implicit_fb_sync = fp->implicit_fb;
+		ep->need_setup = true;
+
+		usb_audio_dbg(chip, "  channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
+			      ep->cur_channels, ep->cur_rate,
+			      snd_pcm_format_name(ep->cur_format),
+			      ep->cur_period_bytes, ep->cur_buffer_periods,
+			      ep->implicit_fb_sync);
+
+	} else {
+		if (!endpoint_compatible(ep, fp, params)) {
+			usb_audio_err(chip, "Incompatible EP setup for 0x%x\n",
+				      ep_num);
+			ep = NULL;
+			goto unlock;
+		}
+
+		usb_audio_dbg(chip, "Reopened EP 0x%x (count %d)\n",
+			      ep_num, ep->opened);
+	}
+
+	ep->opened++;
+
+ unlock:
+	mutex_unlock(&chip->mutex);
+	return ep;
+}
+
+/*
+ * snd_usb_endpoint_set_sync: Link data and sync endpoints
+ *
+ * Pass NULL to sync_ep to unlink again
+ */
+void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip,
+			       struct snd_usb_endpoint *data_ep,
+			       struct snd_usb_endpoint *sync_ep)
+{
+	data_ep->sync_master = sync_ep;
 }
 
 /*
@@ -557,6 +691,54 @@ void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
 	WRITE_ONCE(ep->data_subs, data_subs);
 }
 
+static int endpoint_set_interface(struct snd_usb_audio *chip,
+				  struct snd_usb_endpoint *ep,
+				  bool set)
+{
+	int altset = set ? ep->altsetting : 0;
+	int err;
+
+	usb_audio_dbg(chip, "Setting usb interface %d:%d for EP 0x%x\n",
+		      ep->iface, altset, ep->ep_num);
+	err = usb_set_interface(chip->dev, ep->iface, altset);
+	if (err < 0) {
+		usb_audio_err(chip, "%d:%d: usb_set_interface failed (%d)\n",
+			      ep->iface, altset, err);
+		return err;
+	}
+
+	snd_usb_set_interface_quirk(chip);
+	return 0;
+}
+
+/*
+ * snd_usb_endpoint_close: Close the endpoint
+ *
+ * Unreference the already opened endpoint via snd_usb_endpoint_open().
+ */
+void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+			    struct snd_usb_endpoint *ep)
+{
+	mutex_lock(&chip->mutex);
+	usb_audio_dbg(chip, "Closing EP 0x%x (count %d)\n",
+		      ep->ep_num, ep->opened);
+	if (!--ep->opened) {
+		endpoint_set_interface(chip, ep, false);
+		ep->iface = -1;
+		ep->altsetting = 0;
+		ep->cur_audiofmt = NULL;
+		ep->cur_rate = 0;
+		usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
+	}
+	mutex_unlock(&chip->mutex);
+}
+
+/* Prepare for suspening EP, called from the main suspend handler */
+void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep)
+{
+	ep->need_setup = true;
+}
+
 /*
  *  wait until all urbs are processed.
  */
@@ -646,219 +828,36 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 	ep->nurbs = 0;
 }
 
-/*
- * Check data endpoint for format differences
- */
-static bool check_ep_params(struct snd_usb_endpoint *ep,
-			    snd_pcm_format_t pcm_format,
-			    unsigned int channels,
-			    unsigned int period_bytes,
-			    unsigned int frames_per_period,
-			    unsigned int periods_per_buffer,
-			    unsigned int rate,
-			    struct audioformat *fmt,
-			    struct snd_usb_endpoint *sync_ep)
-{
-	unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
-	unsigned int max_packs_per_period, urbs_per_period, urb_packs;
-	unsigned int max_urbs;
-	int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
-	int tx_length_quirk = (ep->chip->tx_length_quirk &&
-			       usb_pipeout(ep->pipe));
-	bool ret = 1;
-
-	/* matching with the saved parameters? */
-	if (ep->cur_rate == rate &&
-	    ep->cur_format == pcm_format &&
-	    ep->cur_channels == channels &&
-	    ep->cur_period_frames == frames_per_period &&
-	    ep->cur_buffer_periods == periods_per_buffer)
-		return true;
-
-	if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
-		/*
-		 * When operating in DSD DOP mode, the size of a sample frame
-		 * in hardware differs from the actual physical format width
-		 * because we need to make room for the DOP markers.
-		 */
-		frame_bits += channels << 3;
-	}
-
-	ret = ret && (ep->datainterval == fmt->datainterval);
-	ret = ret && (ep->stride == frame_bits >> 3);
-
-	switch (pcm_format) {
-	case SNDRV_PCM_FORMAT_U8:
-		ret = ret && (ep->silence_value == 0x80);
-		break;
-	case SNDRV_PCM_FORMAT_DSD_U8:
-	case SNDRV_PCM_FORMAT_DSD_U16_LE:
-	case SNDRV_PCM_FORMAT_DSD_U32_LE:
-	case SNDRV_PCM_FORMAT_DSD_U16_BE:
-	case SNDRV_PCM_FORMAT_DSD_U32_BE:
-		ret = ret && (ep->silence_value == 0x69);
-		break;
-	default:
-		ret = ret && (ep->silence_value == 0);
-	}
-
-	/* assume max. frequency is 50% higher than nominal */
-	ret = ret && (ep->freqmax == ep->freqn + (ep->freqn >> 1));
-	/* Round up freqmax to nearest integer in order to calculate maximum
-	 * packet size, which must represent a whole number of frames.
-	 * This is accomplished by adding 0x0.ffff before converting the
-	 * Q16.16 format into integer.
-	 * In order to accurately calculate the maximum packet size when
-	 * the data interval is more than 1 (i.e. ep->datainterval > 0),
-	 * multiply by the data interval prior to rounding. For instance,
-	 * a freqmax of 41 kHz will result in a max packet size of 6 (5.125)
-	 * frames with a data interval of 1, but 11 (10.25) frames with a
-	 * data interval of 2.
-	 * (ep->freqmax << ep->datainterval overflows at 8.192 MHz for the
-	 * maximum datainterval value of 3, at USB full speed, higher for
-	 * USB high speed, noting that ep->freqmax is in units of
-	 * frames per packet in Q16.16 format.)
-	 */
-	maxsize = (((ep->freqmax << ep->datainterval) + 0xffff) >> 16) *
-			 (frame_bits >> 3);
-	if (tx_length_quirk)
-		maxsize += sizeof(__le32); /* Space for length descriptor */
-	/* but wMaxPacketSize might reduce this */
-	if (ep->maxpacksize && ep->maxpacksize < maxsize) {
-		/* whatever fits into a max. size packet */
-		unsigned int data_maxsize = maxsize = ep->maxpacksize;
-
-		if (tx_length_quirk)
-			/* Need to remove the length descriptor to calc freq */
-			data_maxsize -= sizeof(__le32);
-		ret = ret && (ep->freqmax == (data_maxsize / (frame_bits >> 3))
-				<< (16 - ep->datainterval));
-	}
-
-	if (ep->fill_max)
-		ret = ret && (ep->curpacksize == ep->maxpacksize);
-	else
-		ret = ret && (ep->curpacksize == maxsize);
-
-	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
-		packs_per_ms = 8 >> ep->datainterval;
-		max_packs_per_urb = MAX_PACKS_HS;
-	} else {
-		packs_per_ms = 1;
-		max_packs_per_urb = MAX_PACKS;
-	}
-	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
-		max_packs_per_urb = min(max_packs_per_urb,
-					1U << sync_ep->syncinterval);
-	max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
-
-	/*
-	 * Capture endpoints need to use small URBs because there's no way
-	 * to tell in advance where the next period will end, and we don't
-	 * want the next URB to complete much after the period ends.
-	 *
-	 * Playback endpoints with implicit sync much use the same parameters
-	 * as their corresponding capture endpoint.
-	 */
-	if (usb_pipein(ep->pipe) ||
-			snd_usb_endpoint_implicit_feedback_sink(ep)) {
-
-		urb_packs = packs_per_ms;
-		/*
-		 * Wireless devices can poll at a max rate of once per 4ms.
-		 * For dataintervals less than 5, increase the packet count to
-		 * allow the host controller to use bursting to fill in the
-		 * gaps.
-		 */
-		if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) {
-			int interval = ep->datainterval;
-
-			while (interval < 5) {
-				urb_packs <<= 1;
-				++interval;
-			}
-		}
-		/* make capture URBs <= 1 ms and smaller than a period */
-		urb_packs = min(max_packs_per_urb, urb_packs);
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-			urb_packs >>= 1;
-		ret = ret && (ep->nurbs == MAX_URBS);
-
-	/*
-	 * Playback endpoints without implicit sync are adjusted so that
-	 * a period fits as evenly as possible in the smallest number of
-	 * URBs.  The total number of URBs is adjusted to the size of the
-	 * ALSA buffer, subject to the MAX_URBS and MAX_QUEUE limits.
-	 */
-	} else {
-		/* determine how small a packet can be */
-		minsize = (ep->freqn >> (16 - ep->datainterval)) *
-				(frame_bits >> 3);
-		/* with sync from device, assume it can be 12% lower */
-		if (sync_ep)
-			minsize -= minsize >> 3;
-		minsize = max(minsize, 1u);
-
-		/* how many packets will contain an entire ALSA period? */
-		max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
-
-		/* how many URBs will contain a period? */
-		urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
-				max_packs_per_urb);
-		/* how many packets are needed in each URB? */
-		urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
-
-		/* limit the number of frames in a single URB */
-		ret = ret && (ep->max_urb_frames ==
-			DIV_ROUND_UP(frames_per_period, urbs_per_period));
-
-		/* try to use enough URBs to contain an entire ALSA buffer */
-		max_urbs = min((unsigned) MAX_URBS,
-				MAX_QUEUE * packs_per_ms / urb_packs);
-		ret = ret && (ep->nurbs == min(max_urbs,
-				urbs_per_period * periods_per_buffer));
-	}
-
-	ret = ret && (ep->datainterval == fmt->datainterval);
-	ret = ret && (ep->maxpacksize == fmt->maxpacksize);
-	ret = ret &&
-		(ep->fill_max == !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX));
-
-	return ret;
-}
-
 /*
  * configure a data endpoint
  */
-static int data_ep_set_params(struct snd_usb_endpoint *ep,
-			      snd_pcm_format_t pcm_format,
-			      unsigned int channels,
-			      unsigned int period_bytes,
-			      unsigned int frames_per_period,
-			      unsigned int periods_per_buffer,
-			      struct audioformat *fmt,
-			      struct snd_usb_endpoint *sync_ep)
+static int data_ep_set_params(struct snd_usb_endpoint *ep)
 {
+	struct snd_usb_audio *chip = ep->chip;
 	unsigned int maxsize, minsize, packs_per_ms, max_packs_per_urb;
 	unsigned int max_packs_per_period, urbs_per_period, urb_packs;
 	unsigned int max_urbs, i;
-	int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
-	int tx_length_quirk = (ep->chip->tx_length_quirk &&
+	const struct audioformat *fmt = ep->cur_audiofmt;
+	int frame_bits = ep->cur_frame_bytes * 8;
+	int tx_length_quirk = (chip->tx_length_quirk &&
 			       usb_pipeout(ep->pipe));
 
-	if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
+	usb_audio_dbg(chip, "Setting params for data EP 0x%x, pipe 0x%x\n",
+		      ep->ep_num, ep->pipe);
+
+	if (ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
 		/*
 		 * When operating in DSD DOP mode, the size of a sample frame
 		 * in hardware differs from the actual physical format width
 		 * because we need to make room for the DOP markers.
 		 */
-		frame_bits += channels << 3;
+		frame_bits += ep->cur_channels << 3;
 	}
 
 	ep->datainterval = fmt->datainterval;
 	ep->stride = frame_bits >> 3;
 
-	switch (pcm_format) {
+	switch (ep->cur_format) {
 	case SNDRV_PCM_FORMAT_U8:
 		ep->silence_value = 0x80;
 		break;
@@ -911,16 +910,16 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 	else
 		ep->curpacksize = maxsize;
 
-	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL) {
+	if (snd_usb_get_speed(chip->dev) != USB_SPEED_FULL) {
 		packs_per_ms = 8 >> ep->datainterval;
 		max_packs_per_urb = MAX_PACKS_HS;
 	} else {
 		packs_per_ms = 1;
 		max_packs_per_urb = MAX_PACKS;
 	}
-	if (sync_ep && !snd_usb_endpoint_implicit_feedback_sink(ep))
+	if (ep->sync_master && !ep->implicit_fb_sync)
 		max_packs_per_urb = min(max_packs_per_urb,
-					1U << sync_ep->syncinterval);
+					1U << ep->sync_master->syncinterval);
 	max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
 
 	/*
@@ -931,9 +930,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 	 * Playback endpoints with implicit sync much use the same parameters
 	 * as their corresponding capture endpoint.
 	 */
-	if (usb_pipein(ep->pipe) ||
-	    ep->is_implicit_feedback ||
-	    snd_usb_endpoint_implicit_feedback_sink(ep)) {
+	if (usb_pipein(ep->pipe) || ep->implicit_fb_sync) {
 
 		urb_packs = packs_per_ms;
 		/*
@@ -942,7 +939,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		 * allow the host controller to use bursting to fill in the
 		 * gaps.
 		 */
-		if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_WIRELESS) {
+		if (snd_usb_get_speed(chip->dev) == USB_SPEED_WIRELESS) {
 			int interval = ep->datainterval;
 			while (interval < 5) {
 				urb_packs <<= 1;
@@ -951,7 +948,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		}
 		/* make capture URBs <= 1 ms and smaller than a period */
 		urb_packs = min(max_packs_per_urb, urb_packs);
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+		while (urb_packs > 1 && urb_packs * maxsize >= ep->cur_period_bytes)
 			urb_packs >>= 1;
 		ep->nurbs = MAX_URBS;
 
@@ -966,12 +963,12 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		minsize = (ep->freqn >> (16 - ep->datainterval)) *
 				(frame_bits >> 3);
 		/* with sync from device, assume it can be 12% lower */
-		if (sync_ep)
+		if (ep->sync_master)
 			minsize -= minsize >> 3;
 		minsize = max(minsize, 1u);
 
 		/* how many packets will contain an entire ALSA period? */
-		max_packs_per_period = DIV_ROUND_UP(period_bytes, minsize);
+		max_packs_per_period = DIV_ROUND_UP(ep->cur_period_bytes, minsize);
 
 		/* how many URBs will contain a period? */
 		urbs_per_period = DIV_ROUND_UP(max_packs_per_period,
@@ -980,13 +977,13 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 		urb_packs = DIV_ROUND_UP(max_packs_per_period, urbs_per_period);
 
 		/* limit the number of frames in a single URB */
-		ep->max_urb_frames = DIV_ROUND_UP(frames_per_period,
-					urbs_per_period);
+		ep->max_urb_frames = DIV_ROUND_UP(ep->cur_period_frames,
+						  urbs_per_period);
 
 		/* try to use enough URBs to contain an entire ALSA buffer */
 		max_urbs = min((unsigned) MAX_URBS,
 				MAX_QUEUE * packs_per_ms / urb_packs);
-		ep->nurbs = min(max_urbs, urbs_per_period * periods_per_buffer);
+		ep->nurbs = min(max_urbs, urbs_per_period * ep->cur_buffer_periods);
 	}
 
 	/* allocate and initialize data urbs */
@@ -1004,7 +1001,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
 			goto out_of_memory;
 
 		u->urb->transfer_buffer =
-			usb_alloc_coherent(ep->chip->dev, u->buffer_size,
+			usb_alloc_coherent(chip->dev, u->buffer_size,
 					   GFP_KERNEL, &u->urb->transfer_dma);
 		if (!u->urb->transfer_buffer)
 			goto out_of_memory;
@@ -1028,9 +1025,13 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
  */
 static int sync_ep_set_params(struct snd_usb_endpoint *ep)
 {
+	struct snd_usb_audio *chip = ep->chip;
 	int i;
 
-	ep->syncbuf = usb_alloc_coherent(ep->chip->dev, SYNC_URBS * 4,
+	usb_audio_dbg(chip, "Setting params for sync EP 0x%x, pipe 0x%x\n",
+		      ep->ep_num, ep->pipe);
+
+	ep->syncbuf = usb_alloc_coherent(chip->dev, SYNC_URBS * 4,
 					 GFP_KERNEL, &ep->sync_dma);
 	if (!ep->syncbuf)
 		return -ENOMEM;
@@ -1063,60 +1064,19 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
 	return -ENOMEM;
 }
 
-/**
+/*
  * snd_usb_endpoint_set_params: configure an snd_usb_endpoint
  *
- * @ep: the snd_usb_endpoint to configure
- * @pcm_format: the audio fomat.
- * @channels: the number of audio channels.
- * @period_bytes: the number of bytes in one alsa period.
- * @period_frames: the number of frames in one alsa period.
- * @buffer_periods: the number of periods in one alsa buffer.
- * @rate: the frame rate.
- * @fmt: the USB audio format information
- * @sync_ep: the sync endpoint to use, if any
- *
  * Determine the number of URBs to be used on this endpoint.
  * An endpoint must be configured before it can be started.
  * An endpoint that is already running can not be reconfigured.
  */
-int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
-				snd_pcm_format_t pcm_format,
-				unsigned int channels,
-				unsigned int period_bytes,
-				unsigned int period_frames,
-				unsigned int buffer_periods,
-				unsigned int rate,
-				struct audioformat *fmt,
-				struct snd_usb_endpoint *sync_ep)
+static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+				       struct snd_usb_endpoint *ep)
 {
+	const struct audioformat *fmt = ep->cur_audiofmt;
 	int err;
 
-	usb_audio_dbg(ep->chip,
-		      "Setting params for ep %x (type %s, count %d), rate=%d, format=%s, channels=%d, period_bytes=%d, periods=%d\n",
-		      ep->ep_num, ep_type_name(ep->type), ep->use_count,
-		      rate, snd_pcm_format_name(pcm_format), channels,
-		      period_bytes, buffer_periods);
-
-	if (ep->use_count != 0) {
-		bool check = ep->is_implicit_feedback &&
-			check_ep_params(ep, pcm_format, channels, period_bytes,
-					period_frames, buffer_periods, rate,
-					fmt, sync_ep);
-
-		if (!check) {
-			usb_audio_warn(ep->chip,
-				"Unable to change format on ep #%x: already in use\n",
-				ep->ep_num);
-			return -EBUSY;
-		}
-
-		usb_audio_dbg(ep->chip,
-			      "Ep #%x already in use as implicit feedback but format not changed\n",
-			      ep->ep_num);
-		return 0;
-	}
-
 	/* release old buffers, if any */
 	release_urbs(ep, 0);
 
@@ -1124,17 +1084,17 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 	ep->maxpacksize = fmt->maxpacksize;
 	ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX);
 
-	if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) {
-		ep->freqn = get_usb_full_speed_rate(rate);
+	if (snd_usb_get_speed(chip->dev) == USB_SPEED_FULL) {
+		ep->freqn = get_usb_full_speed_rate(ep->cur_rate);
 		ep->pps = 1000 >> ep->datainterval;
 	} else {
-		ep->freqn = get_usb_high_speed_rate(rate);
+		ep->freqn = get_usb_high_speed_rate(ep->cur_rate);
 		ep->pps = 8000 >> ep->datainterval;
 	}
 
-	ep->sample_rem = rate % ep->pps;
-	ep->packsize[0] = rate / ep->pps;
-	ep->packsize[1] = (rate + (ep->pps - 1)) / ep->pps;
+	ep->sample_rem = ep->cur_rate % ep->pps;
+	ep->packsize[0] = ep->cur_rate / ep->pps;
+	ep->packsize[1] = (ep->cur_rate + (ep->pps - 1)) / ep->pps;
 
 	/* calculate the frequency in 16.16 format */
 	ep->freqm = ep->freqn;
@@ -1144,9 +1104,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 
 	switch (ep->type) {
 	case  SND_USB_ENDPOINT_TYPE_DATA:
-		err = data_ep_set_params(ep, pcm_format, channels,
-					 period_bytes, period_frames,
-					 buffer_periods, fmt, sync_ep);
+		err = data_ep_set_params(ep);
 		break;
 	case  SND_USB_ENDPOINT_TYPE_SYNC:
 		err = sync_ep_set_params(ep);
@@ -1155,24 +1113,92 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 		err = -EINVAL;
 	}
 
-	usb_audio_dbg(ep->chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err);
+	usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err);
 
 	if (err < 0)
 		return err;
 
-	/* record the current set up in the endpoint (for implicit fb) */
-	spin_lock_irq(&ep->lock);
-	ep->cur_rate = rate;
-	ep->cur_channels = channels;
-	ep->cur_format = pcm_format;
-	ep->cur_period_frames = period_frames;
-	ep->cur_period_bytes = period_bytes;
-	ep->cur_buffer_periods = buffer_periods;
-	spin_unlock_irq(&ep->lock);
+	/* some unit conversions in runtime */
+	ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
+	ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
 
 	return 0;
 }
 
+/*
+ * snd_usb_endpoint_configure: Configure the endpoint
+ *
+ * This function sets up the EP to be fully usable state.
+ * It's called either from hw_params or prepare callback.
+ * The function checks need_setup flag, and perfoms nothing unless needed,
+ * so it's safe to call this multiple times.
+ *
+ * This returns zero if unchanged, 1 if the configuration has changed,
+ * or a negative error code.
+ */
+int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+			       struct snd_usb_endpoint *ep)
+{
+	bool iface_first;
+	int err = 0;
+
+	mutex_lock(&chip->mutex);
+	if (!ep->need_setup)
+		goto unlock;
+
+	/* No need to (re-)configure the sync EP belonging to the same altset */
+	if (ep->ep_idx) {
+		err = snd_usb_endpoint_set_params(chip, ep);
+		if (err < 0)
+			goto unlock;
+		goto done;
+	}
+
+	/* Need to deselect altsetting at first */
+	endpoint_set_interface(chip, ep, false);
+
+	/* Some UAC1 devices (e.g. Yamaha THR10) need the host interface
+	 * to be set up before parameter setups
+	 */
+	iface_first = ep->cur_audiofmt->protocol == UAC_VERSION_1;
+	if (iface_first) {
+		err = endpoint_set_interface(chip, ep, true);
+		if (err < 0)
+			goto unlock;
+	}
+
+	err = snd_usb_init_pitch(chip, ep->cur_audiofmt);
+	if (err < 0)
+		goto unlock;
+
+	err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
+	if (err < 0)
+		goto unlock;
+
+	err = snd_usb_endpoint_set_params(chip, ep);
+	if (err < 0)
+		goto unlock;
+
+	err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
+	if (err < 0)
+		goto unlock;
+
+	/* for UAC2/3, enable the interface altset here at last */
+	if (!iface_first) {
+		err = endpoint_set_interface(chip, ep, true);
+		if (err < 0)
+			goto unlock;
+	}
+
+ done:
+	ep->need_setup = false;
+	err = 1;
+
+unlock:
+	mutex_unlock(&chip->mutex);
+	return err;
+}
+
 /**
  * snd_usb_endpoint_start: start an snd_usb_endpoint
  *
@@ -1194,6 +1220,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (atomic_read(&ep->chip->shutdown))
 		return -EBADFD;
 
+	if (ep->sync_master)
+		WRITE_ONCE(ep->sync_master->sync_slave, ep);
+
 	usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n",
 		      ep_type_name(ep->type), ep->ep_num, ep->use_count);
 
@@ -1226,6 +1255,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
 		}
 
+		usb_audio_dbg(ep->chip, "No URB submission due to implicit fb sync\n");
 		return 0;
 	}
 
@@ -1251,9 +1281,13 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 		set_bit(i, &ep->active_mask);
 	}
 
+	usb_audio_dbg(ep->chip, "%d URBs submitted for EP 0x%x\n",
+		      ep->nurbs, ep->ep_num);
 	return 0;
 
 __error:
+	if (ep->sync_master)
+		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
 	clear_bit(EP_FLAG_RUNNING, &ep->flags);
 	ep->use_count--;
 	deactivate_urbs(ep, false);
@@ -1285,39 +1319,15 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 	if (snd_BUG_ON(ep->use_count == 0))
 		return;
 
+	if (ep->sync_master)
+		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
+
 	if (--ep->use_count == 0) {
 		deactivate_urbs(ep, false);
 		set_bit(EP_FLAG_STOPPING, &ep->flags);
 	}
 }
 
-/**
- * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint
- *
- * @ep: the endpoint to deactivate
- *
- * If the endpoint is not currently in use, this functions will
- * deactivate its associated URBs.
- *
- * In case of any active users, this functions does nothing.
- */
-void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
-{
-	if (!ep)
-		return;
-
-	if (ep->use_count != 0)
-		return;
-
-	deactivate_urbs(ep, true);
-	wait_clear_urbs(ep);
-
-	/* clear the saved hw params */
-	spin_lock_irq(&ep->lock);
-	ep->cur_rate = 0;
-	spin_unlock_irq(&ep->lock);
-}
-
 /**
  * snd_usb_endpoint_release: Tear down an snd_usb_endpoint
  *
@@ -1343,7 +1353,7 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep)
 	kfree(ep);
 }
 
-/**
+/*
  * snd_usb_handle_sync_urb: parse an USB sync packet
  *
  * @ep: the endpoint to handle the packet
@@ -1353,9 +1363,9 @@ void snd_usb_endpoint_free(struct snd_usb_endpoint *ep)
  * This function is called from the context of an endpoint that received
  * the packet and is used to let another endpoint object handle the payload.
  */
-void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
-			     struct snd_usb_endpoint *sender,
-			     const struct urb *urb)
+static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
+				    struct snd_usb_endpoint *sender,
+				    const struct urb *urb)
 {
 	int shift;
 	unsigned int f;
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index e2fddb3dcf7a..2bfa6d3e029c 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -10,16 +10,25 @@ struct snd_usb_endpoint *snd_usb_get_endpoint(struct snd_usb_audio *chip,
 
 int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type);
 
-int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
-				snd_pcm_format_t pcm_format,
-				unsigned int channels,
-				unsigned int period_bytes,
-				unsigned int period_frames,
-				unsigned int buffer_periods,
-				unsigned int rate,
-				struct audioformat *fmt,
-				struct snd_usb_endpoint *sync_ep);
-
+struct snd_usb_endpoint *
+snd_usb_endpoint_open(struct snd_usb_audio *chip,
+		      struct audioformat *fp,
+		      const struct snd_pcm_hw_params *params,
+		      bool is_sync_ep);
+void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+			    struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+			       struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep);
+
+bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
+				 struct snd_usb_endpoint *ep,
+				 const struct audioformat *fp,
+				 const struct snd_pcm_hw_params *params);
+
+void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip,
+			       struct snd_usb_endpoint *data_ep,
+			       struct snd_usb_endpoint *sync_ep);
 void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
 				   void (*prepare)(struct snd_usb_substream *subs,
 						   struct urb *urb),
@@ -27,23 +36,16 @@ void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
 						  struct urb *urb),
 				   struct snd_usb_substream *data_subs);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
-void snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
 
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
-void snd_usb_endpoint_set_syncinterval(struct snd_usb_audio *chip,
-				       struct snd_usb_endpoint *ep,
-				       struct usb_host_interface *alts);
-
-void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
-			     struct snd_usb_endpoint *sender,
-			     const struct urb *urb);
 
 #endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 45a692512d27..e80e8cf1e863 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -80,21 +80,22 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
 /*
  * find a matching audio format
  */
-static struct audioformat *find_format(struct list_head *fmt_list_head,
-				       snd_pcm_format_t format,
-				       unsigned int rate,
-				       unsigned int channels,
-				       struct snd_usb_substream *subs)
+static struct audioformat *
+find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
+	    unsigned int rate, unsigned int channels, bool strict_match,
+	    struct snd_usb_substream *subs)
 {
 	struct audioformat *fp;
 	struct audioformat *found = NULL;
 	int cur_attr = 0, attr;
 
 	list_for_each_entry(fp, fmt_list_head, list) {
-		if (!(fp->formats & pcm_format_to_bits(format)))
-			continue;
-		if (fp->channels != channels)
-			continue;
+		if (strict_match) {
+			if (!(fp->formats & pcm_format_to_bits(format)))
+				continue;
+			if (fp->channels != channels)
+				continue;
+		}
 		if (rate < fp->rate_min || rate > fp->rate_max)
 			continue;
 		if (!(fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) {
@@ -140,38 +141,30 @@ static struct audioformat *find_format(struct list_head *fmt_list_head,
 	return found;
 }
 
-static struct audioformat *find_substream_format(struct snd_usb_substream *subs)
+static struct audioformat *
+find_substream_format(struct snd_usb_substream *subs,
+		      const struct snd_pcm_hw_params *params)
 {
-	return find_format(&subs->fmt_list, subs->pcm_format, subs->cur_rate,
-			   subs->channels, subs);
+	return find_format(&subs->fmt_list, params_format(params),
+			   params_rate(params), params_channels(params),
+			   true, subs);
 }
 
-static int init_pitch_v1(struct snd_usb_audio *chip,
-			 struct audioformat *fmt)
+static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
 {
 	struct usb_device *dev = chip->dev;
-	unsigned int ep;
 	unsigned char data[1];
 	int err;
 
-	ep = fmt->endpoint;
-
 	data[0] = 1;
 	err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
 			      USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 			      UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
 			      data, sizeof(data));
-	if (err < 0) {
-		usb_audio_err(chip, "%d:%d: cannot set enable PITCH\n",
-			      fmt->iface, ep);
-		return err;
-	}
-
-	return 0;
+	return err;
 }
 
-static int init_pitch_v2(struct snd_usb_audio *chip,
-			 struct audioformat *fmt)
+static int init_pitch_v2(struct snd_usb_audio *chip, int ep)
 {
 	struct usb_device *dev = chip->dev;
 	unsigned char data[1];
@@ -182,13 +175,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip,
 			      USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 			      UAC2_EP_CS_PITCH << 8, 0,
 			      data, sizeof(data));
-	if (err < 0) {
-		usb_audio_err(chip, "%d:%d: cannot set enable PITCH (v2)\n",
-			      fmt->iface, fmt->altsetting);
-		return err;
-	}
-
-	return 0;
+	return err;
 }
 
 /*
@@ -197,29 +184,47 @@ static int init_pitch_v2(struct snd_usb_audio *chip,
 int snd_usb_init_pitch(struct snd_usb_audio *chip,
 		       struct audioformat *fmt)
 {
+	int err;
+
 	/* if endpoint doesn't have pitch control, bail out */
 	if (!(fmt->attributes & UAC_EP_CS_ATTR_PITCH_CONTROL))
 		return 0;
 
+	usb_audio_dbg(chip, "enable PITCH for EP 0x%x\n", fmt->endpoint);
+
 	switch (fmt->protocol) {
 	case UAC_VERSION_1:
+		err = init_pitch_v1(chip, fmt->endpoint);
+		break;
+	case UAC_VERSION_2:
+		err = init_pitch_v2(chip, fmt->endpoint);
+		break;
 	default:
-		return init_pitch_v1(chip, fmt);
+		return 0;
+	}
 
-	case UAC_VERSION_2:
-		return init_pitch_v2(chip, fmt);
+	if (err < 0) {
+		usb_audio_err(chip, "failed to enable PITCH for EP 0x%x\n",
+			      fmt->endpoint);
+		return err;
 	}
+
+	return 0;
 }
 
-static void stop_endpoints(struct snd_usb_substream *subs)
+static bool stop_endpoints(struct snd_usb_substream *subs)
 {
+	bool stopped = 0;
+
 	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
 		snd_usb_endpoint_stop(subs->sync_endpoint);
-		subs->sync_endpoint->sync_slave = NULL;
+		stopped = true;
 	}
-
-	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
+	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
 		snd_usb_endpoint_stop(subs->data_endpoint);
+		stopped = true;
+	}
+	return stopped;
 }
 
 static int start_endpoints(struct snd_usb_substream *subs)
@@ -230,9 +235,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
 		return -EINVAL;
 
 	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
-		struct snd_usb_endpoint *ep = subs->data_endpoint;
-
-		err = snd_usb_endpoint_start(ep);
+		err = snd_usb_endpoint_start(subs->data_endpoint);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
 			goto error;
@@ -241,13 +244,9 @@ static int start_endpoints(struct snd_usb_substream *subs)
 
 	if (subs->sync_endpoint &&
 	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
-		struct snd_usb_endpoint *ep = subs->sync_endpoint;
-
-		ep->sync_slave = subs->data_endpoint;
-		err = snd_usb_endpoint_start(ep);
+		err = snd_usb_endpoint_start(subs->sync_endpoint);
 		if (err < 0) {
 			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
-			ep->sync_slave = NULL;
 			goto error;
 		}
 	}
@@ -446,6 +445,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	fmt->sync_ep = ep;
 	fmt->sync_iface = ifnum;
 	fmt->sync_altsetting = alts->desc.bAlternateSetting;
+	fmt->sync_ep_idx = 0;
 	fmt->implicit_fb = 1;
 	dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n",
 		fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
@@ -527,6 +527,7 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 	fmt->sync_ep = ep;
 	fmt->sync_iface = altsd->bInterfaceNumber;
 	fmt->sync_altsetting = altsd->bAlternateSetting;
+	fmt->sync_ep_idx = 1;
 	if ((sync_attr & USB_ENDPOINT_USAGE_MASK) == USB_ENDPOINT_USAGE_IMPLICIT_FB)
 		fmt->implicit_fb = 1;
 
@@ -537,152 +538,6 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 	return 0;
 }
 
-static int set_sync_endpoint(struct snd_usb_substream *subs,
-			     struct audioformat *fmt)
-{
-	struct usb_device *dev = subs->dev;
-	struct usb_host_interface *alts;
-	struct snd_usb_audio *chip = subs->stream->chip;
-	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int ep;
-	int err;
-
-	subs->sync_endpoint = NULL;
-	subs->data_endpoint->sync_master = NULL;
-
-	ep = fmt->sync_ep;
-	if (!ep)
-		return 0;
-
-	alts = snd_usb_get_host_interface(subs->stream->chip, fmt->sync_iface,
-					  fmt->altsetting);
-	if (!alts)
-		return 0;
-
-	subs->sync_endpoint = snd_usb_get_endpoint(chip, ep);
-	if (!subs->sync_endpoint) {
-		if (is_playback &&
-		    (fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) == USB_ENDPOINT_SYNC_NONE)
-			return 0;
-		return -EINVAL;
-	}
-
-	subs->sync_endpoint->iface = fmt->sync_iface;
-	subs->sync_endpoint->altsetting = fmt->sync_altsetting;
-	subs->sync_endpoint->is_implicit_feedback = fmt->implicit_fb;
-
-	subs->data_endpoint->sync_master = subs->sync_endpoint;
-
-	snd_usb_endpoint_set_syncinterval(subs->stream->chip, subs->sync_endpoint, alts);
-
-	if (!subs->sync_endpoint->use_count &&
-	    (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
-	     subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) {
-		err = usb_set_interface(subs->dev,
-					subs->sync_endpoint->iface,
-					subs->sync_endpoint->altsetting);
-		if (err < 0)
-			return err;
-		dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
-			subs->sync_endpoint->iface,
-			subs->sync_endpoint->altsetting);
-		snd_usb_set_interface_quirk(chip);
-	}
-
-	return 0;
-}
-
-/*
- * find a matching format and set up the interface
- */
-static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
-{
-	struct usb_device *dev = subs->dev;
-	struct snd_usb_audio *chip = subs->stream->chip;
-	struct usb_host_interface *alts;
-	struct usb_interface *iface;
-	struct snd_usb_endpoint *ep;
-	int err;
-
-	iface = usb_ifnum_to_if(dev, fmt->iface);
-	if (WARN_ON(!iface))
-		return -EINVAL;
-	alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
-	if (WARN_ON(!alts))
-		return -EINVAL;
-
-	if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
-		return 0;
-
-	/* shared EP with implicit fb */
-	if (fmt->implicit_fb && !subs->need_setup_fmt) {
-		ep = snd_usb_get_endpoint(chip, fmt->endpoint);
-		if (ep && ep->use_count > 0)
-			goto add_data_ep;
-	}
-
-	/* close the old interface */
-	if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
-		err = usb_set_interface(subs->dev, subs->interface, 0);
-		if (err < 0) {
-			dev_err(&dev->dev,
-				"%d:%d: return to setting 0 failed (%d)\n",
-				fmt->iface, fmt->altsetting, err);
-			return -EIO;
-		}
-		subs->interface = -1;
-		subs->altset_idx = 0;
-	}
-
-	if (subs->need_setup_fmt)
-		subs->need_setup_fmt = false;
-
-	/* set interface */
-	if (iface->cur_altsetting != alts) {
-		err = snd_usb_select_mode_quirk(chip, fmt);
-		if (err < 0)
-			return -EIO;
-
-		err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
-		if (err < 0) {
-			dev_err(&dev->dev,
-				"%d:%d: usb_set_interface failed (%d)\n",
-				fmt->iface, fmt->altsetting, err);
-			return -EIO;
-		}
-		dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
-			fmt->iface, fmt->altsetting);
-		snd_usb_set_interface_quirk(chip);
-	}
-
-	subs->need_setup_ep = true;
-
- add_data_ep:
-	subs->interface = fmt->iface;
-	subs->altset_idx = fmt->altset_idx;
-	subs->data_endpoint = snd_usb_get_endpoint(chip, fmt->endpoint);
-	if (!subs->data_endpoint)
-		return -EINVAL;
-	subs->data_endpoint->iface = fmt->iface;
-	subs->data_endpoint->altsetting = fmt->altsetting;
-
-	err = set_sync_endpoint(subs, fmt);
-	if (err < 0)
-		return err;
-
-	if (subs->need_setup_ep) {
-		err = snd_usb_init_pitch(chip, fmt);
-		if (err < 0)
-			return err;
-	}
-
-	subs->cur_audiofmt = fmt;
-
-	snd_usb_set_format_quirk(subs, fmt);
-
-	return 0;
-}
-
 /*
  * Return the score of matching two audioformats.
  * Veto the audioformat if:
@@ -691,8 +546,8 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
  * - Requested sample rate is not supported.
  */
 static int match_endpoint_audioformats(struct snd_usb_substream *subs,
-				       struct audioformat *fp,
-				       struct audioformat *match, int rate,
+				       const struct audioformat *fp,
+				       int rate, int channels,
 				       snd_pcm_format_t pcm_format)
 {
 	int i, score;
@@ -716,108 +571,12 @@ static int match_endpoint_audioformats(struct snd_usb_substream *subs,
 	}
 
 	score = 1;
-	if (fp->channels == match->channels)
+	if (fp->channels == channels)
 		score++;
 
 	return score;
 }
 
-/*
- * Configure the sync ep using the rate and pcm format of the data ep.
- */
-static int configure_sync_endpoint(struct snd_usb_substream *subs)
-{
-	struct audioformat *fp;
-	struct audioformat *sync_fp = NULL;
-	int cur_score = 0;
-	int sync_period_bytes = subs->period_bytes;
-	struct snd_usb_substream *sync_subs =
-		&subs->stream->substream[subs->direction ^ 1];
-
-	if (subs->fixed_hw ||
-	    !subs->sync_endpoint->is_implicit_feedback) {
-		sync_fp = subs->cur_audiofmt;
-		goto configure;
-	}
-
-	sync_fp = find_format(&sync_subs->fmt_list, subs->pcm_format,
-			      subs->cur_rate, subs->channels, NULL);
-	if (sync_fp)
-		goto configure;
-
-	/* Try to find the best matching audioformat. */
-	list_for_each_entry(fp, &sync_subs->fmt_list, list) {
-		int score = match_endpoint_audioformats(subs,
-							fp, subs->cur_audiofmt,
-			subs->cur_rate, subs->pcm_format);
-
-		if (score > cur_score) {
-			sync_fp = fp;
-			cur_score = score;
-		}
-	}
-
-	if (unlikely(sync_fp == NULL)) {
-		dev_err(&subs->dev->dev,
-			"%s: no valid audioformat for sync ep %x found\n",
-			__func__, sync_subs->ep_num);
-		return -EINVAL;
-	}
-
-	/*
-	 * Recalculate the period bytes if channel number differ between
-	 * data and sync ep audioformat.
-	 */
-	if (sync_fp->channels != subs->channels) {
-		sync_period_bytes = (subs->period_bytes / subs->channels) *
-			sync_fp->channels;
-		dev_dbg(&subs->dev->dev,
-			"%s: adjusted sync ep period bytes (%d -> %d)\n",
-			__func__, subs->period_bytes, sync_period_bytes);
-	}
-
- configure:
-	return snd_usb_endpoint_set_params(subs->sync_endpoint,
-					   subs->pcm_format,
-					   sync_fp->channels,
-					   sync_period_bytes,
-					   subs->period_frames,
-					   subs->buffer_periods,
-					   subs->cur_rate,
-					   sync_fp,
-					   NULL);
-}
-
-/*
- * configure endpoint params
- *
- * called  during initial setup and upon resume
- */
-static int configure_endpoint(struct snd_usb_substream *subs)
-{
-	int ret;
-
-	/* format changed */
-	stop_endpoints(subs);
-	sync_pending_stops(subs);
-	ret = snd_usb_endpoint_set_params(subs->data_endpoint,
-					  subs->pcm_format,
-					  subs->channels,
-					  subs->period_bytes,
-					  subs->period_frames,
-					  subs->buffer_periods,
-					  subs->cur_rate,
-					  subs->cur_audiofmt,
-					  subs->sync_endpoint);
-	if (ret < 0)
-		return ret;
-
-	if (subs->sync_endpoint)
-		ret = configure_sync_endpoint(subs);
-
-	return ret;
-}
-
 static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state)
 {
 	int ret;
@@ -866,6 +625,92 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as)
 	return 0;
 }
 
+static struct snd_usb_substream *
+find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num,
+			int fmt_type)
+{
+	struct snd_usb_stream *as;
+	struct snd_usb_substream *subs;
+
+	list_for_each_entry(as, &chip->pcm_list, list) {
+		subs = &as->substream[stream];
+		if (as->fmt_type == fmt_type && subs->ep_num == ep_num)
+			return subs;
+	}
+
+	return NULL;
+}
+
+static struct audioformat *
+find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+			     const struct audioformat *target,
+			     const struct snd_pcm_hw_params *params,
+			     int stream)
+{
+	struct snd_usb_substream *subs;
+	struct audioformat *fp, *sync_fmt;
+	int score, high_score;
+
+	subs = find_matching_substream(chip, stream, target->sync_ep,
+				       target->fmt_type);
+	if (!subs)
+		return NULL;
+
+	sync_fmt = NULL;
+	high_score = 0;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
+		score = match_endpoint_audioformats(subs, fp,
+						    params_rate(params),
+						    params_channels(params),
+						    params_format(params));
+		if (score > high_score) {
+			sync_fmt = fp;
+			high_score = score;
+		}
+	}
+
+	return sync_fmt;
+}
+
+static void close_endpoints(struct snd_usb_audio *chip,
+			    struct snd_usb_substream *subs)
+{
+	if (subs->data_endpoint) {
+		snd_usb_endpoint_set_sync(chip, subs->data_endpoint, NULL);
+		snd_usb_endpoint_close(chip, subs->data_endpoint);
+		subs->data_endpoint = NULL;
+	}
+
+	if (subs->sync_endpoint) {
+		snd_usb_endpoint_close(chip, subs->sync_endpoint);
+		subs->sync_endpoint = NULL;
+	}
+}
+
+static int configure_endpoints(struct snd_usb_audio *chip,
+			       struct snd_usb_substream *subs)
+{
+	int err;
+
+	if (subs->data_endpoint->need_setup) {
+		/* stop any running stream beforehand */
+		if (stop_endpoints(subs))
+			sync_pending_stops(subs);
+		err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
+		if (err < 0)
+			return err;
+		snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
+	}
+
+	if (subs->sync_endpoint) {
+		err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
 /*
  * hw_params callback
  *
@@ -880,30 +725,45 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *hw_params)
 {
 	struct snd_usb_substream *subs = substream->runtime->private_data;
+	struct snd_usb_audio *chip = subs->stream->chip;
 	struct audioformat *fmt;
+	struct audioformat *sync_fmt;
 	int ret;
 
 	ret = snd_media_start_pipeline(subs);
 	if (ret)
 		return ret;
 
-	subs->pcm_format = params_format(hw_params);
-	subs->period_bytes = params_period_bytes(hw_params);
-	subs->period_frames = params_period_size(hw_params);
-	subs->buffer_periods = params_periods(hw_params);
-	subs->channels = params_channels(hw_params);
-	subs->cur_rate = params_rate(hw_params);
-
-	fmt = find_substream_format(subs);
+	fmt = find_substream_format(subs, hw_params);
 	if (!fmt) {
-		dev_dbg(&subs->dev->dev,
-			"cannot set format: format = %#x, rate = %d, channels = %d\n",
-			   subs->pcm_format, subs->cur_rate, subs->channels);
+		usb_audio_dbg(chip,
+			      "cannot find format: format=%s, rate=%d, channels=%d\n",
+			      snd_pcm_format_name(params_format(hw_params)),
+			      params_rate(hw_params), params_channels(hw_params));
 		ret = -EINVAL;
 		goto stop_pipeline;
 	}
 
-	ret = snd_usb_lock_shutdown(subs->stream->chip);
+	if (fmt->implicit_fb &&
+	    (fmt->iface != fmt->sync_iface ||
+	     fmt->altsetting != fmt->sync_altsetting)) {
+		sync_fmt = find_implicit_fb_sync_format(chip, fmt, hw_params,
+							!substream->stream);
+		if (!sync_fmt) {
+			usb_audio_dbg(chip,
+				      "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
+				      fmt->sync_ep, fmt->sync_iface,
+				      fmt->sync_altsetting,
+				      snd_pcm_format_name(params_format(hw_params)),
+				      params_rate(hw_params), params_channels(hw_params));
+			ret = -EINVAL;
+			goto stop_pipeline;
+		}
+	} else {
+		sync_fmt = fmt;
+	}
+
+	ret = snd_usb_lock_shutdown(chip);
 	if (ret < 0)
 		goto stop_pipeline;
 
@@ -911,18 +771,56 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	if (ret < 0)
 		goto unlock;
 
-	ret = set_format(subs, fmt);
+	if (subs->data_endpoint) {
+		if (snd_usb_endpoint_compatible(chip, subs->data_endpoint,
+						fmt, hw_params))
+			goto unlock;
+		close_endpoints(chip, subs);
+	}
+
+	subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);
+	if (!subs->data_endpoint) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (fmt->sync_ep) {
+		subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
+							    hw_params,
+							    fmt == sync_fmt);
+		if (!subs->sync_endpoint) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+
+		snd_usb_endpoint_set_sync(chip, subs->data_endpoint,
+					  subs->sync_endpoint);
+	}
+
+	subs->interface = fmt->iface;
+	subs->altset_idx = fmt->altset_idx;
+	subs->cur_audiofmt = fmt;
+
+	ret = configure_endpoints(chip, subs);
 	if (ret < 0)
 		goto unlock;
 
+	subs->pcm_format = params_format(hw_params);
+	subs->period_bytes = params_period_bytes(hw_params);
+	subs->period_frames = params_period_size(hw_params);
+	subs->buffer_periods = params_periods(hw_params);
+	subs->channels = params_channels(hw_params);
+	subs->cur_rate = params_rate(hw_params);
+
  unlock:
-	snd_usb_unlock_shutdown(subs->stream->chip);
 	if (ret < 0)
-		goto stop_pipeline;
-	return ret;
+		close_endpoints(chip, subs);
 
+	snd_usb_unlock_shutdown(chip);
  stop_pipeline:
-	snd_media_stop_pipeline(subs);
+	if (ret < 0)
+		snd_media_stop_pipeline(subs);
+
 	return ret;
 }
 
@@ -941,15 +839,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 	subs->cur_rate = 0;
 	subs->period_bytes = 0;
 	if (!snd_usb_lock_shutdown(chip)) {
-		stop_endpoints(subs);
-		sync_pending_stops(subs);
-		snd_usb_endpoint_deactivate(subs->sync_endpoint);
-		snd_usb_endpoint_deactivate(subs->data_endpoint);
-		if (subs->data_endpoint) {
-			subs->data_endpoint->sync_master = NULL;
-			subs->data_endpoint = NULL;
-		}
-		subs->sync_endpoint = NULL;
+		if (stop_endpoints(subs))
+			sync_pending_stops(subs);
+		close_endpoints(chip, subs);
 		snd_usb_unlock_shutdown(chip);
 	}
 
@@ -965,16 +857,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_usb_substream *subs = runtime->private_data;
-	struct usb_host_interface *alts;
-	struct usb_interface *iface;
+	struct snd_usb_audio *chip = subs->stream->chip;
 	int ret;
 
-	if (! subs->cur_audiofmt) {
-		dev_err(&subs->dev->dev, "no format is specified!\n");
-		return -ENXIO;
-	}
-
-	ret = snd_usb_lock_shutdown(subs->stream->chip);
+	ret = snd_usb_lock_shutdown(chip);
 	if (ret < 0)
 		return ret;
 	if (snd_BUG_ON(!subs->data_endpoint)) {
@@ -982,36 +868,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 		goto unlock;
 	}
 
-	ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
-	if (ret < 0)
-		goto unlock;
-
-	ret = set_format(subs, subs->cur_audiofmt);
+	ret = configure_endpoints(chip, subs);
 	if (ret < 0)
 		goto unlock;
 
-	if (subs->need_setup_ep) {
-
-		iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
-		alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
-		ret = snd_usb_init_sample_rate(subs->stream->chip,
-					       subs->cur_audiofmt,
-					       subs->cur_rate);
-		if (ret < 0)
-			goto unlock;
-
-		ret = configure_endpoint(subs);
-		if (ret < 0)
-			goto unlock;
-		subs->need_setup_ep = false;
-	}
-
-	/* some unit conversions in runtime */
-	subs->data_endpoint->maxframesize =
-		bytes_to_frames(runtime, subs->data_endpoint->maxpacksize);
-	subs->data_endpoint->curframesize =
-		bytes_to_frames(runtime, subs->data_endpoint->curpacksize);
-
 	/* reset the pointer */
 	subs->hwptr_done = 0;
 	subs->transfer_done = 0;
@@ -1025,7 +885,7 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 		ret = start_endpoints(subs);
 
  unlock:
-	snd_usb_unlock_shutdown(subs->stream->chip);
+	snd_usb_unlock_shutdown(chip);
 	return ret;
 }
 
@@ -1047,6 +907,8 @@ static const struct snd_pcm_hardware snd_usb_hardware =
 				SNDRV_PCM_INFO_INTERLEAVED |
 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				SNDRV_PCM_INFO_PAUSE,
+	.channels_min =		1,
+	.channels_max =		256,
 	.buffer_bytes_max =	1024 * 1024,
 	.period_bytes_min =	64,
 	.period_bytes_max =	512 * 1024,
@@ -1250,7 +1112,6 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 	struct audioformat *fp;
 	int err;
 
-	subs->fixed_hw = 0;
 	list_for_each_entry(fp, &subs->fmt_list, list) {
 		ep = snd_usb_get_endpoint(chip, fp->endpoint);
 		if (ep && ep->cur_rate)
@@ -1266,7 +1127,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 
  found:
 	if (!find_format(&subs->fmt_list, ep->cur_format, ep->cur_rate,
-			 ep->cur_channels, NULL)) {
+			 ep->cur_channels, false, NULL)) {
 		usb_audio_dbg(chip, "EP 0x%x being used, but not applicable\n",
 			      ep->ep_num);
 		return 0;
@@ -1274,19 +1135,23 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 
 	usb_audio_dbg(chip, "EP 0x%x being used, using fixed params:\n",
 		      ep->ep_num);
-	usb_audio_dbg(chip, "rate=%d, format=%s, channels=%d, period_size=%d, periods=%d\n",
-		      ep->cur_rate, snd_pcm_format_name(ep->cur_format),
-		      ep->cur_channels, ep->cur_period_frames,
+	usb_audio_dbg(chip, "rate=%d, period_size=%d, periods=%d\n",
+		      ep->cur_rate, ep->cur_period_frames,
 		      ep->cur_buffer_periods);
 
-	runtime->hw.formats = pcm_format_to_bits(ep->cur_format);
+	runtime->hw.formats = subs->formats;
 	runtime->hw.rate_min = runtime->hw.rate_max = ep->cur_rate;
-	runtime->hw.channels_min = runtime->hw.channels_max =
-		ep->cur_channels;
 	runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
 	runtime->hw.periods_min = runtime->hw.periods_max =
 		ep->cur_buffer_periods;
-	subs->fixed_hw = 1;
+
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  hw_rule_channels, subs,
+				  SNDRV_PCM_HW_PARAM_FORMAT,
+				  SNDRV_PCM_HW_PARAM_RATE,
+				  -1);
+	if (err < 0)
+		return err;
 
 	err = snd_pcm_hw_constraint_minmax(runtime,
 					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
@@ -1442,9 +1307,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
 
 	snd_media_stop_pipeline(subs);
 
-	if (subs->interface >= 0 &&
-	    !snd_usb_lock_shutdown(subs->stream->chip)) {
-		usb_set_interface(subs->dev, subs->interface, 0);
+	if (!snd_usb_lock_shutdown(subs->stream->chip)) {
 		subs->interface = -1;
 		ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
 		snd_usb_unlock_shutdown(subs->stream->chip);
@@ -1823,15 +1686,19 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
 					      retire_playback_urb,
 					      subs);
 		subs->running = 1;
+		dev_dbg(&subs->dev->dev, "%d:%d Start Playback PCM\n",
+			subs->cur_audiofmt->iface,
+			subs->cur_audiofmt->altsetting);
 		return 0;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		subs->need_setup_fmt = true;
-		fallthrough;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
 		snd_usb_endpoint_set_callback(subs->data_endpoint,
 					      NULL, NULL, NULL);
 		subs->running = 0;
+		dev_dbg(&subs->dev->dev, "%d:%d Stop Playback PCM\n",
+			subs->cur_audiofmt->iface,
+			subs->cur_audiofmt->altsetting);
 		return 0;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		/* keep retire_data_urb for delay calculation */
@@ -1840,6 +1707,9 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
 					      retire_playback_urb,
 					      subs);
 		subs->running = 0;
+		dev_dbg(&subs->dev->dev, "%d:%d Pause Playback PCM\n",
+			subs->cur_audiofmt->iface,
+			subs->cur_audiofmt->altsetting);
 		return 0;
 	}
 
@@ -1863,10 +1733,11 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 					      NULL, retire_capture_urb,
 					      subs);
 		subs->running = 1;
+		dev_dbg(&subs->dev->dev, "%d:%d Start Capture PCM\n",
+			subs->cur_audiofmt->iface,
+			subs->cur_audiofmt->altsetting);
 		return 0;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		subs->need_setup_fmt = true;
-		fallthrough;
 	case SNDRV_PCM_TRIGGER_STOP:
 		stop_endpoints(subs);
 		fallthrough;
@@ -1874,6 +1745,9 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 		snd_usb_endpoint_set_callback(subs->data_endpoint,
 					      NULL, NULL, NULL);
 		subs->running = 0;
+		dev_dbg(&subs->dev->dev, "%d:%d Stop Capture PCM\n",
+			subs->cur_audiofmt->iface,
+			subs->cur_audiofmt->altsetting);
 		return 0;
 	}
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 26/41] ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (24 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 25/41] ALSA: usb-audio: Refactor endpoint management Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 27/41] ALSA: usb-audio: Constify audioformat pointer references Takashi Iwai
                   ` (14 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The implicit feedback mode uses a ring buffer for storing the received
packet sizes from the feedback source, and the code has a slight flaw;
when a playback stream stalls by some reason and the URBs aren't
processed, the next_packet FIFO might become empty, but the driver
can't distinguish whether it's empty or full because it's managed with
read_poss and write_pos.

This patch addresses those by changing the next_packet array
management.  Instead of keeping read and write positions, now the head
position and the queued amount are kept.  It's easier to understand
about the emptiness.  Also, the URB active flag is now cleared before
calling queue_pending_output_urbs() for avoiding (theoretically)
possible inconsistency.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     |  5 ++--
 sound/usb/endpoint.c | 83 +++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 66a249ae138f..cde492e9581a 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -80,8 +80,9 @@ struct snd_usb_endpoint {
 		uint32_t packet_size[MAX_PACKS_HS];
 		int packets;
 	} next_packet[MAX_URBS];
-	int next_packet_read_pos, next_packet_write_pos;
-	struct list_head ready_playback_urbs;
+	unsigned int next_packet_head;	/* ring buffer offset to read */
+	unsigned int next_packet_queued; /* queued items in the ring buffer */
+	struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
 
 	unsigned int nurbs;		/* # urbs */
 	unsigned long active_mask;	/* bitmask of active urbs */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index eee74313603e..b8f06a75fc2a 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -328,6 +328,39 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
 	}
 }
 
+/* notify an error as XRUN to the assigned PCM data substream */
+static void notify_xrun(struct snd_usb_endpoint *ep)
+{
+	struct snd_usb_substream *data_subs;
+
+	data_subs = READ_ONCE(ep->data_subs);
+	if (data_subs && data_subs->pcm_substream)
+		snd_pcm_stop_xrun(data_subs->pcm_substream);
+}
+
+static struct snd_usb_packet_info *
+next_packet_fifo_enqueue(struct snd_usb_endpoint *ep)
+{
+	struct snd_usb_packet_info *p;
+
+	p = ep->next_packet + (ep->next_packet_head + ep->next_packet_queued) %
+		ARRAY_SIZE(ep->next_packet);
+	ep->next_packet_queued++;
+	return p;
+}
+
+static struct snd_usb_packet_info *
+next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
+{
+	struct snd_usb_packet_info *p;
+
+	p = ep->next_packet + ep->next_packet_head;
+	ep->next_packet_head++;
+	ep->next_packet_head %= ARRAY_SIZE(ep->next_packet);
+	ep->next_packet_queued--;
+	return p;
+}
+
 /*
  * Send output urbs that have been prepared previously. URBs are dequeued
  * from ep->ready_playback_urbs and in case there aren't any available
@@ -352,17 +385,14 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		int err, i;
 
 		spin_lock_irqsave(&ep->lock, flags);
-		if (ep->next_packet_read_pos != ep->next_packet_write_pos) {
-			packet = ep->next_packet + ep->next_packet_read_pos;
-			ep->next_packet_read_pos++;
-			ep->next_packet_read_pos %= MAX_URBS;
-
+		if (ep->next_packet_queued > 0 &&
+		    !list_empty(&ep->ready_playback_urbs)) {
 			/* take URB out of FIFO */
-			if (!list_empty(&ep->ready_playback_urbs)) {
-				ctx = list_first_entry(&ep->ready_playback_urbs,
+			ctx = list_first_entry(&ep->ready_playback_urbs,
 					       struct snd_urb_ctx, ready_list);
-				list_del_init(&ctx->ready_list);
-			}
+			list_del_init(&ctx->ready_list);
+
+			packet = next_packet_fifo_dequeue(ep);
 		}
 		spin_unlock_irqrestore(&ep->lock, flags);
 
@@ -377,12 +407,15 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		prepare_outbound_urb(ep, ctx);
 
 		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
-		if (err < 0)
+		if (err < 0) {
 			usb_audio_err(ep->chip,
 				      "Unable to submit urb #%d: %d at %s\n",
 				      ctx->index, err, __func__);
-		else
-			set_bit(ctx->index, &ep->active_mask);
+			notify_xrun(ep);
+			return;
+		}
+
+		set_bit(ctx->index, &ep->active_mask);
 	}
 }
 
@@ -393,7 +426,6 @@ static void snd_complete_urb(struct urb *urb)
 {
 	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_endpoint *ep = ctx->ep;
-	struct snd_usb_substream *data_subs;
 	unsigned long flags;
 	int err;
 
@@ -418,10 +450,10 @@ static void snd_complete_urb(struct urb *urb)
 		if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
 			spin_lock_irqsave(&ep->lock, flags);
 			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+			clear_bit(ctx->index, &ep->active_mask);
 			spin_unlock_irqrestore(&ep->lock, flags);
 			queue_pending_output_urbs(ep);
-
-			goto exit_clear;
+			return;
 		}
 
 		prepare_outbound_urb(ep, ctx);
@@ -442,9 +474,7 @@ static void snd_complete_urb(struct urb *urb)
 		return;
 
 	usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
-	data_subs = READ_ONCE(ep->data_subs);
-	if (data_subs && data_subs->pcm_substream)
-		snd_pcm_stop_xrun(data_subs->pcm_substream);
+	notify_xrun(ep);
 
 exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);
@@ -789,8 +819,8 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
 	clear_bit(EP_FLAG_RUNNING, &ep->flags);
 
 	INIT_LIST_HEAD(&ep->ready_playback_urbs);
-	ep->next_packet_read_pos = 0;
-	ep->next_packet_write_pos = 0;
+	ep->next_packet_head = 0;
+	ep->next_packet_queued = 0;
 
 	for (i = 0; i < ep->nurbs; i++) {
 		if (test_bit(i, &ep->active_mask)) {
@@ -1402,7 +1432,16 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 			return;
 
 		spin_lock_irqsave(&ep->lock, flags);
-		out_packet = ep->next_packet + ep->next_packet_write_pos;
+		if (ep->next_packet_queued >= ARRAY_SIZE(ep->next_packet)) {
+			spin_unlock_irqrestore(&ep->lock, flags);
+			usb_audio_err(ep->chip,
+				      "next package FIFO overflow EP 0x%x\n",
+				      ep->ep_num);
+			notify_xrun(ep);
+			return;
+		}
+
+		out_packet = next_packet_fifo_enqueue(ep);
 
 		/*
 		 * Iterate through the inbound packet and prepare the lengths
@@ -1423,8 +1462,6 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 				out_packet->packet_size[i] = 0;
 		}
 
-		ep->next_packet_write_pos++;
-		ep->next_packet_write_pos %= MAX_URBS;
 		spin_unlock_irqrestore(&ep->lock, flags);
 		queue_pending_output_urbs(ep);
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 27/41] ALSA: usb-audio: Constify audioformat pointer references
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (25 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 26/41] ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 28/41] ALSA: usb-audio: Use atomic_t for endpoint use_count Takashi Iwai
                   ` (13 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The audioformat is referred in many places but most of usages are
read-only.  Let's add const prefix in the possible places.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     |  4 ++--
 sound/usb/clock.c    | 16 ++++++++--------
 sound/usb/clock.h    |  4 ++--
 sound/usb/endpoint.c |  2 +-
 sound/usb/endpoint.h |  2 +-
 sound/usb/pcm.c      | 32 ++++++++++++++++----------------
 sound/usb/pcm.h      |  2 +-
 sound/usb/quirks.c   |  9 +++++----
 sound/usb/quirks.h   |  6 +++---
 9 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index cde492e9581a..53f0ce61f858 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -120,7 +120,7 @@ struct snd_usb_endpoint {
 	bool need_setup;		/* (re-)need for configure? */
 
 	/* for hw constraints */
-	struct audioformat *cur_audiofmt;
+	const struct audioformat *cur_audiofmt;
 	unsigned int cur_rate;
 	snd_pcm_format_t cur_format;
 	unsigned int cur_channels;
@@ -142,7 +142,7 @@ struct snd_usb_substream {
 	int direction;	/* playback or capture */
 	int interface;	/* current interface */
 	int endpoint;	/* assigned endpoint */
-	struct audioformat *cur_audiofmt;	/* current audioformat pointer (for hw_params callback) */
+	const struct audioformat *cur_audiofmt;	/* current audioformat pointer (for hw_params callback) */
 	struct snd_usb_power_domain *str_pd;	/* UAC3 Power Domain for streaming path */
 	snd_pcm_format_t pcm_format;	/* current audio format (for hw_params callback) */
 	unsigned int channels;		/* current number of channels (for hw_params callback) */
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index b869a711afbf..e940dcee792b 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -152,7 +152,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
 }
 
 static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-					    struct audioformat *fmt,
+					    const struct audioformat *fmt,
 					    int source_id)
 {
 	bool ret = false;
@@ -215,7 +215,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
 }
 
 static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-				      struct audioformat *fmt,
+				      const struct audioformat *fmt,
 				      int source_id)
 {
 	int err;
@@ -264,7 +264,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
 }
 
 static int __uac_clock_find_source(struct snd_usb_audio *chip,
-				   struct audioformat *fmt, int entity_id,
+				   const struct audioformat *fmt, int entity_id,
 				   unsigned long *visited, bool validate)
 {
 	struct uac_clock_source_descriptor *source;
@@ -358,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 }
 
 static int __uac3_clock_find_source(struct snd_usb_audio *chip,
-				    struct audioformat *fmt, int entity_id,
+				    const struct audioformat *fmt, int entity_id,
 				    unsigned long *visited, bool validate)
 {
 	struct uac3_clock_source_descriptor *source;
@@ -464,7 +464,7 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip,
  * Returns the clock source UnitID (>=0) on success, or an error.
  */
 int snd_usb_clock_find_source(struct snd_usb_audio *chip,
-			      struct audioformat *fmt, bool validate)
+			      const struct audioformat *fmt, bool validate)
 {
 	DECLARE_BITMAP(visited, 256);
 	memset(visited, 0, sizeof(visited));
@@ -482,7 +482,7 @@ int snd_usb_clock_find_source(struct snd_usb_audio *chip,
 }
 
 static int set_sample_rate_v1(struct snd_usb_audio *chip,
-			      struct audioformat *fmt, int rate)
+			      const struct audioformat *fmt, int rate)
 {
 	struct usb_device *dev = chip->dev;
 	struct usb_host_interface *alts;
@@ -611,7 +611,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
 }
 
 static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
-				struct audioformat *fmt, int rate)
+				const struct audioformat *fmt, int rate)
 {
 	int cur_rate, prev_rate;
 	int clock;
@@ -663,7 +663,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip,
 }
 
 int snd_usb_init_sample_rate(struct snd_usb_audio *chip,
-			     struct audioformat *fmt, int rate)
+			     const struct audioformat *fmt, int rate)
 {
 	usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n",
 		      fmt->iface, fmt->altsetting, rate, fmt->clock);
diff --git a/sound/usb/clock.h b/sound/usb/clock.h
index 8d406ed294d6..ed9fc2dc0510 100644
--- a/sound/usb/clock.h
+++ b/sound/usb/clock.h
@@ -3,10 +3,10 @@
 #define __USBAUDIO_CLOCK_H
 
 int snd_usb_init_sample_rate(struct snd_usb_audio *chip,
-			     struct audioformat *fmt, int rate);
+			     const struct audioformat *fmt, int rate);
 
 int snd_usb_clock_find_source(struct snd_usb_audio *chip,
-			      struct audioformat *fmt, bool validate);
+			      const struct audioformat *fmt, bool validate);
 
 int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
 				 const struct audioformat *fmt,
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index b8f06a75fc2a..49fb934ee432 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -623,7 +623,7 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
  */
 struct snd_usb_endpoint *
 snd_usb_endpoint_open(struct snd_usb_audio *chip,
-		      struct audioformat *fp,
+		      const struct audioformat *fp,
 		      const struct snd_pcm_hw_params *params,
 		      bool is_sync_ep)
 {
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 2bfa6d3e029c..201011d89659 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -12,7 +12,7 @@ int snd_usb_add_endpoint(struct snd_usb_audio *chip, int ep_num, int type);
 
 struct snd_usb_endpoint *
 snd_usb_endpoint_open(struct snd_usb_audio *chip,
-		      struct audioformat *fp,
+		      const struct audioformat *fp,
 		      const struct snd_pcm_hw_params *params,
 		      bool is_sync_ep);
 void snd_usb_endpoint_close(struct snd_usb_audio *chip,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index e80e8cf1e863..fc028492dd1a 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -80,13 +80,13 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
 /*
  * find a matching audio format
  */
-static struct audioformat *
+static const struct audioformat *
 find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
 	    unsigned int rate, unsigned int channels, bool strict_match,
 	    struct snd_usb_substream *subs)
 {
-	struct audioformat *fp;
-	struct audioformat *found = NULL;
+	const struct audioformat *fp;
+	const struct audioformat *found = NULL;
 	int cur_attr = 0, attr;
 
 	list_for_each_entry(fp, fmt_list_head, list) {
@@ -141,7 +141,7 @@ find_format(struct list_head *fmt_list_head, snd_pcm_format_t format,
 	return found;
 }
 
-static struct audioformat *
+static const struct audioformat *
 find_substream_format(struct snd_usb_substream *subs,
 		      const struct snd_pcm_hw_params *params)
 {
@@ -182,7 +182,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int ep)
  * initialize the pitch control and sample rate
  */
 int snd_usb_init_pitch(struct snd_usb_audio *chip,
-		       struct audioformat *fmt)
+		       const struct audioformat *fmt)
 {
 	int err;
 
@@ -641,14 +641,14 @@ find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num,
 	return NULL;
 }
 
-static struct audioformat *
+static const struct audioformat *
 find_implicit_fb_sync_format(struct snd_usb_audio *chip,
 			     const struct audioformat *target,
 			     const struct snd_pcm_hw_params *params,
 			     int stream)
 {
 	struct snd_usb_substream *subs;
-	struct audioformat *fp, *sync_fmt;
+	const struct audioformat *fp, *sync_fmt;
 	int score, high_score;
 
 	subs = find_matching_substream(chip, stream, target->sync_ep,
@@ -726,8 +726,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_usb_substream *subs = substream->runtime->private_data;
 	struct snd_usb_audio *chip = subs->stream->chip;
-	struct audioformat *fmt;
-	struct audioformat *sync_fmt;
+	const struct audioformat *fmt;
+	const struct audioformat *sync_fmt;
 	int ret;
 
 	ret = snd_media_start_pipeline(subs);
@@ -918,7 +918,7 @@ static const struct snd_pcm_hardware snd_usb_hardware =
 
 static int hw_check_valid_format(struct snd_usb_substream *subs,
 				 struct snd_pcm_hw_params *params,
-				 struct audioformat *fp)
+				 const struct audioformat *fp)
 {
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
@@ -995,7 +995,7 @@ static int hw_rule_rate(struct snd_pcm_hw_params *params,
 			struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	unsigned int rmin, rmax, r;
 	int i;
@@ -1028,7 +1028,7 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params,
 			    struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 	unsigned int rmin, rmax;
 
@@ -1049,7 +1049,7 @@ static int hw_rule_format(struct snd_pcm_hw_params *params,
 			  struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
 	u64 fbits;
 	u32 oldbits[2];
@@ -1080,7 +1080,7 @@ static int hw_rule_period_time(struct snd_pcm_hw_params *params,
 			       struct snd_pcm_hw_rule *rule)
 {
 	struct snd_usb_substream *subs = rule->private;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	struct snd_interval *it;
 	unsigned char min_datainterval;
 	unsigned int pmin;
@@ -1109,7 +1109,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 {
 	struct snd_usb_audio *chip = subs->stream->chip;
 	struct snd_usb_endpoint *ep;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	int err;
 
 	list_for_each_entry(fp, &subs->fmt_list, list) {
@@ -1170,7 +1170,7 @@ static int apply_hw_constraint_from_sync(struct snd_pcm_runtime *runtime,
 static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
 {
 	struct snd_usb_audio *chip = subs->stream->chip;
-	struct audioformat *fp;
+	const struct audioformat *fp;
 	unsigned int pt, ptmin;
 	int param_period_time_if_needed = -1;
 	int err;
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index a4f784225abc..06c586467d3f 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -10,7 +10,7 @@ int snd_usb_pcm_suspend(struct snd_usb_stream *as);
 int snd_usb_pcm_resume(struct snd_usb_stream *as);
 
 int snd_usb_init_pitch(struct snd_usb_audio *chip,
-		       struct audioformat *fmt);
+		       const struct audioformat *fmt);
 void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
 
 int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 7e7f258011ff..5510c8a98447 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1375,7 +1375,8 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
 /*
  * check if the device uses big-endian samples
  */
-int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
+int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
+				 const struct audioformat *fp)
 {
 	/* it depends on altsetting whether the device is big-endian or not */
 	switch (chip->usb_id) {
@@ -1414,7 +1415,7 @@ enum {
 };
 
 static void set_format_emu_quirk(struct snd_usb_substream *subs,
-				 struct audioformat *fmt)
+				 const struct audioformat *fmt)
 {
 	unsigned char emu_samplerate_id = 0;
 
@@ -1476,7 +1477,7 @@ static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs)
 }
 
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
-			      struct audioformat *fmt)
+			      const struct audioformat *fmt)
 {
 	switch (subs->stream->chip->usb_id) {
 	case USB_ID(0x041e, 0x3f02): /* E-Mu 0202 USB */
@@ -1543,7 +1544,7 @@ static bool is_itf_usb_dsd_dac(unsigned int id)
 }
 
 int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
-			      struct audioformat *fmt)
+			      const struct audioformat *fmt)
 {
 	struct usb_device *dev = chip->dev;
 	int err;
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 011f22cf2bf6..67a02303c820 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -26,12 +26,12 @@ int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
 				  unsigned int usb_id);
 
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
-			      struct audioformat *fmt);
+			      const struct audioformat *fmt);
 
 bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip);
 
 int snd_usb_is_big_endian_format(struct snd_usb_audio *chip,
-				 struct audioformat *fp);
+				 const struct audioformat *fp);
 
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep);
 
@@ -41,7 +41,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
 			   __u16 index, void *data, __u16 size);
 
 int snd_usb_select_mode_quirk(struct snd_usb_audio *chip,
-			      struct audioformat *fmt);
+			      const struct audioformat *fmt);
 
 u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 					struct audioformat *fp,
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 28/41] ALSA: usb-audio: Use atomic_t for endpoint use_count
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (26 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 27/41] ALSA: usb-audio: Constify audioformat pointer references Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 29/41] ALSA: usb-audio: Refactoring endpoint URB deactivation Takashi Iwai
                   ` (12 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The endpoint objects may be started/stopped concurrently by different
substreams in the case of implicit feedback mode, while the current
code handles the reference counter without any protection.

This patch changes the refcount to atomic_t for avoiding the
inconsistency.  We need no reference_t here as the refcount goes only
up to 2.

Also the name "use_count" is renamed to "running" since this is about
actually the running status, not the open refcount.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     |  2 +-
 sound/usb/endpoint.c | 26 ++++++++++++++------------
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 53f0ce61f858..f58c3769b058 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -60,7 +60,7 @@ struct snd_usb_endpoint {
 	struct snd_usb_audio *chip;
 
 	int opened;		/* open refcount; protect with chip->mutex */
-	int use_count;
+	atomic_t running;	/* running status */
 	int ep_num;		/* the referenced endpoint number */
 	int type;		/* SND_USB_ENDPOINT_TYPE_* */
 	unsigned long flags;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 49fb934ee432..4d733b2d8287 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1234,7 +1234,7 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
  *
  * @ep: the endpoint to start
  *
- * A call to this function will increment the use count of the endpoint.
+ * A call to this function will increment the running count of the endpoint.
  * In case it is not already running, the URBs for this endpoint will be
  * submitted. Otherwise, this function does nothing.
  *
@@ -1253,11 +1253,12 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (ep->sync_master)
 		WRITE_ONCE(ep->sync_master->sync_slave, ep);
 
-	usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (count %d)\n",
-		      ep_type_name(ep->type), ep->ep_num, ep->use_count);
+	usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (running %d)\n",
+		      ep_type_name(ep->type), ep->ep_num,
+		      atomic_read(&ep->running));
 
 	/* already running? */
-	if (++ep->use_count != 1)
+	if (atomic_inc_return(&ep->running) != 1)
 		return 0;
 
 	/* just to be sure */
@@ -1319,7 +1320,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (ep->sync_master)
 		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
 	clear_bit(EP_FLAG_RUNNING, &ep->flags);
-	ep->use_count--;
+	atomic_dec(&ep->running);
 	deactivate_urbs(ep, false);
 	return -EPIPE;
 }
@@ -1329,7 +1330,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
  *
  * @ep: the endpoint to stop (may be NULL)
  *
- * A call to this function will decrement the use count of the endpoint.
+ * A call to this function will decrement the running count of the endpoint.
  * In case the last user has requested the endpoint stop, the URBs will
  * actually be deactivated.
  *
@@ -1343,16 +1344,17 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 	if (!ep)
 		return;
 
-	usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (count %d)\n",
-		      ep_type_name(ep->type), ep->ep_num, ep->use_count);
+	usb_audio_dbg(ep->chip, "Stopping %s EP 0x%x (running %d)\n",
+		      ep_type_name(ep->type), ep->ep_num,
+		      atomic_read(&ep->running));
 
-	if (snd_BUG_ON(ep->use_count == 0))
+	if (snd_BUG_ON(!atomic_read(&ep->running)))
 		return;
 
 	if (ep->sync_master)
 		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
 
-	if (--ep->use_count == 0) {
+	if (!atomic_dec_return(&ep->running)) {
 		deactivate_urbs(ep, false);
 		set_bit(EP_FLAG_STOPPING, &ep->flags);
 	}
@@ -1363,7 +1365,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
  *
  * @ep: the endpoint to release
  *
- * This function does not care for the endpoint's use count but will tear
+ * This function does not care for the endpoint's running count but will tear
  * down all the streaming URBs immediately.
  */
 void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
@@ -1410,7 +1412,7 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 	 * will take care of them later.
 	 */
 	if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
-	    ep->use_count != 0) {
+	    atomic_read(&ep->running)) {
 
 		/* implicit feedback case */
 		int i, bytes = 0;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 29/41] ALSA: usb-audio: Refactoring endpoint URB deactivation
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (27 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 28/41] ALSA: usb-audio: Use atomic_t for endpoint use_count Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 30/41] ALSA: usb-audio: Drop unneeded snd_usb_substream fields Takashi Iwai
                   ` (11 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Minor code refactoring to consolidate the URB deactivation code in
endpoint.c.  A slight behavior change is that the error handling in
snd_usb_endpoint_start() leaves EP_FLAG_STOPPING now.  This should be
synced with the later PCM sync_stop callback.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 4d733b2d8287..35c84c2264e1 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -777,6 +777,9 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
 	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
 	int alive;
 
+	if (!test_bit(EP_FLAG_STOPPING, &ep->flags))
+		return 0;
+
 	do {
 		alive = bitmap_weight(&ep->active_mask, ep->nurbs);
 		if (!alive)
@@ -802,22 +805,31 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
  */
 void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
 {
-	if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
+	if (ep)
 		wait_clear_urbs(ep);
 }
 
 /*
- * unlink active urbs.
+ * Stop and unlink active urbs.
+ *
+ * This function checks and clears EP_FLAG_RUNNING state.
+ * When @wait_sync is set, it waits until all pending URBs are killed.
  */
-static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
+static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
+				bool wait_sync)
 {
 	unsigned int i;
 
 	if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */
 		return -EBADFD;
 
-	clear_bit(EP_FLAG_RUNNING, &ep->flags);
+	if (atomic_read(&ep->running))
+		return -EBUSY;
+
+	if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags))
+		goto out;
 
+	set_bit(EP_FLAG_STOPPING, &ep->flags);
 	INIT_LIST_HEAD(&ep->ready_playback_urbs);
 	ep->next_packet_head = 0;
 	ep->next_packet_queued = 0;
@@ -831,6 +843,9 @@ static int deactivate_urbs(struct snd_usb_endpoint *ep, bool force)
 		}
 	}
 
+ out:
+	if (wait_sync)
+		return wait_clear_urbs(ep);
 	return 0;
 }
 
@@ -845,8 +860,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 	snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
 
 	/* stop urbs */
-	deactivate_urbs(ep, force);
-	wait_clear_urbs(ep);
+	stop_and_unlink_urbs(ep, force, true);
 
 	for (i = 0; i < ep->nurbs; i++)
 		release_urb_ctx(&ep->urb[i]);
@@ -1261,9 +1275,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (atomic_inc_return(&ep->running) != 1)
 		return 0;
 
-	/* just to be sure */
-	deactivate_urbs(ep, false);
-
 	ep->active_mask = 0;
 	ep->unlink_mask = 0;
 	ep->phase = 0;
@@ -1317,11 +1328,7 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	return 0;
 
 __error:
-	if (ep->sync_master)
-		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
-	clear_bit(EP_FLAG_RUNNING, &ep->flags);
-	atomic_dec(&ep->running);
-	deactivate_urbs(ep, false);
+	snd_usb_endpoint_stop(ep);
 	return -EPIPE;
 }
 
@@ -1354,10 +1361,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 	if (ep->sync_master)
 		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
 
-	if (!atomic_dec_return(&ep->running)) {
-		deactivate_urbs(ep, false);
-		set_bit(EP_FLAG_STOPPING, &ep->flags);
-	}
+	if (!atomic_dec_return(&ep->running))
+		stop_and_unlink_urbs(ep, false, false);
 }
 
 /**
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 30/41] ALSA: usb-audio: Drop unneeded snd_usb_substream fields
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (28 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 29/41] ALSA: usb-audio: Refactoring endpoint URB deactivation Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 31/41] ALSA: usb-audio: Unify the code for the next packet size calculation Takashi Iwai
                   ` (10 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Some fields like interface and alt_idx in snd_usb_substream are mostly
useless now as they can be referred via either cur_audiofmt or
data_endpoint assigned to the substream.  Drop those, and also assure
the concurrency about the access of cur_audiofmt field.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.c   |  1 -
 sound/usb/card.h   |  8 --------
 sound/usb/pcm.c    | 24 ++++++------------------
 sound/usb/proc.c   | 19 +++++++++++++------
 sound/usb/quirks.c | 10 +++++-----
 5 files changed, 24 insertions(+), 38 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 58958afcec93..7940b3bff5bc 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -124,7 +124,6 @@ static void snd_usb_stream_disconnect(struct snd_usb_stream *as)
 		subs = &as->substream[idx];
 		if (!subs->num_formats)
 			continue;
-		subs->interface = -1;
 		subs->data_endpoint = NULL;
 		subs->sync_endpoint = NULL;
 	}
diff --git a/sound/usb/card.h b/sound/usb/card.h
index f58c3769b058..1dd7a514d1d5 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -140,18 +140,10 @@ struct snd_usb_substream {
 	struct usb_device *dev;
 	struct snd_pcm_substream *pcm_substream;
 	int direction;	/* playback or capture */
-	int interface;	/* current interface */
 	int endpoint;	/* assigned endpoint */
 	const struct audioformat *cur_audiofmt;	/* current audioformat pointer (for hw_params callback) */
 	struct snd_usb_power_domain *str_pd;	/* UAC3 Power Domain for streaming path */
-	snd_pcm_format_t pcm_format;	/* current audio format (for hw_params callback) */
-	unsigned int channels;		/* current number of channels (for hw_params callback) */
 	unsigned int channels_max;	/* max channels in the all audiofmts */
-	unsigned int cur_rate;		/* current rate (for hw_params callback) */
-	unsigned int period_bytes;	/* current period bytes (for hw_params callback) */
-	unsigned int period_frames;	/* current frames per period */
-	unsigned int buffer_periods;	/* current periods per buffer */
-	unsigned int altset_idx;     /* USB data format: index of alternate setting */
 	unsigned int txfr_quirk:1;	/* allow sub-frame alignment */
 	unsigned int tx_length_quirk:1;	/* add length specifier to transfers */
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index fc028492dd1a..95a6a854dc55 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -797,20 +797,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 					  subs->sync_endpoint);
 	}
 
-	subs->interface = fmt->iface;
-	subs->altset_idx = fmt->altset_idx;
+	mutex_lock(&chip->mutex);
 	subs->cur_audiofmt = fmt;
+	mutex_unlock(&chip->mutex);
 
 	ret = configure_endpoints(chip, subs);
-	if (ret < 0)
-		goto unlock;
-
-	subs->pcm_format = params_format(hw_params);
-	subs->period_bytes = params_period_bytes(hw_params);
-	subs->period_frames = params_period_size(hw_params);
-	subs->buffer_periods = params_periods(hw_params);
-	subs->channels = params_channels(hw_params);
-	subs->cur_rate = params_rate(hw_params);
 
  unlock:
 	if (ret < 0)
@@ -835,9 +826,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 	struct snd_usb_audio *chip = subs->stream->chip;
 
 	snd_media_stop_pipeline(subs);
+	mutex_lock(&chip->mutex);
 	subs->cur_audiofmt = NULL;
-	subs->cur_rate = 0;
-	subs->period_bytes = 0;
+	mutex_unlock(&chip->mutex);
 	if (!snd_usb_lock_shutdown(chip)) {
 		if (stop_endpoints(subs))
 			sync_pending_stops(subs);
@@ -1274,8 +1265,6 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream)
 	struct snd_usb_substream *subs = &as->substream[direction];
 	int ret;
 
-	subs->interface = -1;
-	subs->altset_idx = 0;
 	runtime->hw = snd_usb_hardware;
 	runtime->private_data = subs;
 	subs->pcm_substream = substream;
@@ -1308,7 +1297,6 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
 	snd_media_stop_pipeline(subs);
 
 	if (!snd_usb_lock_shutdown(subs->stream->chip)) {
-		subs->interface = -1;
 		ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D1);
 		snd_usb_unlock_shutdown(subs->stream->chip);
 		if (ret < 0)
@@ -1570,10 +1558,10 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 	}
 	bytes = frames * ep->stride;
 
-	if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
+	if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
 		     subs->cur_audiofmt->dsd_dop)) {
 		fill_playback_urb_dsd_dop(subs, urb, bytes);
-	} else if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U8 &&
+	} else if (unlikely(ep->cur_format == SNDRV_PCM_FORMAT_DSD_U8 &&
 			   subs->cur_audiofmt->dsd_bitrev)) {
 		/* bit-reverse the bytes */
 		u8 *buf = urb->transfer_buffer;
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 889c550c9f29..447ba32e281c 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -175,32 +175,39 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,
 	}
 }
 
-static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
+static void proc_dump_substream_status(struct snd_usb_audio *chip,
+				       struct snd_usb_substream *subs,
+				       struct snd_info_buffer *buffer)
 {
+	mutex_lock(&chip->mutex);
 	if (subs->running) {
 		snd_iprintf(buffer, "  Status: Running\n");
-		snd_iprintf(buffer, "    Interface = %d\n", subs->interface);
-		snd_iprintf(buffer, "    Altset = %d\n", subs->altset_idx);
+		if (subs->cur_audiofmt) {
+			snd_iprintf(buffer, "    Interface = %d\n", subs->cur_audiofmt->iface);
+			snd_iprintf(buffer, "    Altset = %d\n", subs->cur_audiofmt->altsetting);
+		}
 		proc_dump_ep_status(subs, subs->data_endpoint, subs->sync_endpoint, buffer);
 	} else {
 		snd_iprintf(buffer, "  Status: Stop\n");
 	}
+	mutex_unlock(&chip->mutex);
 }
 
 static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
 	struct snd_usb_stream *stream = entry->private_data;
+	struct snd_usb_audio *chip = stream->chip;
 
-	snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
+	snd_iprintf(buffer, "%s : %s\n", chip->card->longname, stream->pcm->name);
 
 	if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
 		snd_iprintf(buffer, "\nPlayback:\n");
-		proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
+		proc_dump_substream_status(chip, &stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
 		proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
 	}
 	if (stream->substream[SNDRV_PCM_STREAM_CAPTURE].num_formats) {
 		snd_iprintf(buffer, "\nCapture:\n");
-		proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
+		proc_dump_substream_status(chip, &stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
 		proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
 	}
 }
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 5510c8a98447..02f3f6ed9390 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1424,7 +1424,7 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
 	 * by playback substream
 	 */
 	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].interface != -1)
+		if (subs->stream->substream[SNDRV_PCM_STREAM_CAPTURE].cur_audiofmt)
 			return;
 	}
 
@@ -1459,13 +1459,13 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
  */
 static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs)
 {
-
+	unsigned int cur_rate = subs->data_endpoint->cur_rate;
 	/* Convert sample rate value to little endian */
 	u8 sr[3];
 
-	sr[0] = subs->cur_rate & 0xff;
-	sr[1] = (subs->cur_rate >> 8) & 0xff;
-	sr[2] = (subs->cur_rate >> 16) & 0xff;
+	sr[0] = cur_rate & 0xff;
+	sr[1] = (cur_rate >> 8) & 0xff;
+	sr[2] = (cur_rate >> 16) & 0xff;
 
 	/* Configure device */
 	usb_set_interface(subs->dev, 0, 1);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 31/41] ALSA: usb-audio: Unify the code for the next packet size calculation
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (29 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 30/41] ALSA: usb-audio: Drop unneeded snd_usb_substream fields Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 32/41] ALSA: usb-audio: Simplify rate_min/max and rates set up Takashi Iwai
                   ` (9 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

There are two places calculating the next packet size for the playback
stream in the exactly same way.  Provide the single helper for this
purpose and use it from both places gracefully.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/endpoint.c | 40 ++++++++++++++++++++++++----------------
 sound/usb/endpoint.h |  4 ++--
 sound/usb/pcm.c      |  8 +-------
 3 files changed, 27 insertions(+), 25 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 35c84c2264e1..5d618724bd75 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -121,13 +121,13 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep)
 }
 
 /*
- * For streaming based on information derived from sync endpoints,
- * prepare_outbound_urb_sizes() will call slave_next_packet_size() to
- * determine the number of samples to be sent in the next packet.
+ * Return the number of samples to be sent in the next packet
+ * for streaming based on information derived from sync endpoints
  *
- * For implicit feedback, slave_next_packet_size() is unused.
+ * This won't be used for implicit feedback which takes the packet size
+ * returned from the sync source
  */
-int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep)
+static int slave_next_packet_size(struct snd_usb_endpoint *ep)
 {
 	unsigned long flags;
 	int ret;
@@ -145,11 +145,10 @@ int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep)
 }
 
 /*
- * For adaptive and synchronous endpoints, prepare_outbound_urb_sizes()
- * will call next_packet_size() to determine the number of samples to be
- * sent in the next packet.
+ * Return the number of samples to be sent in the next packet
+ * for adaptive and synchronous endpoints
  */
-int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
+static int next_packet_size(struct snd_usb_endpoint *ep)
 {
 	int ret;
 
@@ -167,6 +166,21 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
 	return ret;
 }
 
+/*
+ * snd_usb_endpoint_next_packet_size: Return the number of samples to be sent
+ * in the next packet
+ */
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
+				      struct snd_urb_ctx *ctx, int idx)
+{
+	if (ctx->packet_size[idx])
+		return ctx->packet_size[idx];
+	else if (ep->sync_master)
+		return slave_next_packet_size(ep);
+	else
+		return next_packet_size(ep);
+}
+
 static void call_retire_callback(struct snd_usb_endpoint *ep,
 				 struct urb *urb)
 {
@@ -223,13 +237,7 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
 		unsigned int length;
 		int counts;
 
-		if (ctx->packet_size[i])
-			counts = ctx->packet_size[i];
-		else if (ep->sync_master)
-			counts = snd_usb_endpoint_slave_next_packet_size(ep);
-		else
-			counts = snd_usb_endpoint_next_packet_size(ep);
-
+		counts = snd_usb_endpoint_next_packet_size(ep, ctx, i);
 		length = counts * ep->stride; /* number of silent bytes */
 		offset = offs * ep->stride + extra * i;
 		urb->iso_frame_desc[i].offset = offset;
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 201011d89659..11e3bb839fd7 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -45,7 +45,7 @@ void snd_usb_endpoint_release(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct snd_usb_endpoint *ep);
 
 int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
-int snd_usb_endpoint_slave_next_packet_size(struct snd_usb_endpoint *ep);
-int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
+				      struct snd_urb_ctx *ctx, int idx);
 
 #endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 95a6a854dc55..5953e22a72c5 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1512,13 +1512,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
 	spin_lock_irqsave(&subs->lock, flags);
 	subs->frame_limit += ep->max_urb_frames;
 	for (i = 0; i < ctx->packets; i++) {
-		if (ctx->packet_size[i])
-			counts = ctx->packet_size[i];
-		else if (ep->sync_master)
-			counts = snd_usb_endpoint_slave_next_packet_size(ep);
-		else
-			counts = snd_usb_endpoint_next_packet_size(ep);
-
+		counts = snd_usb_endpoint_next_packet_size(ep, ctx, i);
 		/* set up descriptor */
 		urb->iso_frame_desc[i].offset = frames * ep->stride;
 		urb->iso_frame_desc[i].length = counts * ep->stride;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 32/41] ALSA: usb-audio: Simplify rate_min/max and rates set up
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (30 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 31/41] ALSA: usb-audio: Unify the code for the next packet size calculation Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 33/41] ALSA: usb-audio: Replace slave/master terms Takashi Iwai
                   ` (8 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

There are multiple places in format.c performing the similar code for
setting the rate_min, rate_max and rates fields.  This patch unifies
those in a helper function and calls it at the end of the parser phase
so that all rate_table entries have been already determined.

No functional changes, just a minor code refactoring.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/format.c | 53 ++++++++++++++++++++++++-----------------------------
 1 file changed, 24 insertions(+), 29 deletions(-)

diff --git a/sound/usb/format.c b/sound/usb/format.c
index 7641716f0c6c..93459ba228d3 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -164,6 +164,23 @@ static int set_fixed_rate(struct audioformat *fp, int rate, int rate_bits)
 	return 0;
 }
 
+/* set up rate_min, rate_max and rates from the rate table */
+static void set_rate_table_min_max(struct audioformat *fp)
+{
+	unsigned int rate;
+	int i;
+
+	fp->rate_min = INT_MAX;
+	fp->rate_max = 0;
+	fp->rates = 0;
+	for (i = 0; i < fp->nr_rates; i++) {
+		rate = fp->rate_table[i];
+		fp->rate_min = min(fp->rate_min, rate);
+		fp->rate_max = max(fp->rate_max, rate);
+		fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+	}
+}
+
 /*
  * parse the format descriptor and stores the possible sample rates
  * on the audioformat table (audio class v1).
@@ -198,7 +215,6 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
 			return -ENOMEM;
 
 		fp->nr_rates = 0;
-		fp->rate_min = fp->rate_max = 0;
 		for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
 			unsigned int rate = combine_triple(&fmt[idx]);
 			if (!rate)
@@ -217,13 +233,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
 			     chip->usb_id == USB_ID(0x041e, 0x4068)))
 				rate = 8000;
 
-			fp->rate_table[fp->nr_rates] = rate;
-			if (!fp->rate_min || rate < fp->rate_min)
-				fp->rate_min = rate;
-			if (!fp->rate_max || rate > fp->rate_max)
-				fp->rate_max = rate;
-			fp->rates |= snd_pcm_rate_to_rate_bit(rate);
-			fp->nr_rates++;
+			fp->rate_table[fp->nr_rates++] = rate;
 		}
 		if (!fp->nr_rates) {
 			usb_audio_info(chip,
@@ -231,6 +241,7 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
 				       fp->iface, fp->altsetting);
 			return -EINVAL;
 		}
+		set_rate_table_min_max(fp);
 	} else {
 		/* continuous rates */
 		fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
@@ -336,8 +347,6 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
 {
 	int i, nr_rates = 0;
 
-	fp->rates = fp->rate_min = fp->rate_max = 0;
-
 	for (i = 0; i < nr_triplets; i++) {
 		int min = combine_quad(&data[2 + 12 * i]);
 		int max = combine_quad(&data[6 + 12 * i]);
@@ -373,12 +382,6 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
 
 			if (fp->rate_table)
 				fp->rate_table[nr_rates] = rate;
-			if (!fp->rate_min || rate < fp->rate_min)
-				fp->rate_min = rate;
-			if (!fp->rate_max || rate > fp->rate_max)
-				fp->rate_max = rate;
-			fp->rates |= snd_pcm_rate_to_rate_bit(rate);
-
 			nr_rates++;
 			if (nr_rates >= MAX_NR_RATES) {
 				usb_audio_err(chip, "invalid uac2 rates\n");
@@ -459,9 +462,6 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
 	struct usb_device *dev = chip->dev;
 	unsigned int *table;
 	unsigned int nr_rates;
-	unsigned int rate_min = 0x7fffffff;
-	unsigned int rate_max = 0;
-	unsigned int rates = 0;
 	int i, err;
 
 	table = kcalloc(fp->nr_rates, sizeof(*table), GFP_KERNEL);
@@ -478,14 +478,8 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
 		if (err < 0)
 			continue;
 
-		if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting)) {
+		if (check_valid_altsetting_v2v3(chip, fp->iface, fp->altsetting))
 			table[nr_rates++] = fp->rate_table[i];
-			if (rate_min > fp->rate_table[i])
-				rate_min = fp->rate_table[i];
-			if (rate_max < fp->rate_table[i])
-				rate_max = fp->rate_table[i];
-			rates |= snd_pcm_rate_to_rate_bit(fp->rate_table[i]);
-		}
 	}
 
 	if (!nr_rates) {
@@ -503,9 +497,6 @@ static int validate_sample_rate_table_v2v3(struct snd_usb_audio *chip,
 	kfree(fp->rate_table);
 	fp->rate_table = table;
 	fp->nr_rates = nr_rates;
-	fp->rate_min = rate_min;
-	fp->rate_max = rate_max;
-	fp->rates = rates;
 	return 0;
 }
 
@@ -602,6 +593,10 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
 	parse_uac2_sample_rate_range(chip, fp, nr_triplets, data);
 
 	ret = validate_sample_rate_table_v2v3(chip, fp, clock);
+	if (ret < 0)
+		goto err_free;
+
+	set_rate_table_min_max(fp);
 
 err_free:
 	kfree(data);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 33/41] ALSA: usb-audio: Replace slave/master terms
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (31 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 32/41] ALSA: usb-audio: Simplify rate_min/max and rates set up Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 34/41] ALSA: usb-audio: Use unsigned char for iface and altsettings fields Takashi Iwai
                   ` (7 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Follow the inclusive terminology, just replace sync_master/sync_slave
with sync_source/sync_sink.  It's also a bit clearer from its meaning,
too.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     |  4 ++--
 sound/usb/endpoint.c | 28 ++++++++++++++--------------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 1dd7a514d1d5..3e16b9288693 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -71,8 +71,8 @@ struct snd_usb_endpoint {
 				 struct urb *urb);
 
 	struct snd_usb_substream *data_subs;
-	struct snd_usb_endpoint *sync_master;
-	struct snd_usb_endpoint *sync_slave;
+	struct snd_usb_endpoint *sync_source;
+	struct snd_usb_endpoint *sync_sink;
 
 	struct snd_urb_ctx urb[MAX_URBS];
 
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 5d618724bd75..5f1d5f1ed8db 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -175,7 +175,7 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
 {
 	if (ctx->packet_size[idx])
 		return ctx->packet_size[idx];
-	else if (ep->sync_master)
+	else if (ep->sync_source)
 		return slave_next_packet_size(ep);
 	else
 		return next_packet_size(ep);
@@ -205,16 +205,16 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
 			       struct snd_urb_ctx *urb_ctx)
 {
 	struct urb *urb = urb_ctx->urb;
-	struct snd_usb_endpoint *sync_slave;
+	struct snd_usb_endpoint *sync_sink;
 
 	if (unlikely(ep->skip_packets > 0)) {
 		ep->skip_packets--;
 		return;
 	}
 
-	sync_slave = READ_ONCE(ep->sync_slave);
-	if (sync_slave)
-		snd_usb_handle_sync_urb(sync_slave, ep, urb);
+	sync_sink = READ_ONCE(ep->sync_sink);
+	if (sync_sink)
+		snd_usb_handle_sync_urb(sync_sink, ep, urb);
 
 	call_retire_callback(ep, urb);
 }
@@ -708,7 +708,7 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip,
 			       struct snd_usb_endpoint *data_ep,
 			       struct snd_usb_endpoint *sync_ep)
 {
-	data_ep->sync_master = sync_ep;
+	data_ep->sync_source = sync_ep;
 }
 
 /*
@@ -802,7 +802,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
 			alive, ep->ep_num);
 	clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
-	ep->sync_slave = NULL;
+	ep->sync_sink = NULL;
 	snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
 
 	return 0;
@@ -969,9 +969,9 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
 		packs_per_ms = 1;
 		max_packs_per_urb = MAX_PACKS;
 	}
-	if (ep->sync_master && !ep->implicit_fb_sync)
+	if (ep->sync_source && !ep->implicit_fb_sync)
 		max_packs_per_urb = min(max_packs_per_urb,
-					1U << ep->sync_master->syncinterval);
+					1U << ep->sync_source->syncinterval);
 	max_packs_per_urb = max(1u, max_packs_per_urb >> ep->datainterval);
 
 	/*
@@ -1015,7 +1015,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
 		minsize = (ep->freqn >> (16 - ep->datainterval)) *
 				(frame_bits >> 3);
 		/* with sync from device, assume it can be 12% lower */
-		if (ep->sync_master)
+		if (ep->sync_source)
 			minsize -= minsize >> 3;
 		minsize = max(minsize, 1u);
 
@@ -1272,8 +1272,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 	if (atomic_read(&ep->chip->shutdown))
 		return -EBADFD;
 
-	if (ep->sync_master)
-		WRITE_ONCE(ep->sync_master->sync_slave, ep);
+	if (ep->sync_source)
+		WRITE_ONCE(ep->sync_source->sync_sink, ep);
 
 	usb_audio_dbg(ep->chip, "Starting %s EP 0x%x (running %d)\n",
 		      ep_type_name(ep->type), ep->ep_num,
@@ -1366,8 +1366,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
 	if (snd_BUG_ON(!atomic_read(&ep->running)))
 		return;
 
-	if (ep->sync_master)
-		WRITE_ONCE(ep->sync_master->sync_slave, NULL);
+	if (ep->sync_source)
+		WRITE_ONCE(ep->sync_source->sync_sink, NULL);
 
 	if (!atomic_dec_return(&ep->running))
 		stop_and_unlink_urbs(ep, false, false);
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 34/41] ALSA: usb-audio: Use unsigned char for iface and altsettings fields
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (32 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 33/41] ALSA: usb-audio: Replace slave/master terms Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 35/41] ALSA: usb-audio: Show sync endpoint information in proc outputs Takashi Iwai
                   ` (6 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Just for consistency, use unsigned char for iface and altsetting in
allover places.  Also rearrange the field positions of
snd_usb_endpiont and tidy up with some comments.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/card.h     | 11 +++++++----
 sound/usb/endpoint.c |  2 +-
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index 3e16b9288693..6a027c349194 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -16,7 +16,7 @@ struct audioformat {
 	unsigned int fmt_type;		/* USB audio format type (1-3) */
 	unsigned int fmt_bits;		/* number of significant bits */
 	unsigned int frame_size;	/* samples per frame for non-audio */
-	int iface;			/* interface number */
+	unsigned char iface;		/* interface number */
 	unsigned char altsetting;	/* corresponding alternate setting */
 	unsigned char altset_idx;	/* array index of altenate setting */
 	unsigned char attributes;	/* corresponding attributes of cs endpoint */
@@ -63,7 +63,12 @@ struct snd_usb_endpoint {
 	atomic_t running;	/* running status */
 	int ep_num;		/* the referenced endpoint number */
 	int type;		/* SND_USB_ENDPOINT_TYPE_* */
-	unsigned long flags;
+
+	unsigned char iface;		/* interface number */
+	unsigned char altsetting;	/* corresponding alternate setting */
+	unsigned char ep_idx;		/* endpoint array index */
+
+	unsigned long flags;	/* running bit flags */
 
 	void (*prepare_data_urb) (struct snd_usb_substream *subs,
 				  struct urb *urb);
@@ -112,8 +117,6 @@ struct snd_usb_endpoint {
 	unsigned int syncinterval;	/* P for adaptive mode, 0 otherwise */
 	unsigned char silence_value;
 	unsigned int stride;
-	int iface, altsetting;
-	unsigned char ep_idx;		/* endpoint array index */
 	int skip_packets;		/* quirks for devices to ignore the first n packets
 					   in a stream */
 	bool implicit_fb_sync;		/* syncs with implicit feedback */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 5f1d5f1ed8db..162da7a50046 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -762,7 +762,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
 		      ep->ep_num, ep->opened);
 	if (!--ep->opened) {
 		endpoint_set_interface(chip, ep, false);
-		ep->iface = -1;
+		ep->iface = 0;
 		ep->altsetting = 0;
 		ep->cur_audiofmt = NULL;
 		ep->cur_rate = 0;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 35/41] ALSA: usb-audio: Show sync endpoint information in proc outputs
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (33 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 34/41] ALSA: usb-audio: Use unsigned char for iface and altsettings fields Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 36/41] ALSA: usb-audio: Quirk for BOSS GT-001 Takashi Iwai
                   ` (5 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

Now the sync endpoints have been parsed at the beginning and won't be
changed dynamically, let's show them in the proc outputs for helping
debugging.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/proc.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index 447ba32e281c..e9bbaea7b2fa 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -108,7 +108,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
 					    snd_pcm_format_name(fmt));
 		snd_iprintf(buffer, "\n");
 		snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
-		snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
+		snd_iprintf(buffer, "    Endpoint: 0x%02x (%d %s) (%s)\n",
+			    fp->endpoint,
 			    fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
 			    fp->endpoint & USB_DIR_IN ? "IN" : "OUT",
 			    sync_types[(fp->ep_attr & USB_ENDPOINT_SYNCTYPE) >> 2]);
@@ -150,6 +151,19 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
 			snd_iprintf(buffer, "\n");
 		}
 
+		if (fp->sync_ep) {
+			snd_iprintf(buffer, "    Sync Endpoint: 0x%02x (%d %s)\n",
+				    fp->sync_ep,
+				    fp->sync_ep & USB_ENDPOINT_NUMBER_MASK,
+				    fp->sync_ep & USB_DIR_IN ? "IN" : "OUT");
+			snd_iprintf(buffer, "    Sync EP Interface: %d\n",
+				    fp->sync_iface);
+			snd_iprintf(buffer, "    Sync EP Altset: %d\n",
+				    fp->sync_altsetting);
+			snd_iprintf(buffer, "    Implicit Feedback Mode: %s\n",
+				    fp->implicit_fb ? "Yes" : "No");
+		}
+
 		// snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
 		// snd_iprintf(buffer, "    EP Attribute = %#x\n", fp->attributes);
 	}
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 36/41] ALSA: usb-audio: Quirk for BOSS GT-001
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (34 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 35/41] ALSA: usb-audio: Show sync endpoint information in proc outputs Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 37/41] ALSA: usb-audio: Factor out the implicit feedback quirk code Takashi Iwai
                   ` (4 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The capture stream of BOSS GT-001 seems always requiring to be tied
with the playback stream.  OTOH, the playback stream of this device
doesn't seem working in the implicit fb mode, per se, since the
playback must be running before the capture stream.

This patch tries to address the points above:
- Avoid the implicit fb mode for the playback
- Set up a fake sync EP for the capture stream with the hard-coded
  playback stream using the implicit fb mode

Reported-by: Keith Milner <kamilner@superlative.org>
Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/pcm.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 5953e22a72c5..676acc20595b 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -403,6 +403,9 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	case USB_ID(0x0582, 0x01d8): /* BOSS Katana */
 		/* BOSS Katana amplifiers do not need quirks */
 		return 0;
+	case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */
+		/* BOSS GT-001 needs no implicit fb for playback */
+		return 0;
 	}
 
 	/* Generic UAC2 implicit feedback */
@@ -454,6 +457,30 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	return 1;
 }
 
+static int audioformat_capture_quirk(struct snd_usb_audio *chip,
+				     struct audioformat *fmt,
+				     struct usb_host_interface *alts)
+{
+	struct usb_device *dev = chip->dev;
+
+	switch (chip->usb_id) {
+	case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */
+		if (!snd_usb_get_host_interface(chip, 0x01, 0x01))
+			return 0;
+		fmt->sync_ep = 0x0d;
+		fmt->sync_iface = 0x01;
+		fmt->sync_altsetting = 0x01;
+		fmt->sync_ep_idx = 0;
+		fmt->implicit_fb = 1;
+		dev_dbg(&dev->dev, "%d:%d: added fake capture sync sync_ep=%x, iface=%d, alt=%d\n",
+			fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
+			fmt->sync_altsetting);
+		return 1;
+	}
+	return 0;
+
+}
+
 int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 				    struct audioformat *fmt)
 {
@@ -474,6 +501,10 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 		err = audioformat_implicit_fb_quirk(chip, fmt, alts);
 		if (err > 0)
 			return 0;
+	} else {
+		err = audioformat_capture_quirk(chip, fmt, alts);
+		if (err > 0)
+			return 0;
 	}
 
 	if (altsd->bNumEndpoints < 2)
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 37/41] ALSA: usb-audio: Factor out the implicit feedback quirk code
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (35 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 36/41] ALSA: usb-audio: Quirk for BOSS GT-001 Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 38/41] ALSA: usb-audio: Add generic implicit fb parsing Takashi Iwai
                   ` (3 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

The code dealing with the implicit feedback mode grew recently, and
it's becoming messy.  As we receive more and more devices that need
the similar handling, it's better to be processed through a table
instead of the open code.

This patch moves the code that is relevant with parsing the implicit
feedback mode and some helpers into another file, implicit.c.  The
detection and the setup of the implicit feedback sync EPs are
rewritten to use the ID/class matching table instead.

There should be no functional changes.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/Makefile   |   1 +
 sound/usb/implicit.c | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sound/usb/implicit.h |  14 +++
 sound/usb/pcm.c      | 320 +++--------------------------------------------
 4 files changed, 376 insertions(+), 306 deletions(-)
 create mode 100644 sound/usb/implicit.c
 create mode 100644 sound/usb/implicit.h

diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 56031026b113..9ccb21a4ff8a 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -8,6 +8,7 @@ snd-usb-audio-objs := 	card.o \
 			endpoint.o \
 			format.o \
 			helper.o \
+			implicit.o \
 			mixer.o \
 			mixer_quirks.o \
 			mixer_scarlett.o \
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
new file mode 100644
index 000000000000..bc7edecff946
--- /dev/null
+++ b/sound/usb/implicit.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Special handling for implicit feedback mode
+//
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "helper.h"
+#include "implicit.h"
+
+enum {
+	IMPLICIT_FB_NONE,
+	IMPLICIT_FB_FIXED,
+};
+
+struct snd_usb_implicit_fb_match {
+	unsigned int id;
+	unsigned int iface_class;
+	unsigned int ep_num;
+	unsigned int iface;
+	int type;
+};
+
+#define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \
+	{ .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\
+	    .iface = (ifnum) }
+#define IMPLICIT_FB_SKIP_DEV(vend, prod) \
+	{ .id = USB_ID(vend, prod), .type = IMPLICIT_FB_NONE }
+
+/* Implicit feedback quirk table for playback */
+static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
+	/* Fixed EP */
+	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */
+	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */
+	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */
+	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */
+	IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
+	IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */
+	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */
+	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
+	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
+	IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
+	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */
+	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */
+	IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
+	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */
+	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */
+	IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
+	IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
+	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
+
+	/* Special matching */
+	{ .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_AUDIO,
+	  .type = IMPLICIT_FB_NONE },		/* MicroBook IIc */
+	/* ep = 0x84, ifnum = 0 */
+	{ .id = USB_ID(0x07fd, 0x0004), .iface_class = USB_CLASS_VENDOR_SPEC,
+	  .type = IMPLICIT_FB_FIXED,
+	  .ep_num = 0x84, .iface = 0 },		/* MOTU MicroBook II */
+
+	/* No quirk */
+	IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8),	/* BOSS Katana */
+
+	/* No quirk for playback but with capture quirk (see below) */
+	IMPLICIT_FB_SKIP_DEV(0x0582, 0x01e5),	/* BOSS GT-001 */
+
+	{} /* terminator */
+};
+
+/* Implicit feedback quirk table for capture */
+static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
+	IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */
+
+	{} /* terminator */
+};
+
+/* set up sync EP information on the audioformat */
+static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
+				   struct audioformat *fmt,
+				   int ep, int ifnum,
+				   const struct usb_host_interface *alts)
+{
+	struct usb_interface *iface;
+
+	if (!alts) {
+		iface = usb_ifnum_to_if(chip->dev, ifnum);
+		if (!iface || iface->num_altsetting < 2)
+			return 0;
+		alts = &iface->altsetting[1];
+	}
+
+	fmt->sync_ep = ep;
+	fmt->sync_iface = ifnum;
+	fmt->sync_altsetting = alts->desc.bAlternateSetting;
+	fmt->sync_ep_idx = 0;
+	fmt->implicit_fb = 1;
+	usb_audio_dbg(chip,
+		      "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n",
+		      fmt->iface, fmt->altsetting,
+		      (ep & USB_DIR_IN) ? "playback" : "capture",
+		      fmt->sync_ep, fmt->sync_iface, fmt->sync_altsetting);
+	return 1;
+}
+
+/* Check whether the given UAC2 iface:altset points to an implicit fb source */
+static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip,
+					struct audioformat *fmt,
+					unsigned int ifnum,
+					unsigned int altsetting)
+{
+	struct usb_host_interface *alts;
+	struct usb_endpoint_descriptor *epd;
+
+	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
+	if (!alts)
+		return 0;
+	if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO ||
+	    alts->desc.bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING ||
+	    alts->desc.bInterfaceProtocol != UAC_VERSION_2 ||
+	    alts->desc.bNumEndpoints < 1)
+		return 0;
+	epd = get_endpoint(alts, 0);
+	if (!usb_endpoint_is_isoc_in(epd) ||
+	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
+					USB_ENDPOINT_USAGE_IMPLICIT_FB)
+		return 0;
+	return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+				       ifnum, alts);
+}
+
+/* Like the function above, but specific to Roland with vendor class and hack */
+static int add_roland_implicit_fb(struct snd_usb_audio *chip,
+				  struct audioformat *fmt,
+				  unsigned int ifnum,
+				  unsigned int altsetting)
+{
+	struct usb_host_interface *alts;
+	struct usb_endpoint_descriptor *epd;
+
+	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
+	if (!alts)
+		return 0;
+	if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
+	    (alts->desc.bInterfaceSubClass != 2 &&
+	     alts->desc.bInterfaceProtocol != 2) ||
+	    alts->desc.bNumEndpoints < 1)
+		return 0;
+	epd = get_endpoint(alts, 0);
+	if (!usb_endpoint_is_isoc_in(epd) ||
+	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
+					USB_ENDPOINT_USAGE_IMPLICIT_FB)
+		return 0;
+	return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+				       ifnum, alts);
+}
+
+static const struct snd_usb_implicit_fb_match *
+find_implicit_fb_entry(struct snd_usb_audio *chip,
+		       const struct snd_usb_implicit_fb_match *match,
+		       const struct usb_host_interface *alts)
+{
+	for (; match->id; match++)
+		if (match->id == chip->usb_id &&
+		    (!match->iface_class ||
+		     (alts->desc.bInterfaceClass == match->iface_class)))
+			return match;
+
+	return NULL;
+}
+
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
+static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
+					 struct audioformat *fmt,
+					 struct usb_host_interface *alts)
+{
+	const struct snd_usb_implicit_fb_match *p;
+	unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
+
+	p = find_implicit_fb_entry(chip, playback_implicit_fb_quirks, alts);
+	if (p) {
+		switch (p->type) {
+		case IMPLICIT_FB_NONE:
+			return 0; /* No quirk */
+		case IMPLICIT_FB_FIXED:
+			return add_implicit_fb_sync_ep(chip, fmt, p->ep_num,
+						       p->iface, NULL);
+		}
+	}
+
+	/* Generic UAC2 implicit feedback */
+	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+	    alts->desc.bInterfaceClass == USB_CLASS_AUDIO &&
+	    alts->desc.bInterfaceProtocol == UAC_VERSION_2 &&
+	    alts->desc.bNumEndpoints == 1) {
+		if (add_generic_uac2_implicit_fb(chip, fmt,
+						 alts->desc.bInterfaceNumber + 1,
+						 alts->desc.bAlternateSetting))
+			return 1;
+	}
+
+	/* Roland/BOSS implicit feedback with vendor spec class */
+	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
+	    alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
+	    alts->desc.bInterfaceProtocol == 2 &&
+	    alts->desc.bNumEndpoints == 1 &&
+	    USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) {
+		if (add_roland_implicit_fb(chip, fmt,
+					   alts->desc.bInterfaceNumber + 1,
+					   alts->desc.bAlternateSetting))
+			return 1;
+	}
+
+	/* No quirk */
+	return 0;
+}
+
+/* same for capture, but only handling FIXED entry */
+static int audioformat_capture_quirk(struct snd_usb_audio *chip,
+				     struct audioformat *fmt,
+				     struct usb_host_interface *alts)
+{
+	const struct snd_usb_implicit_fb_match *p;
+
+	p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts);
+	if (p && p->type == IMPLICIT_FB_FIXED)
+		return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, p->iface,
+					       NULL);
+	return 0;
+}
+
+/*
+ * Parse altset and set up implicit feedback endpoint on the audioformat
+ */
+int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio *chip,
+				    struct audioformat *fmt,
+				    struct usb_host_interface *alts)
+{
+	if (fmt->endpoint & USB_DIR_IN)
+		return audioformat_capture_quirk(chip, fmt, alts);
+	else
+		return audioformat_implicit_fb_quirk(chip, fmt, alts);
+}
+
+/*
+ * Return the score of matching two audioformats.
+ * Veto the audioformat if:
+ * - It has no channels for some reason.
+ * - Requested PCM format is not supported.
+ * - Requested sample rate is not supported.
+ */
+static int match_endpoint_audioformats(struct snd_usb_substream *subs,
+				       const struct audioformat *fp,
+				       int rate, int channels,
+				       snd_pcm_format_t pcm_format)
+{
+	int i, score;
+
+	if (fp->channels < 1)
+		return 0;
+
+	if (!(fp->formats & pcm_format_to_bits(pcm_format)))
+		return 0;
+
+	if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
+		if (rate < fp->rate_min || rate > fp->rate_max)
+			return 0;
+	} else {
+		for (i = 0; i < fp->nr_rates; i++) {
+			if (fp->rate_table[i] == rate)
+				break;
+		}
+		if (i >= fp->nr_rates)
+			return 0;
+	}
+
+	score = 1;
+	if (fp->channels == channels)
+		score++;
+
+	return score;
+}
+
+static struct snd_usb_substream *
+find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num,
+			int fmt_type)
+{
+	struct snd_usb_stream *as;
+	struct snd_usb_substream *subs;
+
+	list_for_each_entry(as, &chip->pcm_list, list) {
+		subs = &as->substream[stream];
+		if (as->fmt_type == fmt_type && subs->ep_num == ep_num)
+			return subs;
+	}
+
+	return NULL;
+}
+
+/*
+ * Return the audioformat that is suitable for the implicit fb
+ */
+const struct audioformat *
+snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+				     const struct audioformat *target,
+				     const struct snd_pcm_hw_params *params,
+				     int stream)
+{
+	struct snd_usb_substream *subs;
+	const struct audioformat *fp, *sync_fmt;
+	int score, high_score;
+
+	/* When sharing the same altset, use the original audioformat */
+	if (target->iface == target->sync_iface &&
+	    target->altsetting == target->sync_altsetting)
+		return target;
+
+	subs = find_matching_substream(chip, stream, target->sync_ep,
+				       target->fmt_type);
+	if (!subs)
+		return NULL;
+
+	sync_fmt = NULL;
+	high_score = 0;
+	list_for_each_entry(fp, &subs->fmt_list, list) {
+		score = match_endpoint_audioformats(subs, fp,
+						    params_rate(params),
+						    params_channels(params),
+						    params_format(params));
+		if (score > high_score) {
+			sync_fmt = fp;
+			high_score = score;
+		}
+	}
+
+	return sync_fmt;
+}
+
diff --git a/sound/usb/implicit.h b/sound/usb/implicit.h
new file mode 100644
index 000000000000..ccb415a0ea86
--- /dev/null
+++ b/sound/usb/implicit.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __USBAUDIO_IMPLICIT_H
+#define __USBAUDIO_IMPLICIT_H
+
+int snd_usb_parse_implicit_fb_quirk(struct snd_usb_audio *chip,
+				    struct audioformat *fmt,
+				    struct usb_host_interface *alts);
+const struct audioformat *
+snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+				     const struct audioformat *target,
+				     const struct snd_pcm_hw_params *params,
+				     int stream);
+
+#endif /* __USBAUDIO_IMPLICIT_H */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 676acc20595b..56079901769f 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -23,6 +23,7 @@
 #include "clock.h"
 #include "power.h"
 #include "media.h"
+#include "implicit.h"
 
 #define SUBSTREAM_FLAG_DATA_EP_STARTED	0
 #define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
@@ -276,211 +277,7 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-/* Check whether the given iface:altsetting points to an implicit fb source */
-static bool search_generic_implicit_fb(struct snd_usb_audio *chip, int ifnum,
-				       unsigned int altsetting,
-				       struct usb_host_interface **altsp,
-				       unsigned int *ep)
-{
-	struct usb_host_interface *alts;
-	struct usb_interface_descriptor *altsd;
-	struct usb_endpoint_descriptor *epd;
-
-	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
-	if (!alts)
-		return false;
-	altsd = get_iface_desc(alts);
-	if (altsd->bInterfaceClass != USB_CLASS_AUDIO ||
-	    altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING ||
-	    altsd->bInterfaceProtocol != UAC_VERSION_2 ||
-	    altsd->bNumEndpoints < 1)
-		return false;
-	epd = get_endpoint(alts, 0);
-	if (!usb_endpoint_is_isoc_in(epd) ||
-	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
-					USB_ENDPOINT_USAGE_IMPLICIT_FB)
-		return false;
-	*ep = epd->bEndpointAddress;
-	*altsp = alts;
-	return true;
-}
-
-/* Like the function above, but specific to Roland with vendor class and hack */
-static bool search_roland_implicit_fb(struct snd_usb_audio *chip, int ifnum,
-				      unsigned int altsetting,
-				      struct usb_host_interface **altsp,
-				      unsigned int *ep)
-{
-	struct usb_host_interface *alts;
-	struct usb_interface_descriptor *altsd;
-	struct usb_endpoint_descriptor *epd;
-
-	alts = snd_usb_get_host_interface(chip, ifnum, altsetting);
-	if (!alts)
-		return false;
-	altsd = get_iface_desc(alts);
-	if (altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
-	    (altsd->bInterfaceSubClass != 2 &&
-	     altsd->bInterfaceProtocol != 2) ||
-	    altsd->bNumEndpoints < 1)
-		return false;
-	epd = get_endpoint(alts, 0);
-	if (!usb_endpoint_is_isoc_in(epd) ||
-	    (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
-					USB_ENDPOINT_USAGE_IMPLICIT_FB)
-		return false;
-	*ep = epd->bEndpointAddress;
-	*altsp = alts;
-	return true;
-}
-
-/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
- * applies. Returns 1 if a quirk was found.
- */
-static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
-					 struct audioformat *fmt,
-					 struct usb_host_interface *alts)
-{
-	struct usb_device *dev = chip->dev;
-	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
-	struct usb_interface *iface;
-	unsigned int attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
-	unsigned int ep;
-	unsigned int ifnum;
-
-	switch (chip->usb_id) {
-	case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
-	case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
-	case USB_ID(0x22f0, 0x0006): /* Allen&Heath Qu-16 */
-		ep = 0x81;
-		ifnum = 3;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
-	case USB_ID(0x0763, 0x2081):
-		ep = 0x81;
-		ifnum = 2;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x2466, 0x8003): /* Fractal Audio Axe-Fx II */
-	case USB_ID(0x0499, 0x172a): /* Yamaha MODX */
-		ep = 0x86;
-		ifnum = 2;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x2466, 0x8010): /* Fractal Audio Axe-Fx III */
-		ep = 0x81;
-		ifnum = 2;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x1686, 0xf029): /* Zoom UAC-2 */
-		ep = 0x82;
-		ifnum = 2;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x1397, 0x0001): /* Behringer UFX1604 */
-	case USB_ID(0x1397, 0x0002): /* Behringer UFX1204 */
-		ep = 0x81;
-		ifnum = 1;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x07fd, 0x0004): /* MOTU MicroBook II/IIc */
-		/* MicroBook IIc */
-		if (altsd->bInterfaceClass == USB_CLASS_AUDIO)
-			return 0;
-
-		/* MicroBook II */
-		ep = 0x84;
-		ifnum = 0;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
-	case USB_ID(0x31e9, 0x0001): /* Solid State Logic SSL2 */
-	case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */
-	case USB_ID(0x0499, 0x172f): /* Steinberg UR22C */
-	case USB_ID(0x0d9a, 0x00df): /* RTX6001 */
-		ep = 0x81;
-		ifnum = 2;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
-	case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
-		ep = 0x82;
-		ifnum = 0;
-		goto add_sync_ep_from_ifnum;
-	case USB_ID(0x0582, 0x01d8): /* BOSS Katana */
-		/* BOSS Katana amplifiers do not need quirks */
-		return 0;
-	case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */
-		/* BOSS GT-001 needs no implicit fb for playback */
-		return 0;
-	}
-
-	/* Generic UAC2 implicit feedback */
-	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
-	    altsd->bInterfaceClass == USB_CLASS_AUDIO &&
-	    altsd->bInterfaceProtocol == UAC_VERSION_2 &&
-	    altsd->bNumEndpoints == 1) {
-		ifnum = altsd->bInterfaceNumber + 1;
-		if (search_generic_implicit_fb(chip, ifnum,
-					       altsd->bAlternateSetting,
-					       &alts, &ep))
-			goto add_sync_ep;
-	}
-
-	/* Roland/BOSS implicit feedback with vendor spec class */
-	if (attr == USB_ENDPOINT_SYNC_ASYNC &&
-	    altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
-	    altsd->bInterfaceProtocol == 2 &&
-	    altsd->bNumEndpoints == 1 &&
-	    USB_ID_VENDOR(chip->usb_id) == 0x0582 /* Roland */) {
-		ifnum = altsd->bInterfaceNumber + 1;
-		if (search_roland_implicit_fb(chip, ifnum,
-					      altsd->bAlternateSetting,
-					      &alts, &ep))
-			goto add_sync_ep;
-	}
-
-	/* No quirk */
-	return 0;
-
-add_sync_ep_from_ifnum:
-	iface = usb_ifnum_to_if(dev, ifnum);
-
-	if (!iface || iface->num_altsetting < 2)
-		return 0;
-
-	alts = &iface->altsetting[1];
-
-add_sync_ep:
-	fmt->sync_ep = ep;
-	fmt->sync_iface = ifnum;
-	fmt->sync_altsetting = alts->desc.bAlternateSetting;
-	fmt->sync_ep_idx = 0;
-	fmt->implicit_fb = 1;
-	dev_dbg(&dev->dev, "%d:%d: found implicit_fb sync_ep=%x, iface=%d, alt=%d\n",
-		fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
-		fmt->sync_altsetting);
-
-	return 1;
-}
-
-static int audioformat_capture_quirk(struct snd_usb_audio *chip,
-				     struct audioformat *fmt,
-				     struct usb_host_interface *alts)
-{
-	struct usb_device *dev = chip->dev;
-
-	switch (chip->usb_id) {
-	case USB_ID(0x0582, 0x01e5): /* BOSS GT-001 */
-		if (!snd_usb_get_host_interface(chip, 0x01, 0x01))
-			return 0;
-		fmt->sync_ep = 0x0d;
-		fmt->sync_iface = 0x01;
-		fmt->sync_altsetting = 0x01;
-		fmt->sync_ep_idx = 0;
-		fmt->implicit_fb = 1;
-		dev_dbg(&dev->dev, "%d:%d: added fake capture sync sync_ep=%x, iface=%d, alt=%d\n",
-			fmt->iface, fmt->altsetting, fmt->sync_ep, fmt->sync_iface,
-			fmt->sync_altsetting);
-		return 1;
-	}
-	return 0;
-
-}
-
+/* Set up sync endpoint */
 int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 				    struct audioformat *fmt)
 {
@@ -496,20 +293,18 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 		return 0;
 	altsd = get_iface_desc(alts);
 
-	is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
-	if (is_playback) {
-		err = audioformat_implicit_fb_quirk(chip, fmt, alts);
-		if (err > 0)
-			return 0;
-	} else {
-		err = audioformat_capture_quirk(chip, fmt, alts);
-		if (err > 0)
-			return 0;
-	}
+	err = snd_usb_parse_implicit_fb_quirk(chip, fmt, alts);
+	if (err > 0)
+		return 0; /* matched */
+
+	/*
+	 * Generic sync EP handling
+	 */
 
 	if (altsd->bNumEndpoints < 2)
 		return 0;
 
+	is_playback = !(get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN);
 	attr = fmt->ep_attr & USB_ENDPOINT_SYNCTYPE;
 	if ((is_playback && (attr == USB_ENDPOINT_SYNC_SYNC ||
 			     attr == USB_ENDPOINT_SYNC_ADAPTIVE)) ||
@@ -569,45 +364,6 @@ int snd_usb_audioformat_set_sync_ep(struct snd_usb_audio *chip,
 	return 0;
 }
 
-/*
- * Return the score of matching two audioformats.
- * Veto the audioformat if:
- * - It has no channels for some reason.
- * - Requested PCM format is not supported.
- * - Requested sample rate is not supported.
- */
-static int match_endpoint_audioformats(struct snd_usb_substream *subs,
-				       const struct audioformat *fp,
-				       int rate, int channels,
-				       snd_pcm_format_t pcm_format)
-{
-	int i, score;
-
-	if (fp->channels < 1)
-		return 0;
-
-	if (!(fp->formats & pcm_format_to_bits(pcm_format)))
-		return 0;
-
-	if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
-		if (rate < fp->rate_min || rate > fp->rate_max)
-			return 0;
-	} else {
-		for (i = 0; i < fp->nr_rates; i++) {
-			if (fp->rate_table[i] == rate)
-				break;
-		}
-		if (i >= fp->nr_rates)
-			return 0;
-	}
-
-	score = 1;
-	if (fp->channels == channels)
-		score++;
-
-	return score;
-}
-
 static int snd_usb_pcm_change_state(struct snd_usb_substream *subs, int state)
 {
 	int ret;
@@ -656,53 +412,6 @@ int snd_usb_pcm_resume(struct snd_usb_stream *as)
 	return 0;
 }
 
-static struct snd_usb_substream *
-find_matching_substream(struct snd_usb_audio *chip, int stream, int ep_num,
-			int fmt_type)
-{
-	struct snd_usb_stream *as;
-	struct snd_usb_substream *subs;
-
-	list_for_each_entry(as, &chip->pcm_list, list) {
-		subs = &as->substream[stream];
-		if (as->fmt_type == fmt_type && subs->ep_num == ep_num)
-			return subs;
-	}
-
-	return NULL;
-}
-
-static const struct audioformat *
-find_implicit_fb_sync_format(struct snd_usb_audio *chip,
-			     const struct audioformat *target,
-			     const struct snd_pcm_hw_params *params,
-			     int stream)
-{
-	struct snd_usb_substream *subs;
-	const struct audioformat *fp, *sync_fmt;
-	int score, high_score;
-
-	subs = find_matching_substream(chip, stream, target->sync_ep,
-				       target->fmt_type);
-	if (!subs)
-		return NULL;
-
-	sync_fmt = NULL;
-	high_score = 0;
-	list_for_each_entry(fp, &subs->fmt_list, list) {
-		score = match_endpoint_audioformats(subs, fp,
-						    params_rate(params),
-						    params_channels(params),
-						    params_format(params));
-		if (score > high_score) {
-			sync_fmt = fp;
-			high_score = score;
-		}
-	}
-
-	return sync_fmt;
-}
-
 static void close_endpoints(struct snd_usb_audio *chip,
 			    struct snd_usb_substream *subs)
 {
@@ -775,11 +484,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 		goto stop_pipeline;
 	}
 
-	if (fmt->implicit_fb &&
-	    (fmt->iface != fmt->sync_iface ||
-	     fmt->altsetting != fmt->sync_altsetting)) {
-		sync_fmt = find_implicit_fb_sync_format(chip, fmt, hw_params,
-							!substream->stream);
+	if (fmt->implicit_fb) {
+		sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
+								hw_params,
+								!substream->stream);
 		if (!sync_fmt) {
 			usb_audio_dbg(chip,
 				      "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 38/41] ALSA: usb-audio: Add generic implicit fb parsing
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (36 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 37/41] ALSA: usb-audio: Factor out the implicit feedback quirk code Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option Takashi Iwai
                   ` (2 subsequent siblings)
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

This patch extends the implicit feedback mode parser code to check the
description more generically, so that the quirk entries can be added
without the explicit EP and interface numbers.  The search is done for
the next and the previous interface of the given altset, and if both
entries are ASYNC mode and the direction matches, it just takes as the
sync endpoint.  The generic parser is applicable only for the playback
stream.

As of now, only a few M-Audio devices have been converted to use this
mode.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/implicit.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 5 deletions(-)

diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index bc7edecff946..16b1fb55b7b9 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -19,6 +19,7 @@
 
 enum {
 	IMPLICIT_FB_NONE,
+	IMPLICIT_FB_GENERIC,
 	IMPLICIT_FB_FIXED,
 };
 
@@ -30,6 +31,8 @@ struct snd_usb_implicit_fb_match {
 	int type;
 };
 
+#define IMPLICIT_FB_GENERIC_DEV(vend, prod) \
+	{ .id = USB_ID(vend, prod), .type = IMPLICIT_FB_GENERIC }
 #define IMPLICIT_FB_FIXED_DEV(vend, prod, ep, ifnum) \
 	{ .id = USB_ID(vend, prod), .type = IMPLICIT_FB_FIXED, .ep_num = (ep),\
 	    .iface = (ifnum) }
@@ -38,19 +41,22 @@ struct snd_usb_implicit_fb_match {
 
 /* Implicit feedback quirk table for playback */
 static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
+	/* Generic matching */
+	IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2080), /* M-Audio FastTrack Ultra */
+	IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2081), /* M-Audio FastTrack Ultra */
+	IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2030), /* M-Audio Fast Track C400 */
+	IMPLICIT_FB_GENERIC_DEV(0x0763, 0x2031), /* M-Audio Fast Track C600 */
+
 	/* Fixed EP */
+	/* FIXME: check the availability of generic matching */
 	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */
 	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */
-	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2080, 0x81, 2), /* M-Audio FastTrack Ultra */
-	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2081, 0x81, 2), /* M-Audio FastTrack Ultra */
 	IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
 	IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */
 	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */
 	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
 	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
 	IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
-	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2030, 0x81, 3), /* M-Audio Fast Track C400 */
-	IMPLICIT_FB_FIXED_DEV(0x0763, 0x2031, 0x81, 3), /* M-Audio Fast Track C600 */
 	IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
 	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */
 	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */
@@ -75,7 +81,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 	{} /* terminator */
 };
 
-/* Implicit feedback quirk table for capture */
+/* Implicit feedback quirk table for capture: only FIXED type */
 static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
 	IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */
 
@@ -162,6 +168,47 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
 				       ifnum, alts);
 }
 
+
+static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
+				     struct audioformat *fmt,
+				     int iface, int altset)
+{
+	struct usb_host_interface *alts;
+	struct usb_endpoint_descriptor *epd;
+
+	alts = snd_usb_get_host_interface(chip, iface, altset);
+	if (!alts)
+		return 0;
+
+	if ((alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC &&
+	     alts->desc.bInterfaceClass != USB_CLASS_AUDIO) ||
+	    alts->desc.bNumEndpoints < 1)
+		return 0;
+	epd = get_endpoint(alts, 0);
+	if (!usb_endpoint_is_isoc_in(epd) ||
+	    (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
+		return 0;
+	return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress,
+				       iface, alts);
+}
+
+/* More generic quirk: look for the sync EP next to the data EP */
+static int add_generic_implicit_fb(struct snd_usb_audio *chip,
+				   struct audioformat *fmt,
+				   struct usb_host_interface *alts)
+{
+	if ((fmt->ep_attr & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
+		return 0;
+
+	if (__add_generic_implicit_fb(chip, fmt,
+				      alts->desc.bInterfaceNumber + 1,
+				      alts->desc.bAlternateSetting))
+		return 1;
+	return __add_generic_implicit_fb(chip, fmt,
+					 alts->desc.bInterfaceNumber - 1,
+					 alts->desc.bAlternateSetting);
+}
+
 static const struct snd_usb_implicit_fb_match *
 find_implicit_fb_entry(struct snd_usb_audio *chip,
 		       const struct snd_usb_implicit_fb_match *match,
@@ -189,6 +236,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 	p = find_implicit_fb_entry(chip, playback_implicit_fb_quirks, alts);
 	if (p) {
 		switch (p->type) {
+		case IMPLICIT_FB_GENERIC:
+			return add_generic_implicit_fb(chip, fmt, alts);
 		case IMPLICIT_FB_NONE:
 			return 0; /* No quirk */
 		case IMPLICIT_FB_FIXED:
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (37 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 38/41] ALSA: usb-audio: Add generic implicit fb parsing Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  9:46   ` Pavel Hofman
  2020-11-23  8:53 ` [PATCH 40/41] ALSA: usb-audio: Fix quirks for other BOSS devices Takashi Iwai
  2020-11-23  8:53 ` [PATCH 41/41] ALSA: usb-audio: Fix MOTU M-Series quirks Takashi Iwai
  40 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

A new module option, implicit_fb, is added to specify the driver
looking for the implicit feedback sync.  This can be useful for a
device that could be working better in the implicit feed back mode and
user wants to test it quickly.  When this works, we can add the quirk
entry easily.

Tested-by: Keith Milner <kamilner@superlative.org>
Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 Documentation/sound/alsa-configuration.rst | 5 +++++
 sound/usb/card.c                           | 4 ++++
 sound/usb/implicit.c                       | 4 ++++
 sound/usb/usbaudio.h                       | 1 +
 4 files changed, 14 insertions(+)

diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index c755b1c5e16f..fe52c314b763 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -2227,6 +2227,11 @@ quirk_alias
     Quirk alias list, pass strings like ``0123abcd:5678beef``, which
     applies the existing quirk for the device 5678:beef to a new
     device 0123:abcd.
+implicit_fb
+    Apply the generic implicit feedback sync mode.  When this is set
+    and the playback stream sync mode is ASYNC, the driver tries to
+    tie an adjacent ASYNC capture stream as the implicit feedback
+    source.
 use_vmalloc
     Use vmalloc() for allocations of the PCM buffers (default: yes).
     For architectures with non-coherent memory like ARM or MIPS, the
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 7940b3bff5bc..cb0b6582dfee 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -72,6 +72,7 @@ static bool ignore_ctl_error;
 static bool autoclock = true;
 static char *quirk_alias[SNDRV_CARDS];
 static char *delayed_register[SNDRV_CARDS];
+static bool implicit_fb[SNDRV_CARDS];
 
 bool snd_usb_use_vmalloc = true;
 bool snd_usb_skip_validation;
@@ -97,6 +98,8 @@ module_param_array(quirk_alias, charp, NULL, 0444);
 MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
 module_param_array(delayed_register, charp, NULL, 0444);
 MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4.");
+module_param_array(implicit_fb, bool, NULL, 0444);
+MODULE_PARM_DESC(implicit_fb, "Apply generic implicit feedback sync mode.");
 module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
 MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
 module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444);
@@ -596,6 +599,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
 	chip->dev = dev;
 	chip->card = card;
 	chip->setup = device_setup[idx];
+	chip->generic_implicit_fb = implicit_fb[idx];
 	chip->autoclock = autoclock;
 	atomic_set(&chip->active, 1); /* avoid autopm during probing */
 	atomic_set(&chip->usage_count, 0);
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 16b1fb55b7b9..1d87fcdae95b 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -269,6 +269,10 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
 			return 1;
 	}
 
+	/* Try the generic implicit fb if available */
+	if (chip->generic_implicit_fb)
+		return add_generic_implicit_fb(chip, fmt, alts);
+
 	/* No quirk */
 	return 0;
 }
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index cc338e8e2597..980287aadd36 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -51,6 +51,7 @@ struct snd_usb_audio {
 	struct list_head mixer_list;	/* list of mixer interfaces */
 
 	int setup;			/* from the 'device_setup' module param */
+	bool generic_implicit_fb;	/* from the 'implicit_fb' module param */
 	bool autoclock;			/* from the 'autoclock' module param */
 
 	struct usb_host_interface *ctrl_intf;	/* the audio control interface */
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 40/41] ALSA: usb-audio: Fix quirks for other BOSS devices
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (38 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  2020-11-23  8:53 ` [PATCH 41/41] ALSA: usb-audio: Fix MOTU M-Series quirks Takashi Iwai
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

A few other BOSS devices (BR-80, GT-100v2, Katana) seem requiring the
same quirk as BOSS GT-001, i.e. no implicit feedback for playback but
tying with capture.  Add and correct the corresponding quirk table
entries for them.

Reported-and-tested-by: Keith Milner <kamilner@superlative.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/implicit.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 1d87fcdae95b..1f7fb036c5b6 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -72,10 +72,10 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 	  .type = IMPLICIT_FB_FIXED,
 	  .ep_num = 0x84, .iface = 0 },		/* MOTU MicroBook II */
 
-	/* No quirk */
-	IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8),	/* BOSS Katana */
-
 	/* No quirk for playback but with capture quirk (see below) */
+	IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130),	/* BOSS BR-80 */
+	IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189),	/* BOSS GT-100v2 */
+	IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8),	/* BOSS Katana */
 	IMPLICIT_FB_SKIP_DEV(0x0582, 0x01e5),	/* BOSS GT-001 */
 
 	{} /* terminator */
@@ -83,6 +83,9 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 
 /* Implicit feedback quirk table for capture: only FIXED type */
 static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
+	IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */
+	IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */
+	IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */
 	IMPLICIT_FB_FIXED_DEV(0x0582, 0x01e5, 0x0d, 0x01), /* BOSS GT-001 */
 
 	{} /* terminator */
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* [PATCH 41/41] ALSA: usb-audio: Fix MOTU M-Series quirks
  2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
                   ` (39 preceding siblings ...)
  2020-11-23  8:53 ` [PATCH 40/41] ALSA: usb-audio: Fix quirks for other BOSS devices Takashi Iwai
@ 2020-11-23  8:53 ` Takashi Iwai
  40 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2020-11-23  8:53 UTC (permalink / raw)
  To: alsa-devel; +Cc: Matwey Kornilov, Dylan Robinson, Keith Milner

From: Dylan Robinson <dylan_robinson@motu.com>

Now that the usb audio driver correctly finds implicit feedback endpoints,
the implicit feedback quirk for the MOTU M-Series is no longer required.

This also removes some unnecessary vendor specific messages from the MOTU
M-Series boot quirk. The removed vendor specific messages turned on vendor
specific interrupts to the host every 32 samples. The only thing the boot
quirk needs to do is wait for 2 seconds.

Tested-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Dylan Robinson <dylan_robinson@motu.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/implicit.c |  1 -
 sound/usb/quirks.c   | 16 ----------------
 2 files changed, 17 deletions(-)

diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 1f7fb036c5b6..386198b36b87 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -52,7 +52,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0001, 0x81, 1), /* Behringer UFX1604 */
 	IMPLICIT_FB_FIXED_DEV(0x1397, 0x0002, 0x81, 1), /* Behringer UFX1204 */
 	IMPLICIT_FB_FIXED_DEV(0x2466, 0x8010, 0x81, 2), /* Fractal Audio Axe-Fx III */
-	IMPLICIT_FB_FIXED_DEV(0x07fd, 0x0008, 0x81, 2), /* MOTU M Series */
 	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0001, 0x81, 2), /* Solid State Logic SSL2 */
 	IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
 	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 02f3f6ed9390..63cdf3c8c2bc 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1110,24 +1110,8 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev)
 
 static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
 {
-	int ret;
-
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			      1, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x0, 0, NULL, 0, 1000);
-
-	if (ret < 0)
-		return ret;
-
 	msleep(2000);
 
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-			      1, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x20, 0, NULL, 0, 1000);
-
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option
  2020-11-23  8:53 ` [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option Takashi Iwai
@ 2020-11-23  9:46   ` Pavel Hofman
  0 siblings, 0 replies; 52+ messages in thread
From: Pavel Hofman @ 2020-11-23  9:46 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel


Dne 23. 11. 20 v 9:53 Takashi Iwai napsal(a):
> A new module option, implicit_fb, is added to specify the driver
> looking for the implicit feedback sync.  This can be useful for a
> device that could be working better in the implicit feed back mode and
> user wants to test it quickly.  When this works, we can add the quirk
> entry easily.

Hi Takashi, thanks a lot for this extremely practical feature, along
with all the very useful patches.

With regards,

Pavel.

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2020-11-23  8:53 ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase Takashi Iwai
@ 2021-01-03 17:09   ` František Kučera
  2021-01-03 17:19     ` Takashi Iwai
  0 siblings, 1 reply; 52+ messages in thread
From: František Kučera @ 2021-01-03 17:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Matwey Kornilov, Dylan Robinson, Keith Milner

Dne 23. 11. 20 v 9:53 Takashi Iwai napsal(a):
> Currently snd_usb_endpoint objects are created at first when the
> substream is opened and tries to assign the endpoints corresponding to
> the matching audioformat.  But since basically the all endpoints have
> been already parsed and the information have been obtained, we may
> create the endpoint objects statically at the init phase.  It's easier
> to manage for the implicit fb case, for example.
>
> This patch changes the endpoint object management and lets the parser
> to create the all endpoint objects.
>
> This change shouldn't bring any functional changes.

The Pioneer DJ DJM-250MK2 (implemented in 73d8c9408434, 14335d8b9e1a, cdc01a1558de) stopped working.

After bisecting, it seems that it worked in 5fd255f4fe97 and stopped working in 54cb31901b83.

The arecord says: set_params:1407: Unable to install hw params

And even playback is impossible in this version. But there is no error in the log. However in later versions (e.g. eda809aef534) I found errors in kern.log:

usb 1-3: Cannot find EP 0x1 to open

usb 1-3: Cannot find EP 0x82 to open

(each repeats 20 or more times, seems to be in pcm.c in subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);)

Could you please check it? I am not sure whether it should be fixed in the DJM-250MK2 specific code or here.

Thanks,

Franta



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-03 17:09   ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working František Kučera
@ 2021-01-03 17:19     ` Takashi Iwai
  2021-01-03 18:15       ` František Kučera
  0 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2021-01-03 17:19 UTC (permalink / raw)
  To: František Kučera
  Cc: alsa-devel, Matwey Kornilov, Dylan Robinson, Keith Milner

On Sun, 03 Jan 2021 18:09:41 +0100,
František Kučera wrote:
> 
> Dne 23. 11. 20 v 9:53 Takashi Iwai napsal(a):
> > Currently snd_usb_endpoint objects are created at first when the
> > substream is opened and tries to assign the endpoints corresponding to
> > the matching audioformat.  But since basically the all endpoints have
> > been already parsed and the information have been obtained, we may
> > create the endpoint objects statically at the init phase.  It's easier
> > to manage for the implicit fb case, for example.
> >
> > This patch changes the endpoint object management and lets the parser
> > to create the all endpoint objects.
> >
> > This change shouldn't bring any functional changes.
> 
> The Pioneer DJ DJM-250MK2 (implemented in 73d8c9408434, 14335d8b9e1a, cdc01a1558de) stopped working.
> 
> After bisecting, it seems that it worked in 5fd255f4fe97 and stopped working in 54cb31901b83.
> 
> The arecord says: set_params:1407: Unable to install hw params
> 
> And even playback is impossible in this version. But there is no error in the log. However in later versions (e.g. eda809aef534) I found errors in kern.log:
> 
> usb 1-3: Cannot find EP 0x1 to open
> 
> usb 1-3: Cannot find EP 0x82 to open
> 
> (each repeats 20 or more times, seems to be in pcm.c in subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);)
> 
> Could you please check it? I am not sure whether it should be fixed in the DJM-250MK2 specific code or here.

Could you give lsusb -v output as well as /proc/asound/card*/usbmixer
and stream* files?  The proc files are at best from both older and new
kernels.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-03 17:19     ` Takashi Iwai
@ 2021-01-03 18:15       ` František Kučera
  2021-01-05  9:29         ` Takashi Iwai
  0 siblings, 1 reply; 52+ messages in thread
From: František Kučera @ 2021-01-03 18:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Matwey Kornilov, Dylan Robinson, Keith Milner

[-- Attachment #1: Type: text/plain, Size: 967 bytes --]

Dne 03. 01. 21 v 18:19 Takashi Iwai napsal(a):
> Could you give lsusb -v output as well as /proc/asound/card*/usbmixer
> and stream* files?  The proc files are at best from both older and new
> kernels.

Here are the files. They look same. The only difference is in the stream0, but it is probably only formatting. I also attached the kern.log from the new version.

When I tried to debug the new version (eda809aef534), it crashed in pcm.c in snd_usb_hw_params() on lines:

    subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false); // error in log: usb 3-3: Cannot find EP 0x1 to open // (or 0x82)
    if (!subs->data_endpoint) {
        ret = -EINVAL;
        goto unlock; // was here
    }

Before that, it did not enter these conditional blocks:

    if (!fmt) { ... }

    if (fmt->implicit_fb) { ... }

    if (ret < 0), if (ret < 0)

    if (subs->data_endpoint) { ... }

Franta


[-- Attachment #2: lsusb_2b73:0017_5fd255f4fe97.txt --]
[-- Type: text/plain, Size: 7350 bytes --]


Bus 001 Device 002: ID 2b73:0017 Pioneer DJ Corporation DJM-250MK2
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x2b73 
  idProduct          0x0017 
  bcdDevice            1.06
  iManufacturer           1 Pioneer DJ Corporation
  iProduct                2 DJM-250MK2
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x00a2
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0009
        bInCollection           1
        baInterfaceNr(0)        2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0041
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 3
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 4
        bNrInputPins            1
        baSourceID( 0)          3
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 2
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       2
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       3
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      52
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               4
Device Status:     0x0001
  Self Powered

[-- Attachment #3: lsusb_2b73:0017_54cb31901b83.txt --]
[-- Type: text/plain, Size: 7350 bytes --]


Bus 001 Device 002: ID 2b73:0017 Pioneer DJ Corporation DJM-250MK2
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x2b73 
  idProduct          0x0017 
  bcdDevice            1.06
  iManufacturer           1 Pioneer DJ Corporation
  iProduct                2 DJM-250MK2
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x00a2
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0009
        bInCollection           1
        baInterfaceNr(0)        2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0041
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 3
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 4
        bNrInputPins            1
        baSourceID( 0)          3
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 2
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       2
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       3
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      52
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               4
Device Status:     0x0001
  Self Powered

[-- Attachment #4: lsusb_2b73:0017_eda809aef534.txt --]
[-- Type: text/plain, Size: 7350 bytes --]


Bus 001 Device 002: ID 2b73:0017 Pioneer DJ Corporation DJM-250MK2
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x2b73 
  idProduct          0x0017 
  bcdDevice            1.06
  iManufacturer           1 Pioneer DJ Corporation
  iProduct                2 DJM-250MK2
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x00a2
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xc0
      Self Powered
    MaxPower                0mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            5
          Transfer Type            Isochronous
          Synch Type               Asynchronous
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               3
        bRefresh                0
        bSynchAddress           0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0009
        bInCollection           1
        baInterfaceNr(0)        2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         1 Audio
      bInterfaceSubClass      3 MIDI Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      MIDIStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength       0x0041
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               1 Embedded
        bJackID                 3
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 6
        bDescriptorType        36
        bDescriptorSubtype      2 (MIDI_IN_JACK)
        bJackType               2 External
        bJackID                 1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               2 External
        bJackID                 4
        bNrInputPins            1
        baSourceID( 0)          3
        BaSourcePin( 0)         1
        iJack                   0 
      MIDIStreaming Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (MIDI_OUT_JACK)
        bJackType               1 Embedded
        bJackID                 2
        bNrInputPins            1
        baSourceID( 0)          1
        BaSourcePin( 0)         1
        iJack                   0 
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       2
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
        bRefresh                0
        bSynchAddress           0
        MIDIStreaming Endpoint Descriptor:
          bLength                 5
          bDescriptorType        37
          bDescriptorSubtype      1 (GENERAL)
          bNumEmbMIDIJack         1
          baAssocJackID( 0)       3
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      52
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               4
Device Status:     0x0001
  Self Powered

[-- Attachment #5: stream0_5fd255f4fe97.txt --]
[-- Type: text/plain, Size: 436 bytes --]

Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed : USB Audio

Playback:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 1 OUT (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

Capture:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 2 IN (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

[-- Attachment #6: stream0_54cb31901b83.txt --]
[-- Type: text/plain, Size: 436 bytes --]

Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed : USB Audio

Playback:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 1 OUT (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

Capture:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 2 IN (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

[-- Attachment #7: stream0_eda809aef534.txt --]
[-- Type: text/plain, Size: 450 bytes --]

Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed : USB Audio

Playback:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 0x01 (1 OUT) (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

Capture:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 0x82 (2 IN) (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0

[-- Attachment #8: usbmixer_5fd255f4fe97.txt --]
[-- Type: text/plain, Size: 600 bytes --]

USB Mixer: usb_id=0x2b730017, ctrlif=1, ctlerr=0
Card: Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed
  Unit: 0
    Control: name="Playback 5-6 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 3-4 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 1-2 Playback Switch", index=0
  Unit: 0
    Control: name="Capture 5-6 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 3-4 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 1-2 Capture Switch", index=0
  Unit: 0
    Control: name="Master Capture Level Capture Switch", index=0

[-- Attachment #9: usbmixer_54cb31901b83.txt --]
[-- Type: text/plain, Size: 600 bytes --]

USB Mixer: usb_id=0x2b730017, ctrlif=1, ctlerr=0
Card: Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed
  Unit: 0
    Control: name="Playback 5-6 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 3-4 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 1-2 Playback Switch", index=0
  Unit: 0
    Control: name="Capture 5-6 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 3-4 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 1-2 Capture Switch", index=0
  Unit: 0
    Control: name="Master Capture Level Capture Switch", index=0

[-- Attachment #10: usbmixer_eda809aef534.txt --]
[-- Type: text/plain, Size: 600 bytes --]

USB Mixer: usb_id=0x2b730017, ctrlif=1, ctlerr=0
Card: Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed
  Unit: 0
    Control: name="Playback 5-6 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 3-4 Playback Switch", index=0
  Unit: 0
    Control: name="Playback 1-2 Playback Switch", index=0
  Unit: 0
    Control: name="Capture 5-6 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 3-4 Capture Switch", index=0
  Unit: 0
    Control: name="Capture 1-2 Capture Switch", index=0
  Unit: 0
    Control: name="Master Capture Level Capture Switch", index=0

[-- Attachment #11: kern_eda809aef534.log --]
[-- Type: text/x-log, Size: 95004 bytes --]

Jan  3 18:47:03 antracit kernel: [   52.632639] usb 1-3: new high-speed USB device number 2 using ehci-pci
Jan  3 18:47:03 antracit kernel: [   52.789359] usb 1-3: New USB device found, idVendor=2b73, idProduct=0017, bcdDevice= 1.06
Jan  3 18:47:03 antracit kernel: [   52.789370] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Jan  3 18:47:03 antracit kernel: [   52.789376] usb 1-3: Product: DJM-250MK2
Jan  3 18:47:03 antracit kernel: [   52.789380] usb 1-3: Manufacturer: Pioneer DJ Corporation
Jan  3 18:47:03 antracit kernel: [   52.791204] hid-generic 0003:2B73:0017.0004: hiddev0,hidraw3: USB HID v1.11 Device [Pioneer DJ Corporation DJM-250MK2] on usb-0000:00:12.2-3/input3
Jan  3 18:47:03 antracit kernel: [   52.810884] mc: Linux media interface: v0.10
Jan  3 18:47:03 antracit kernel: [   52.822190] usbcore: registered new interface driver snd-usb-audio
Jan  3 18:47:03 antracit kernel: [   52.880613] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.880689] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.880752] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.880839] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.880933] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881159] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881223] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881282] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881369] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881464] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881859] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881920] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.881978] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.882052] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.882137] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.882694] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.882867] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.883037] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.883208] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.883389] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.884052] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.884263] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.884474] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.884714] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.884940] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.885680] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.885708] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.885734] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.885780] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.885846] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886029] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886056] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886082] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886127] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886184] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886447] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886528] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886606] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886697] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.886800] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.887138] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.887242] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.887344] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.887455] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.887578] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.889248] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889277] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889304] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889351] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889410] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889593] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889622] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889649] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889695] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.889753] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890016] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890095] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890172] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890261] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890361] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890692] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890704] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.890730] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.890753] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.890792] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.890797] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.890852] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.890887] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.891001] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.891019] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891043] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891067] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891112] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891121] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.891165] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891433] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891507] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891578] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891660] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.891753] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.892081] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.892182] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.892292] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.892386] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.892488] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.894123] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894150] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894174] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894218] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894272] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894450] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894476] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894501] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894545] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894601] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894868] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.894942] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895020] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895111] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895210] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895548] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895648] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895745] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895852] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.895974] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.909699] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.909753] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.909803] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.909865] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.909938] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.910284] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.910332] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.910379] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.910440] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.910510] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.911009] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.911153] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.911297] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.911438] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.911588] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.912177] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.912352] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.912521] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.912714] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.912944] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.918138] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918161] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918183] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918221] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918270] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918425] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918446] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918468] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918510] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918557] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918787] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918851] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918914] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.918990] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919073] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919365] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919450] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919529] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919619] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.919715] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.923974] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924027] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924077] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924145] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924217] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924573] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924630] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924679] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924740] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.924812] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.925303] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.925444] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.925584] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.925725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.925874] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.926436] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.926605] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.926774] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.926939] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.927113] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.931023] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931046] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931068] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931106] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931154] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931312] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931334] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931355] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931393] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931440] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931662] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931725] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931787] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931862] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.931943] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.932219] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.932300] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.932378] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.932467] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.932601] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.933981] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934009] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934035] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934082] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934142] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934331] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934357] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934383] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934429] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934487] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934761] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934838] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.934914] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935004] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935103] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935447] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935547] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935644] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935756] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.935878] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.938551] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938577] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938599] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938638] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938687] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938839] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938862] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938883] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938921] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.938969] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939189] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939254] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939318] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939394] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939478] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939760] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939846] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.939927] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.940019] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.940120] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.941491] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941514] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941536] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941575] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941623] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941775] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941798] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941819] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941857] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.941905] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942126] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942191] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942255] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942330] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942414] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942694] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942779] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942861] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.942951] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.943050] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.952965] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.953019] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.953069] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.953137] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.953210] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959220] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959233] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959269] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959275] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959303] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959326] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959362] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959389] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959438] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959462] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959670] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959704] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959735] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959793] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959798] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959847] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959867] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.959896] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.959958] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.960028] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.960187] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960286] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960379] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960490] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960493] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.960663] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960694] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.960847] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.960952] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.960990] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.961039] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.961125] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.961141] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.961220] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.961324] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.961720] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.961894] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.962061] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.962229] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.962406] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.967374] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967398] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967421] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967461] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967510] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967661] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967683] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967705] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967744] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.967792] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968011] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968077] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968142] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968217] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968302] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968712] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968803] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968886] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.968980] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.969081] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.970471] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970494] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970516] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970555] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970605] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970770] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970794] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970815] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970854] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.970904] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971138] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971202] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971266] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971342] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971426] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971720] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971805] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971888] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.971981] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.972082] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.976601] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.976654] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.976704] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.976767] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.976841] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977179] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977229] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977277] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977338] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977411] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.977892] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.978033] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.978173] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.978314] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.978465] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.979034] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.979210] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.979379] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.979550] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.979734] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.984805] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.984829] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.984851] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.984891] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.984941] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985101] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985124] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985146] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985185] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985236] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985460] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985527] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985591] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985668] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.985754] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.986054] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.986138] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.986217] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.986308] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.986407] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.987231] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987254] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987275] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987314] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987362] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987520] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987542] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987563] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987602] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987650] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987874] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.987939] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988001] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988075] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988157] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988442] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988527] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988767] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.988909] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.989031] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.992043] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992069] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992091] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992132] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992182] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992335] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992357] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992379] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992420] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992469] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992837] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992904] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.992968] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993043] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993127] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993419] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993506] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993589] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993681] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.993781] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   52.995109] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995131] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995154] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995193] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995243] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995396] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995418] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995442] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995480] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995589] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995826] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995890] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.995954] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996028] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996113] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996396] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996481] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996590] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996683] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   52.996785] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.005512] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.005564] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.005612] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.005677] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.005755] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006080] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006128] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006177] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006239] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006310] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006797] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.006937] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.007130] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.007270] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.007417] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.008010] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.008199] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.008448] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.008650] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.008854] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.014020] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014044] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014066] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014104] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014152] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014306] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014328] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014349] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014386] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014433] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014649] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014711] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014773] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014846] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.014928] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015209] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015292] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015371] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015460] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015557] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.015650] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.015702] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.015750] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.015814] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.015883] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016206] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016253] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016300] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016359] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016449] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.016975] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.017118] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.017259] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.017398] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.017546] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.018130] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.018305] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.018473] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.018640] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.018818] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.023751] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.023775] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.023797] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.023836] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.023886] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024040] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024062] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024084] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024123] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024171] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024396] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024461] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024523] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024648] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.024744] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.025038] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.025124] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.025205] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.025298] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.025399] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.026795] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.026819] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.026841] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.026879] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.026929] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027084] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027107] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027129] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027167] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027216] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027440] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027505] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027569] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027643] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.027727] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.035400] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.035474] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.035545] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.035638] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.035745] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.036155] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.036214] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.036272] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.036345] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.036431] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.037005] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.037148] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.037291] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.037432] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.037581] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.038161] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.038337] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.038506] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.038674] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.038850] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.043968] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.043994] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044015] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044056] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044106] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044266] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044288] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044310] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044348] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044398] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044696] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044793] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044886] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.044995] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.045118] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.045544] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.045668] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.045790] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.045925] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.046072] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:03 antracit kernel: [   53.048043] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048077] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048110] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048167] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048239] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048468] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048501] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048532] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048631] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048704] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.048945] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049012] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049075] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049149] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049233] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049519] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049606] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049688] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049780] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:03 antracit kernel: [   53.049881] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:08 antracit kernel: [   58.154752] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:08 antracit kernel: [   58.155466] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:10 antracit kernel: [   59.570244] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:10 antracit kernel: [   59.571174] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:11 antracit kernel: [   60.416577] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:11 antracit kernel: [   60.417129] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.979933] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.997888] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.998043] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.998189] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.998387] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.998636] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.998986] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999051] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999112] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999204] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999292] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999784] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999843] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   73.999918] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.000005] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.000621] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.000771] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.000915] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.001055] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.001202] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.001785] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.001958] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.002125] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.002292] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.002469] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008749] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008771] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008811] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008841] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.008862] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.008867] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.008891] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.008939] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009001] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009016] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009040] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009062] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009102] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009151] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009160] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009184] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009205] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009247] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009302] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009371] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009437] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009499] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009520] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009575] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009590] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009656] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009662] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.009735] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009820] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.009945] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.010031] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.010101] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.010112] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.010188] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.010205] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.010273] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.010308] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.010368] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.010470] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.011856] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.011880] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.011902] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.011941] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.011990] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012145] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012168] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012191] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012230] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012279] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012504] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012599] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012663] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012738] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.012821] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.013112] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.013197] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.013279] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.013371] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.013472] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.026461] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.026522] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.026576] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.026646] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.026735] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.030907] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.030937] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.030965] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031030] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031101] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031307] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031335] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031363] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031403] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031453] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031686] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031752] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031817] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031893] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.031975] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.032261] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.032346] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.032427] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.032518] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.032732] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034448] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034477] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034503] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034550] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034608] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034668] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034693] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034716] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034759] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034797] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034809] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034827] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034855] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034902] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034960] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.034965] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.034988] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035010] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035050] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035099] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035234] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.035316] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.035321] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035391] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035408] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.035456] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035503] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.035532] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035613] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.035618] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035918] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.035969] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.036006] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.036074] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.036090] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.036181] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.036186] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.036291] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.036298] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.036429] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037213] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037237] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037259] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037298] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037348] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037507] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037530] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037552] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037591] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037641] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037862] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037927] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.037991] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038066] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038149] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038437] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038523] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038605] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038696] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.038795] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.052362] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.052414] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.052462] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.052532] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.052678] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053027] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053083] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053132] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053194] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053273] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053777] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.053918] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.054058] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.054197] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.054345] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.054923] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.055100] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.055269] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.055410] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055438] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055441] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.055467] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055510] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055561] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055622] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.055711] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055734] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055756] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055795] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.055845] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056073] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056140] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056204] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056280] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056364] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056689] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056784] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056880] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.056977] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.057085] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.058463] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058486] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058508] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058546] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058595] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058758] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058780] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058802] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058840] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.058889] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059118] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059183] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059245] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059320] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059404] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059690] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059777] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059858] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.059950] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.060051] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.060520] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060574] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060597] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060638] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060697] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060869] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060892] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060914] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.060953] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061002] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061228] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061295] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061360] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061435] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061518] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061805] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061892] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.061974] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.062065] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.062167] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.063507] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063530] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063553] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063592] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063641] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063796] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063818] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063839] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063877] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.063926] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064149] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064213] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064278] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064354] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064470] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064787] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064873] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.064953] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.065046] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.065146] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.077589] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.077640] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.077763] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.077827] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.077899] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078247] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078297] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078345] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078407] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078479] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.078988] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.079125] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.079262] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.079399] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.079545] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.080118] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.080289] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.080463] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.080756] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.080989] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.084982] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085011] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085038] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085100] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085159] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085345] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085372] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085398] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085444] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085501] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085770] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085855] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.085933] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086024] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086125] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086459] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086565] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086668] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086780] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.086902] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.087277] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087306] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087335] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087387] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087442] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087615] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087640] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087663] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087706] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087759] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.087998] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088076] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088154] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088243] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088352] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088833] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.088938] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.089043] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.089146] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.106841] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.106905] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.106965] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107045] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107140] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107361] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107390] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107416] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107461] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107519] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107521] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107578] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107636] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107696] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107710] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107720] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107744] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107789] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.107793] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.107843] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108105] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108182] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108255] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108333] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.108341] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108435] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108494] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.108705] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.108800] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108869] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.108899] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.108993] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.109044] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.109100] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.109227] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.109725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.109923] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.110106] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.110293] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.110516] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.116309] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116338] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116363] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116408] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116463] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116673] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116699] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116723] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116768] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.116824] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117080] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117156] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117236] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117325] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117422] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117756] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117858] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.117956] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.118063] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.118181] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.119759] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.119786] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.119812] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.119859] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.119916] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120105] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120131] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120156] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120202] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120259] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120527] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120785] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120864] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.120955] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121057] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121403] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121513] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121613] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121725] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.121845] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127161] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127225] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127285] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127360] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127447] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127847] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127907] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.127962] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.128035] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.128120] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.128716] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.128885] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.129050] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.129214] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.129385] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.130059] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.130267] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.130471] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.130677] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.130898] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.136852] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.136882] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.136908] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.136959] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137018] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137202] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137229] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137255] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137301] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137360] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137624] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137707] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137788] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137885] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.137987] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.138324] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.138430] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.138533] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.138645] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.138768] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.139896] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.139924] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.139950] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.139995] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140052] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140232] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140259] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140285] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140329] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.140384] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.141092] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.141294] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.141485] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.141706] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.141945] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.142900] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.143153] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.143393] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.143584] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143610] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143633] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143662] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.143679] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143731] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143876] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143901] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143922] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.143962] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.143969] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144023] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144246] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144311] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144373] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144449] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144533] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144845] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.144931] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.145011] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.145102] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.145200] usb 1-3: Cannot find EP 0x82 to open
Jan  3 18:47:24 antracit kernel: [   74.146529] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146553] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146575] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146614] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146664] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146816] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146838] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146859] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146898] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.146946] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147165] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147231] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147294] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147368] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147451] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147736] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147821] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147901] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.147994] usb 1-3: Cannot find EP 0x1 to open
Jan  3 18:47:24 antracit kernel: [   74.148093] usb 1-3: Cannot find EP 0x1 to open

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-03 18:15       ` František Kučera
@ 2021-01-05  9:29         ` Takashi Iwai
  2021-01-05 13:20           ` Takashi Iwai
  0 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2021-01-05  9:29 UTC (permalink / raw)
  To: František Kučera
  Cc: alsa-devel, Matwey Kornilov, Dylan Robinson, Keith Milner

On Sun, 03 Jan 2021 19:15:48 +0100,
František Kučera wrote:
> 
> Dne 03. 01. 21 v 18:19 Takashi Iwai napsal(a):
> > Could you give lsusb -v output as well as /proc/asound/card*/usbmixer
> > and stream* files?  The proc files are at best from both older and new
> > kernels.
> 
> Here are the files. They look same. The only difference is in the stream0, but it is probably only formatting. I also attached the kern.log from the new version.

Thanks.

It must be something specific to the devices with the fixed stream
qurik.  Could you try the patch below?


Takashi

-- 8< --
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -155,9 +155,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 
 	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 ||
 	    fp->altset_idx >= iface->num_altsetting) {
 		err = -EINVAL;
@@ -176,6 +173,11 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
 	if (fp->maxpacksize == 0)
 		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+
+	err = snd_usb_add_audio_stream(chip, stream, fp);
+	if (err < 0)
+		goto error;
+
 	usb_set_interface(chip->dev, fp->iface, 0);
 	snd_usb_init_pitch(chip, fp);
 	snd_usb_init_sample_rate(chip, fp, fp->rate_max);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-05  9:29         ` Takashi Iwai
@ 2021-01-05 13:20           ` Takashi Iwai
  2021-01-05 22:27             ` František Kučera
  0 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2021-01-05 13:20 UTC (permalink / raw)
  To: František Kučera
  Cc: alsa-devel, Matwey Kornilov, Dylan Robinson, Keith Milner

On Tue, 05 Jan 2021 10:29:24 +0100,
Takashi Iwai wrote:
> 
> On Sun, 03 Jan 2021 19:15:48 +0100,
> František Kučera wrote:
> > 
> > Dne 03. 01. 21 v 18:19 Takashi Iwai napsal(a):
> > > Could you give lsusb -v output as well as /proc/asound/card*/usbmixer
> > > and stream* files?  The proc files are at best from both older and new
> > > kernels.
> > 
> > Here are the files. They look same. The only difference is in the stream0, but it is probably only formatting. I also attached the kern.log from the new version.
> 
> Thanks.
> 
> It must be something specific to the devices with the fixed stream
> qurik.  Could you try the patch below?

Scratch that.  The call of snd_usb_add_endpoint() is needed explicitly
now at the quirk itself.

Below is the v2 patch.  Please give it a try.


thanks,

Takashi

-- 8< --
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -120,6 +120,38 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 	return 0;
 }
 
+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;
+
+	/* add endpoints */
+	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
  */
@@ -131,8 +163,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 	struct audioformat *fp;
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
-	int stream, err;
 	unsigned *rate_table = NULL;
+	int err;
 
 	fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
 	if (!fp)
@@ -153,11 +185,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		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 ||
 	    fp->altset_idx >= iface->num_altsetting) {
 		err = -EINVAL;
@@ -176,6 +203,11 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
 	if (fp->maxpacksize == 0)
 		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+
+	err = add_audio_stream_from_fixed_fmt(chip, fp);
+	if (err < 0)
+		goto error;
+
 	usb_set_interface(chip->dev, fp->iface, 0);
 	snd_usb_init_pitch(chip, fp);
 	snd_usb_init_sample_rate(chip, fp, fp->rate_max);
@@ -417,7 +449,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct audioformat *fp;
-	int stream, err;
+	int err;
 
 	/* both PCM and MIDI interfaces have 2 or more altsettings */
 	if (iface->num_altsetting < 2)
@@ -482,9 +514,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 		return -ENXIO;
 	}
 
-	stream = (fp->endpoint & USB_DIR_IN)
-		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-	err = snd_usb_add_audio_stream(chip, stream, fp);
+	err = add_audio_stream_from_fixed_fmt(chip, fp);
 	if (err < 0) {
 		list_del(&fp->list); /* unlink for avoiding double-free */
 		kfree(fp);

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-05 13:20           ` Takashi Iwai
@ 2021-01-05 22:27             ` František Kučera
  2021-01-06  9:03               ` Takashi Iwai
  0 siblings, 1 reply; 52+ messages in thread
From: František Kučera @ 2021-01-05 22:27 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Matwey Kornilov, Dylan Robinson, Keith Milner

Dne 05. 01. 21 v 14:20 Takashi Iwai napsal(a):
> The call of snd_usb_add_endpoint() is needed explicitly
> now at the quirk itself.
>
> Below is the v2 patch.  Please give it a try.

I applied your v2 patch to f6e7a024bfe5 version and tested with DJM-250MK2. It seems working (playback, recording).

The original error messages (usb 1-3: Cannot find EP 0x1 to open, usb 1-3: Cannot find EP 0x82 to open) disappeared from the log. And new one occurred (Incompatible EP setup for 0x82 - repeats many times). However DJM-250MK2 works again.

Thanks,

Franta



^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-05 22:27             ` František Kučera
@ 2021-01-06  9:03               ` Takashi Iwai
  2021-01-06 19:01                 ` František Kučera
  0 siblings, 1 reply; 52+ messages in thread
From: Takashi Iwai @ 2021-01-06  9:03 UTC (permalink / raw)
  To: František Kučera
  Cc: alsa-devel, Matwey Kornilov, Dylan Robinson, Keith Milner

On Tue, 05 Jan 2021 23:27:14 +0100,
František Kučera wrote:
> 
> Dne 05. 01. 21 v 14:20 Takashi Iwai napsal(a):
> > The call of snd_usb_add_endpoint() is needed explicitly
> > now at the quirk itself.
> >
> > Below is the v2 patch.  Please give it a try.
> 
> I applied your v2 patch to f6e7a024bfe5 version and tested with DJM-250MK2. It seems working (playback, recording).
> 
> The original error messages (usb 1-3: Cannot find EP 0x1 to open, usb 1-3: Cannot find EP 0x82 to open) disappeared from the log. And new one occurred (Incompatible EP setup for 0x82 - repeats many times). However DJM-250MK2 works again.

OK, then could you try the v3 patch below?


Takashi

-- 8< --
From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH v3] 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 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.

Also, since the implicit feedback can be handled generically, drop
the implicit feedback quirk entries for those devices.
This fixes the missing sync_ep_idx entry, too.

Fixes: 54cb31901b83 ("ALSA: usb-audio: Create endpoint objects at parsing phase")
Reported-by: František Kučera <konference@frantovo.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/usb/implicit.c |  2 --
 sound/usb/quirks.c   | 54 ++++++++++++++++++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 931042a6a051..3e0d8a59dddb 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -58,8 +58,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
 	IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
 	IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
-	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */
-	IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */
 	IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
 	IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
 	IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e4a690bb4c99..b70e2ebc3e29 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -120,6 +120,40 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 	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
  */
@@ -131,8 +165,8 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 	struct audioformat *fp;
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
-	int stream, err;
 	unsigned *rate_table = NULL;
+	int err;
 
 	fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
 	if (!fp)
@@ -153,11 +187,6 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		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 ||
 	    fp->altset_idx >= iface->num_altsetting) {
 		err = -EINVAL;
@@ -176,6 +205,13 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
 	if (fp->maxpacksize == 0)
 		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);
 	snd_usb_init_pitch(chip, fp);
 	snd_usb_init_sample_rate(chip, fp, fp->rate_max);
@@ -417,7 +453,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 	struct usb_host_interface *alts;
 	struct usb_interface_descriptor *altsd;
 	struct audioformat *fp;
-	int stream, err;
+	int err;
 
 	/* both PCM and MIDI interfaces have 2 or more altsettings */
 	if (iface->num_altsetting < 2)
@@ -482,9 +518,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 		return -ENXIO;
 	}
 
-	stream = (fp->endpoint & USB_DIR_IN)
-		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-	err = snd_usb_add_audio_stream(chip, stream, fp);
+	err = add_audio_stream_from_fixed_fmt(chip, fp);
 	if (err < 0) {
 		list_del(&fp->list); /* unlink for avoiding double-free */
 		kfree(fp);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-06  9:03               ` Takashi Iwai
@ 2021-01-06 19:01                 ` František Kučera
  2021-01-07 13:30                   ` Takashi Iwai
  0 siblings, 1 reply; 52+ messages in thread
From: František Kučera @ 2021-01-06 19:01 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Matwey Kornilov, Dylan Robinson, Keith Milner

[-- Attachment #1: Type: text/plain, Size: 2386 bytes --]

Dne 06. 01. 21 v 10:03 Takashi Iwai napsal(a):
> OK, then could you try the v3 patch below?

I tried v3 patch. Playback works, but recording does not - i found errors like these in the log during recording:

Jan  6 18:07:08 antracit kernel: [  619.973372] retire_capture_urb: 21 callbacks suppressed
Jan  6 18:07:13 antracit kernel: [  624.974175] retire_capture_urb: 9993 callbacks suppressed
Jan  6 18:07:18 antracit kernel: [  629.978015] retire_capture_urb: 9999 callbacks suppressed
Jan  6 18:08:04 antracit kernel: [  675.932930] retire_capture_urb: 102 callbacks suppressed
Jan  6 18:08:09 antracit kernel: [  680.936305] retire_capture_urb: 9998 callbacks suppressed
Jan  6 18:08:14 antracit kernel: [  685.940643] retire_capture_urb: 10000 callbacks suppressed
Jan  6 18:09:45 antracit kernel: [  776.168655] retire_capture_urb: 302 callbacks suppressed
Jan  6 18:09:50 antracit kernel: [  781.169504] retire_capture_urb: 9993 callbacks suppressed
Jan  6 18:09:55 antracit kernel: [  786.173337] retire_capture_urb: 9999 callbacks suppressed

(the original "Incompatible EP setup for 0x82" error was also present in the log)

The arecord command does nothing and after few seconds it fails with:

$ arecord -D hw:CARD=DJM250MK2 -f S24_3LE -c 8 -r 48000 > v3.wav
Recording WAVE 'stdin' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Channels 8
arecord: pcm_read:2153: read error: Input/output error

The stream0 files from v2 and v3 differs in: Playback / Implicit Feedback Mode: Yes/No


BTW: playback or capture sometimes returns error for the first time but next attempts are successful. However I saw this behavior even in the older versions, so it is nothing v3 specific.

This is the error I got sometimes during the first run:

$ arecord -D hw:CARD=DJM250MK2 -f S24_3LE -c 8 -r 48000 > v3.wav
Recording WAVE 'stdin' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Channels 8
arecord: set_params:1407: Unable to install hw params:
ACCESS:  RW_INTERLEAVED
FORMAT:  S24_3LE
SUBFORMAT:  STD
SAMPLE_BITS: 24
FRAME_BITS: 192
CHANNELS: 8
RATE: 48000
PERIOD_TIME: (455104 455105)
PERIOD_SIZE: 21845
PERIOD_BYTES: 524280
PERIODS: 2
BUFFER_TIME: (910208 910209)
BUFFER_SIZE: 43690
BUFFER_BYTES: 1048560
TICK_TIME: 0

If I execute the same command again, it works. (but not in v3).

Franta


[-- Attachment #2: stream0-v3.txt --]
[-- Type: text/plain, Size: 668 bytes --]

Pioneer DJ Corporation DJM-250MK2 at usb-0000:00:12.2-3, high speed : USB Audio

Playback:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 0x01 (1 OUT) (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0
    Sync Endpoint: 0x82 (2 IN)
    Sync EP Interface: 0
    Sync EP Altset: 1
    Implicit Feedback Mode: No

Capture:
  Status: Stop
  Interface 0
    Altset 1
    Format: S24_3LE
    Channels: 8
    Endpoint: 0x82 (2 IN) (ASYNC)
    Rates: 48000
    Data packet interval: 500 us
    Bits: 0
    Sync Endpoint: 0x82 (2 IN)
    Sync EP Interface: 0
    Sync EP Altset: 1
    Implicit Feedback Mode: No

^ permalink raw reply	[flat|nested] 52+ messages in thread

* Re: [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working
  2021-01-06 19:01                 ` František Kučera
@ 2021-01-07 13:30                   ` Takashi Iwai
  0 siblings, 0 replies; 52+ messages in thread
From: Takashi Iwai @ 2021-01-07 13:30 UTC (permalink / raw)
  To: František Kučera
  Cc: alsa-devel, Matwey Kornilov, Dylan Robinson, Keith Milner

On Wed, 06 Jan 2021 20:01:16 +0100,
František Kučera wrote:
> 
> Dne 06. 01. 21 v 10:03 Takashi Iwai napsal(a):
> > OK, then could you try the v3 patch below?
> 
> I tried v3 patch. Playback works, but recording does not - i found errors like these in the log during recording:

Hm.  There seem more problems than I've thought.  The Pioneer devices
are special and don't look like the generic application of the
implicit fb works.

Now I worked on v4 patch set.  Will post in another thread.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 52+ messages in thread

end of thread, other threads:[~2021-01-07 13:31 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-23  8:53 [PATCH 00/41] USB audio refactoring for better implicit feedback support Takashi Iwai
2020-11-23  8:53 ` [PATCH 01/41] ALSA: usb-audio: Handle discrete rates properly in hw constraints Takashi Iwai
2020-11-23  8:53 ` [PATCH 02/41] ALSA: usb-audio: Don't call usb_set_interface() at trigger callback Takashi Iwai
2020-11-23  8:53 ` [PATCH 03/41] ALSA: usb-audio: Check valid altsetting at parsing rates for UAC2/3 Takashi Iwai
2020-11-23  8:53 ` [PATCH 04/41] ALSA: usb-audio: Check implicit feedback EP generically for UAC2 Takashi Iwai
2020-11-23  8:53 ` [PATCH 05/41] ALSA: usb-audio: Add snd_usb_get_endpoint() helper Takashi Iwai
2020-11-23  8:53 ` [PATCH 06/41] ALSA: usb-audio: Set and clear sync EP link properly Takashi Iwai
2020-11-23  8:53 ` [PATCH 07/41] ALSA: usb-audio: Improve some debug prints Takashi Iwai
2020-11-23  8:53 ` [PATCH 08/41] ALSA: usb-audio: Track implicit fb sync endpoint in audioformat list Takashi Iwai
2020-11-23  8:53 ` [PATCH 09/41] ALSA: usb-audio: Move snd_usb_autoresume() call out of setup_hw_info() Takashi Iwai
2020-11-23  8:53 ` [PATCH 10/41] ALSA: usb-audio: Add hw constraint for implicit fb sync Takashi Iwai
2020-11-23  8:53 ` [PATCH 11/41] ALSA: usb-audio: Simplify hw_params rules Takashi Iwai
2020-11-23  8:53 ` [PATCH 12/41] ALSA: usb-audio: Drop debug.h Takashi Iwai
2020-11-23  8:53 ` [PATCH 13/41] ALSA: usb-audio: Avoid doubly initialization for implicit fb Takashi Iwai
2020-11-23  8:53 ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase Takashi Iwai
2021-01-03 17:09   ` [PATCH 14/41] ALSA: usb-audio: Create endpoint objects at parsing phase - Pioneer DJ DJM-250MK2 stopped working František Kučera
2021-01-03 17:19     ` Takashi Iwai
2021-01-03 18:15       ` František Kučera
2021-01-05  9:29         ` Takashi Iwai
2021-01-05 13:20           ` Takashi Iwai
2021-01-05 22:27             ` František Kučera
2021-01-06  9:03               ` Takashi Iwai
2021-01-06 19:01                 ` František Kučera
2021-01-07 13:30                   ` Takashi Iwai
2020-11-23  8:53 ` [PATCH 15/41] ALSA: usb-audio: Drop keep_interface flag again Takashi Iwai
2020-11-23  8:53 ` [PATCH 16/41] ALSA: usb-audio: Add snd_usb_get_host_interface() helper Takashi Iwai
2020-11-23  8:53 ` [PATCH 17/41] ALSA: usb-audio: Don't set altsetting before initializing sample rate Takashi Iwai
2020-11-23  8:53 ` [PATCH 18/41] ALSA: usb-audio: Pass snd_usb_audio object to quirk functions Takashi Iwai
2020-11-23  8:53 ` [PATCH 19/41] ALSA: usb-audio: Simplify snd_usb_init_sample_rate() arguments Takashi Iwai
2020-11-23  8:53 ` [PATCH 20/41] ALSA: usb-audio: Simplify snd_usb_init_pitch() arguments Takashi Iwai
2020-11-23  8:53 ` [PATCH 21/41] ALSA: usb-audio: Stop both endpoints properly at error Takashi Iwai
2020-11-23  8:53 ` [PATCH 22/41] ALSA: usb-audio: Set callbacks via snd_usb_endpoint_set_callback() Takashi Iwai
2020-11-23  8:53 ` [PATCH 23/41] ALSA: usb-audio: Always set up the parameters after resume Takashi Iwai
2020-11-23  8:53 ` [PATCH 24/41] ALSA: usb-audio: Fix EP matching for continuous rates Takashi Iwai
2020-11-23  8:53 ` [PATCH 25/41] ALSA: usb-audio: Refactor endpoint management Takashi Iwai
2020-11-23  8:53 ` [PATCH 26/41] ALSA: usb-audio: Fix possible stall of implicit fb packet ring-buffer Takashi Iwai
2020-11-23  8:53 ` [PATCH 27/41] ALSA: usb-audio: Constify audioformat pointer references Takashi Iwai
2020-11-23  8:53 ` [PATCH 28/41] ALSA: usb-audio: Use atomic_t for endpoint use_count Takashi Iwai
2020-11-23  8:53 ` [PATCH 29/41] ALSA: usb-audio: Refactoring endpoint URB deactivation Takashi Iwai
2020-11-23  8:53 ` [PATCH 30/41] ALSA: usb-audio: Drop unneeded snd_usb_substream fields Takashi Iwai
2020-11-23  8:53 ` [PATCH 31/41] ALSA: usb-audio: Unify the code for the next packet size calculation Takashi Iwai
2020-11-23  8:53 ` [PATCH 32/41] ALSA: usb-audio: Simplify rate_min/max and rates set up Takashi Iwai
2020-11-23  8:53 ` [PATCH 33/41] ALSA: usb-audio: Replace slave/master terms Takashi Iwai
2020-11-23  8:53 ` [PATCH 34/41] ALSA: usb-audio: Use unsigned char for iface and altsettings fields Takashi Iwai
2020-11-23  8:53 ` [PATCH 35/41] ALSA: usb-audio: Show sync endpoint information in proc outputs Takashi Iwai
2020-11-23  8:53 ` [PATCH 36/41] ALSA: usb-audio: Quirk for BOSS GT-001 Takashi Iwai
2020-11-23  8:53 ` [PATCH 37/41] ALSA: usb-audio: Factor out the implicit feedback quirk code Takashi Iwai
2020-11-23  8:53 ` [PATCH 38/41] ALSA: usb-audio: Add generic implicit fb parsing Takashi Iwai
2020-11-23  8:53 ` [PATCH 39/41] ALSA: usb-audio: Add implicit_fb module option Takashi Iwai
2020-11-23  9:46   ` Pavel Hofman
2020-11-23  8:53 ` [PATCH 40/41] ALSA: usb-audio: Fix quirks for other BOSS devices Takashi Iwai
2020-11-23  8:53 ` [PATCH 41/41] ALSA: usb-audio: Fix MOTU M-Series quirks Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.