All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] snd-usb endpoint rework, version 6
@ 2011-12-23 16:15 Daniel Mack
  2011-12-23 16:15 ` [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex Daniel Mack
                   ` (6 more replies)
  0 siblings, 7 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

Fortunately, the effects reported by Aurélien were easy to fix, and
indeed just regressions from previous version of the patch set. Those
are now out of the way, so here's version 6.

One thing that has also been added here is a sixth patch that adds
some documentation to endpoint.c to explain the concept of the new
implementation.

Thanks, and please have more test results coming.


Daniel


Daniel Mack (6):
  ALSA: snd-usb: add snd_usb_audio-wide mutex
  ALSA: snd-usb: implement new endpoint streaming model
  ALSA: snd-usb: switch over to new endpoint streaming logic
  ALSA: snd-usb: remove old streaming logic
  ALSA: snd-usb: add support for implicit feedback
  ALSA: snd-usb: add some documentation

 sound/usb/card.c     |   10 +-
 sound/usb/card.h     |   62 ++
 sound/usb/endpoint.c | 1602 ++++++++++++++++++++++++++++----------------------
 sound/usb/endpoint.h |   32 +-
 sound/usb/pcm.c      |  440 ++++++++++++---
 sound/usb/stream.c   |   31 +-
 sound/usb/usbaudio.h |    2 +
 7 files changed, 1381 insertions(+), 798 deletions(-)

-- 
1.7.7.4

_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-23 16:15 ` [PATCH 2/6] ALSA: snd-usb: implement new endpoint streaming model Daniel Mack
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

This is needed for new card-wide list operations.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/card.c     |    2 ++
 sound/usb/usbaudio.h |    1 +
 2 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4a7be7b..6bc88b7 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -276,6 +276,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
 
 static int snd_usb_audio_free(struct snd_usb_audio *chip)
 {
+	mutex_destroy(&chip->mutex);
 	kfree(chip);
 	return 0;
 }
@@ -336,6 +337,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 		return -ENOMEM;
 	}
 
+	mutex_init(&chip->mutex);
 	mutex_init(&chip->shutdown_mutex);
 	chip->index = idx;
 	chip->dev = dev;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 3e2b035..a16c21d 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -36,6 +36,7 @@ struct snd_usb_audio {
 	struct snd_card *card;
 	struct usb_interface *pm_intf;
 	u32 usb_id;
+	struct mutex mutex;
 	struct mutex shutdown_mutex;
 	unsigned int shutdown:1;
 	unsigned int probing:1;
-- 
1.7.7.4

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

* [PATCH 2/6] ALSA: snd-usb: implement new endpoint streaming model
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
  2011-12-23 16:15 ` [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-23 16:15 ` [PATCH 3/6] ALSA: snd-usb: switch over to new endpoint streaming logic Daniel Mack
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

This patch adds a new generic streaming logic for audio over USB.

It defines a model (snd_usb_endpoint) that handles everything that
is related to an USB endpoint and its streaming. There are functions to
activate and deactivate an endpoint (which call usb_set_interface()),
and to start and stop its URBs. It also has function pointers to be
called when data was received or is about to be sent, and pointer to
a sync slave (another snd_usb_endpoint) that is informed when data has
been received.

A snd_usb_endpoint knows about its state and implements a refcounting,
so only the first user will actually start the URBs and only the last
one to stop it will tear them down again.

With this sort of abstraction, the actual streaming is decoupled from
the pcm handling, which makes the "implicit feedback" mechanisms easy to
implement.

In order to split changes properly, this patch only adds the new
implementation but leaves the old one around, so the the driver doesn't
change its behaviour. The switch to actually use the new code is
submitted separately.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/card.h     |   58 ++++
 sound/usb/endpoint.c |  927 +++++++++++++++++++++++++++++++++++++++++++++++++-
 sound/usb/endpoint.h |   26 ++
 sound/usb/usbaudio.h |    1 +
 4 files changed, 1001 insertions(+), 11 deletions(-)

diff --git a/sound/usb/card.h b/sound/usb/card.h
index a39edcc..92228f1 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -29,13 +29,17 @@ struct audioformat {
 };
 
 struct snd_usb_substream;
+struct snd_usb_endpoint;
 
 struct snd_urb_ctx {
 	struct urb *urb;
 	unsigned int buffer_size;	/* size of data buffer, if data URB */
 	struct snd_usb_substream *subs;
+	struct snd_usb_endpoint *ep;
 	int index;	/* index for urb array */
 	int packets;	/* number of packets per urb */
+	int packet_size[MAX_PACKS_HS]; /* size of packets for next submission */
+	struct list_head ready_list;
 };
 
 struct snd_urb_ops {
@@ -45,6 +49,60 @@ struct snd_urb_ops {
 	int (*retire_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
 };
 
+struct snd_usb_endpoint {
+	struct snd_usb_audio *chip;
+
+	int use_count;
+	int ep_num;		/* the referenced endpoint number */
+	int type;		/* SND_USB_ENDPOINT_TYPE_* */
+	unsigned long flags;
+
+	void (*prepare_data_urb) (struct snd_usb_substream *subs,
+				  struct urb *urb);
+	void (*retire_data_urb) (struct snd_usb_substream *subs,
+				 struct urb *urb);
+
+	struct snd_usb_substream *data_subs;
+	struct snd_usb_endpoint *sync_master;
+	struct snd_usb_endpoint *sync_slave;
+
+	struct snd_urb_ctx urb[MAX_URBS];
+
+	struct snd_usb_packet_info {
+		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 nurbs;		/* # urbs */
+	unsigned long active_mask;	/* bitmask of active urbs */
+	unsigned long unlink_mask;	/* bitmask of unlinked urbs */
+	char *syncbuf;			/* sync buffer for all sync URBs */
+	dma_addr_t sync_dma;		/* DMA address of syncbuf */
+
+	unsigned int pipe;		/* the data i/o pipe */
+	unsigned int freqn;		/* nominal sampling rate in fs/fps in Q16.16 format */
+	unsigned int freqm;		/* momentary sampling rate in fs/fps in Q16.16 format */
+	int	   freqshift;		/* how much to shift the feedback value to get Q16.16 */
+	unsigned int freqmax;		/* maximum sampling rate, used for buffer management */
+	unsigned int phase;		/* phase accumulator */
+	unsigned int maxpacksize;	/* max packet size in bytes */
+	unsigned int maxframesize;      /* max packet size in frames */
+	unsigned int curpacksize;	/* current packet size in bytes (for capture) */
+	unsigned int curframesize;      /* current packet size in frames (for capture) */
+	unsigned int syncmaxsize;	/* sync endpoint packet size */
+	unsigned int fill_max:1;	/* fill max packet size always */
+	unsigned int datainterval;      /* log_2 of data packet interval */
+	unsigned int syncinterval;	/* P for adaptive mode, 0 otherwise */
+	unsigned char silence_value;
+	unsigned int stride;
+	int iface, alt_idx;
+
+	spinlock_t lock;
+	struct list_head list;
+};
+
 struct snd_usb_substream {
 	struct snd_usb_stream *stream;
 	struct usb_device *dev;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 81c6ede..eb47466 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -19,9 +19,11 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 #include <linux/usb/audio.h>
+#include <linux/slab.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 
 #include "usbaudio.h"
 #include "helper.h"
@@ -29,6 +31,9 @@
 #include "endpoint.h"
 #include "pcm.h"
 
+#define EP_FLAG_ACTIVATED	0
+#define EP_FLAG_RUNNING		1
+
 /*
  * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
  * this will overflow at approx 524 kHz
@@ -50,7 +55,7 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate)
 /*
  * unlink active urbs.
  */
-static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
+static int deactivate_urbs_old(struct snd_usb_substream *subs, int force, int can_sleep)
 {
 	struct snd_usb_audio *chip = subs->stream->chip;
 	unsigned int i;
@@ -112,7 +117,7 @@ static void release_urb_ctx(struct snd_urb_ctx *u)
 /*
  *  wait until all urbs are processed.
  */
-static int wait_clear_urbs(struct snd_usb_substream *subs)
+static int wait_clear_urbs_old(struct snd_usb_substream *subs)
 {
 	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
 	unsigned int i;
@@ -147,8 +152,8 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
 	int i;
 
 	/* stop urbs (to be sure) */
-	deactivate_urbs(subs, force, 1);
-	wait_clear_urbs(subs);
+	deactivate_urbs_old(subs, force, 1);
+	wait_clear_urbs_old(subs);
 
 	for (i = 0; i < MAX_URBS; i++)
 		release_urb_ctx(&subs->dataurb[i]);
@@ -163,7 +168,7 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
 /*
  * complete callback from data urb
  */
-static void snd_complete_urb(struct urb *urb)
+static void snd_complete_urb_old(struct urb *urb)
 {
 	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_substream *subs = ctx->subs;
@@ -317,7 +322,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
 		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		u->urb->interval = 1 << subs->datainterval;
 		u->urb->context = u;
-		u->urb->complete = snd_complete_urb;
+		u->urb->complete = snd_complete_urb_old;
 	}
 
 	if (subs->syncpipe) {
@@ -855,7 +860,7 @@ static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *ru
 
  __error:
 	// snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
-	deactivate_urbs(subs, 0, 0);
+	deactivate_urbs_old(subs, 0, 0);
 	return -EPIPE;
 }
 
@@ -916,7 +921,7 @@ int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int
 		subs->ops.prepare = prepare_playback_urb;
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs(subs, 0, 0);
+		return deactivate_urbs_old(subs, 0, 0);
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		subs->ops.prepare = prepare_nodata_playback_urb;
 		return 0;
@@ -934,7 +939,7 @@ int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int c
 		subs->ops.retire = retire_capture_urb;
 		return start_urbs(subs, substream->runtime);
 	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs(subs, 0, 0);
+		return deactivate_urbs_old(subs, 0, 0);
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		subs->ops.retire = retire_paused_capture_urb;
 		return 0;
@@ -950,8 +955,8 @@ int snd_usb_substream_prepare(struct snd_usb_substream *subs,
 			      struct snd_pcm_runtime *runtime)
 {
 	/* clear urbs (to be sure) */
-	deactivate_urbs(subs, 0, 1);
-	wait_clear_urbs(subs);
+	deactivate_urbs_old(subs, 0, 1);
+	wait_clear_urbs_old(subs);
 
 	/* for playback, submit the URBs now; otherwise, the first hwptr_done
 	 * updates for all URBs would happen at the same time when starting */
@@ -963,3 +968,903 @@ int snd_usb_substream_prepare(struct snd_usb_substream *subs,
 	return 0;
 }
 
+int snd_usb_endpoint_implict_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);
+}
+
+/* determine the number of frames in the next packet */
+static int next_packet_size(struct snd_usb_endpoint *ep)
+{
+	unsigned long flags;
+	int ret;
+
+	if (ep->fill_max)
+		return ep->maxframesize;
+
+	spin_lock_irqsave(&ep->lock, flags);
+	ep->phase = (ep->phase & 0xffff)
+		+ (ep->freqm << ep->datainterval);
+	ret = min(ep->phase >> 16, ep->maxframesize);
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	return ret;
+}
+
+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);
+}
+
+static void retire_inbound_urb(struct snd_usb_endpoint *ep,
+			       struct snd_urb_ctx *urb_ctx)
+{
+	struct urb *urb = urb_ctx->urb;
+
+	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);
+}
+
+static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
+				       struct snd_urb_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->packets; ++i)
+		ctx->packet_size[i] = next_packet_size(ep);
+}
+
+/*
+ * Prepare a PLAYBACK urb for submission to the bus.
+ */
+static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
+				 struct snd_urb_ctx *ctx)
+{
+	int i;
+	struct urb *urb = ctx->urb;
+	unsigned char *cp = urb->transfer_buffer;
+
+	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 */
+			unsigned int offs = 0;
+			for (i = 0; i < ctx->packets; ++i) {
+				int counts = ctx->packet_size[i];
+				urb->iso_frame_desc[i].offset = offs * ep->stride;
+				urb->iso_frame_desc[i].length = counts * ep->stride;
+				offs += counts;
+			}
+
+			urb->number_of_packets = ctx->packets;
+			urb->transfer_buffer_length = offs * ep->stride;
+			memset(urb->transfer_buffer, ep->silence_value,
+			       offs * ep->stride);
+		}
+		break;
+
+	case SND_USB_ENDPOINT_TYPE_SYNC:
+		if (snd_usb_get_speed(ep->chip->dev) >= USB_SPEED_HIGH) {
+			/*
+			 * fill the length and offset of each urb descriptor.
+			 * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+			 */
+			urb->iso_frame_desc[0].length = 4;
+			urb->iso_frame_desc[0].offset = 0;
+			cp[0] = ep->freqn;
+			cp[1] = ep->freqn >> 8;
+			cp[2] = ep->freqn >> 16;
+			cp[3] = ep->freqn >> 24;
+		} else {
+			/*
+			 * fill the length and offset of each urb descriptor.
+			 * the fixed 10.14 frequency is passed through the pipe.
+			 */
+			urb->iso_frame_desc[0].length = 3;
+			urb->iso_frame_desc[0].offset = 0;
+			cp[0] = ep->freqn >> 2;
+			cp[1] = ep->freqn >> 10;
+			cp[2] = ep->freqn >> 18;
+		}
+
+		break;
+	}
+}
+
+/*
+ * Prepare a CAPTURE or SYNC urb for submission to the bus.
+ */
+static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
+				       struct snd_urb_ctx *urb_ctx)
+{
+	int i, offs;
+	struct urb *urb = urb_ctx->urb;
+
+	urb->dev = ep->chip->dev; /* we need to set this at each time */
+
+	switch (ep->type) {
+	case SND_USB_ENDPOINT_TYPE_DATA:
+		offs = 0;
+		for (i = 0; i < urb_ctx->packets; i++) {
+			urb->iso_frame_desc[i].offset = offs;
+			urb->iso_frame_desc[i].length = ep->curpacksize;
+			offs += ep->curpacksize;
+		}
+
+		urb->transfer_buffer_length = offs;
+		urb->number_of_packets = urb_ctx->packets;
+		break;
+
+	case SND_USB_ENDPOINT_TYPE_SYNC:
+		urb->iso_frame_desc[0].length = min(4u, ep->syncmaxsize);
+		urb->iso_frame_desc[0].offset = 0;
+		break;
+	}
+}
+
+static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->lock, flags);
+
+	while (test_bit(EP_FLAG_RUNNING, &ep->flags) &&
+	       !list_empty(&ep->ready_playback_urbs) &&
+	       ep->next_packet_read_pos != ep->next_packet_write_pos) {
+
+		struct snd_usb_packet_info *packet;
+		struct snd_urb_ctx *ctx;
+		struct urb *urb;
+		int err, i;
+
+		packet = ep->next_packet + ep->next_packet_read_pos;
+		ep->next_packet_read_pos++;
+		ep->next_packet_read_pos %= MAX_URBS;
+
+		/* take URB out of FIFO */
+		ctx = list_first_entry(&ep->ready_playback_urbs,
+				       struct snd_urb_ctx, ready_list);
+		list_del(&ctx->ready_list);
+		urb = ctx->urb;
+
+		/* copy over the length information */
+		for (i = 0; i < packet->packets; i++)
+			ctx->packet_size[i] = packet->packet_size[i];
+
+		prepare_outbound_urb(ep, ctx);
+
+		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
+		if (err < 0)
+			snd_printk(KERN_ERR "Unable to submit urb #%d: %d (urb %p)\n",
+				   ctx->index, err, ctx->urb);
+		else
+			set_bit(ctx->index, &ep->active_mask);
+	}
+
+	spin_unlock_irqrestore(&ep->lock, flags);
+}
+
+/*
+ * complete callback for urbs
+ */
+static void snd_complete_urb(struct urb *urb)
+{
+	struct snd_urb_ctx *ctx = urb->context;
+	struct snd_usb_endpoint *ep = ctx->ep;
+	int err;
+
+	if (unlikely(urb->status == -ENOENT ||		/* unlinked */
+		     urb->status == -ENODEV ||		/* device removed */
+		     urb->status == -ECONNRESET ||	/* unlinked */
+		     urb->status == -ESHUTDOWN))	/* device disabled */
+		goto exit_clear;
+
+	if (usb_pipeout(ep->pipe)) {
+		retire_outbound_urb(ep, ctx);
+		/* can be stopped during retire callback */
+		if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+			goto exit_clear;
+
+		if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&ep->lock, flags);
+			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+			spin_unlock_irqrestore(&ep->lock, flags);
+			queue_pending_output_urbs(ep);
+
+			goto exit_clear;
+		}
+
+		prepare_outbound_urb_sizes(ep, ctx);
+		prepare_outbound_urb(ep, ctx);
+	} else {
+		retire_inbound_urb(ep, ctx);
+		/* can be stopped during retire callback */
+		if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+			goto exit_clear;
+
+		prepare_inbound_urb(ep, ctx);
+	}
+
+	err = usb_submit_urb(urb, GFP_ATOMIC);
+	if (err == 0)
+		return;
+
+	snd_printk(KERN_ERR "cannot submit urb (err = %d)\n", err);
+	//snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+
+exit_clear:
+	clear_bit(ctx->index, &ep->active_mask);
+}
+
+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)
+{
+	struct list_head *p;
+	struct snd_usb_endpoint *ep;
+	int ret, is_playback = direction == SNDRV_PCM_STREAM_PLAYBACK;
+
+	mutex_lock(&chip->mutex);
+
+	list_for_each(p, &chip->ep_list) {
+		ep = list_entry(p, struct snd_usb_endpoint, list);
+		if (ep->ep_num == ep_num &&
+		    ep->iface == alts->desc.bInterfaceNumber &&
+		    ep->alt_idx == alts->desc.bAlternateSetting) {
+			snd_printdd(KERN_DEBUG "Re-using EP %x in iface %d,%d @%p\n",
+					ep_num, ep->iface, ep->alt_idx, ep);
+			goto __exit_unlock;
+		}
+	}
+
+	snd_printdd(KERN_DEBUG "Creating new %s %s endpoint #%x\n",
+		   is_playback ? "playback" : "capture",
+		   type == SND_USB_ENDPOINT_TYPE_DATA ? "data" : "sync",
+		   ep_num);
+
+	/* select the alt setting once so the endpoints become valid */
+	ret = usb_set_interface(chip->dev, alts->desc.bInterfaceNumber,
+				alts->desc.bAlternateSetting);
+	if (ret < 0) {
+		snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
+					__func__, ret);
+		ep = NULL;
+		goto __exit_unlock;
+	}
+
+	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+	if (!ep)
+		goto __exit_unlock;
+
+	ep->chip = chip;
+	spin_lock_init(&ep->lock);
+	ep->type = type;
+	ep->ep_num = ep_num;
+	ep->iface = alts->desc.bInterfaceNumber;
+	ep->alt_idx = alts->desc.bAlternateSetting;
+	INIT_LIST_HEAD(&ep->ready_playback_urbs);
+	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;
+		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
+			ep->syncinterval = 3;
+
+		ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
+	}
+
+	list_add_tail(&ep->list, &chip->ep_list);
+
+__exit_unlock:
+	mutex_unlock(&chip->mutex);
+
+	return ep;
+}
+
+/*
+ *  wait until all urbs are processed.
+ */
+static int wait_clear_urbs(struct snd_usb_endpoint *ep)
+{
+	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
+	unsigned int i;
+	int alive;
+
+	do {
+		alive = 0;
+		for (i = 0; i < ep->nurbs; i++)
+			if (test_bit(i, &ep->active_mask))
+				alive++;
+
+		if (!alive)
+			break;
+
+		schedule_timeout_uninterruptible(1);
+	} while (time_before(jiffies, end_time));
+
+	if (alive)
+		snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
+					alive, ep->ep_num);
+
+	return 0;
+}
+
+/*
+ * unlink active urbs.
+ */
+static int deactivate_urbs(struct snd_usb_endpoint *ep, int force, int can_sleep)
+{
+	unsigned long flags;
+	unsigned int i;
+	int async;
+
+	if (!force && ep->chip->shutdown) /* to be sure... */
+		return -EBADFD;
+
+	async = !can_sleep && ep->chip->async_unlink;
+
+	clear_bit(EP_FLAG_RUNNING, &ep->flags);
+
+	spin_lock_irqsave(&ep->lock, flags);
+	INIT_LIST_HEAD(&ep->ready_playback_urbs);
+	ep->next_packet_read_pos = 0;
+	ep->next_packet_write_pos = 0;
+	spin_unlock_irqrestore(&ep->lock, flags);
+
+	if (!async && in_interrupt())
+		return 0;
+
+	for (i = 0; i < ep->nurbs; i++) {
+		if (test_bit(i, &ep->active_mask)) {
+			if (!test_and_set_bit(i, &ep->unlink_mask)) {
+				struct urb *u = ep->urb[i].urb;
+				if (async)
+					usb_unlink_urb(u);
+				else
+					usb_kill_urb(u);
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * release an endpoint's urbs
+ */
+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;
+
+	/* stop urbs */
+	deactivate_urbs(ep, force, 1);
+	wait_clear_urbs(ep);
+
+	for (i = 0; i < ep->nurbs; i++)
+		release_urb_ctx(&ep->urb[i]);
+
+	if (ep->syncbuf)
+		usb_free_coherent(ep->chip->dev, SYNC_URBS * 4,
+				  ep->syncbuf, ep->sync_dma);
+
+	ep->syncbuf = NULL;
+	ep->nurbs = 0;
+}
+
+static int data_ep_set_params(struct snd_usb_endpoint *ep,
+			      struct snd_pcm_hw_params *hw_params,
+			      struct audioformat *fmt,
+			      struct snd_usb_endpoint *sync_ep)
+{
+	unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms;
+	int period_bytes = params_period_bytes(hw_params);
+	int format = params_format(hw_params);
+	int is_playback = usb_pipeout(ep->pipe);
+	int frame_bits = snd_pcm_format_physical_width(params_format(hw_params)) *
+							params_channels(hw_params);
+
+	ep->datainterval = fmt->datainterval;
+	ep->stride = frame_bits >> 3;
+	ep->silence_value = format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;
+
+	/* calculate max. frequency */
+	if (ep->maxpacksize) {
+		/* whatever fits into a max. size packet */
+		maxsize = ep->maxpacksize;
+		ep->freqmax = (maxsize / (frame_bits >> 3))
+				<< (16 - ep->datainterval);
+	} else {
+		/* no max. packet size: just take 25% higher than nominal */
+		ep->freqmax = ep->freqn + (ep->freqn >> 2);
+		maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
+				>> (16 - ep->datainterval);
+	}
+
+	if (ep->fill_max)
+		ep->curpacksize = ep->maxpacksize;
+	else
+		ep->curpacksize = maxsize;
+
+	if (snd_usb_get_speed(ep->chip->dev) != USB_SPEED_FULL)
+		packs_per_ms = 8 >> ep->datainterval;
+	else
+		packs_per_ms = 1;
+
+	if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
+		urb_packs = max(ep->chip->nrpacks, 1);
+		urb_packs = min(urb_packs, (unsigned int) MAX_PACKS);
+	} else {
+		urb_packs = 1;
+	}
+
+	urb_packs *= packs_per_ms;
+
+	if (sync_ep && !snd_usb_endpoint_implict_feedback_sink(ep))
+		urb_packs = min(urb_packs, 1U << sync_ep->syncinterval);
+
+	/* decide how many packets to be used */
+	if (is_playback && !snd_usb_endpoint_implict_feedback_sink(ep)) {
+		unsigned int minsize, maxpacks;
+		/* 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);
+		total_packs = (period_bytes + minsize - 1) / minsize;
+		/* we need at least two URBs for queueing */
+		if (total_packs < 2) {
+			total_packs = 2;
+		} else {
+			/* and we don't want too long a queue either */
+			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+			total_packs = min(total_packs, maxpacks);
+		}
+	} else {
+		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+			urb_packs >>= 1;
+		total_packs = MAX_URBS * urb_packs;
+	}
+
+	ep->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+	if (ep->nurbs > MAX_URBS) {
+		/* too much... */
+		ep->nurbs = MAX_URBS;
+		total_packs = MAX_URBS * urb_packs;
+	} else if (ep->nurbs < 2) {
+		/* too little - we need at least two packets
+		 * to ensure contiguous playback/capture
+		 */
+		ep->nurbs = 2;
+	}
+
+	/* allocate and initialize data urbs */
+	for (i = 0; i < ep->nurbs; i++) {
+		struct snd_urb_ctx *u = &ep->urb[i];
+		u->index = i;
+		u->ep = ep;
+		u->packets = (i + 1) * total_packs / ep->nurbs
+			- i * total_packs / ep->nurbs;
+		u->buffer_size = maxsize * u->packets;
+
+		if (fmt->fmt_type == UAC_FORMAT_TYPE_II)
+			u->packets++; /* for transfer delimiter */
+		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+		if (!u->urb)
+			goto out_of_memory;
+
+		u->urb->transfer_buffer =
+			usb_alloc_coherent(ep->chip->dev, u->buffer_size,
+					   GFP_KERNEL, &u->urb->transfer_dma);
+		if (!u->urb->transfer_buffer)
+			goto out_of_memory;
+		u->urb->pipe = ep->pipe;
+		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		u->urb->interval = 1 << ep->datainterval;
+		u->urb->context = u;
+		u->urb->complete = snd_complete_urb;
+	}
+
+	return 0;
+
+out_of_memory:
+	release_urbs(ep, 0);
+	return -ENOMEM;
+}
+
+static int sync_ep_set_params(struct snd_usb_endpoint *ep,
+			      struct snd_pcm_hw_params *hw_params,
+			      struct audioformat *fmt)
+{
+	int i;
+
+	ep->syncbuf = usb_alloc_coherent(ep->chip->dev, SYNC_URBS * 4,
+					 GFP_KERNEL, &ep->sync_dma);
+	if (!ep->syncbuf)
+		return -ENOMEM;
+
+	for (i = 0; i < SYNC_URBS; i++) {
+		struct snd_urb_ctx *u = &ep->urb[i];
+		u->index = i;
+		u->ep = ep;
+		u->packets = 1;
+		u->urb = usb_alloc_urb(1, GFP_KERNEL);
+		if (!u->urb)
+			goto out_of_memory;
+		u->urb->transfer_buffer = ep->syncbuf + i * 4;
+		u->urb->transfer_dma = ep->sync_dma + i * 4;
+		u->urb->transfer_buffer_length = 4;
+		u->urb->pipe = ep->pipe;
+		u->urb->transfer_flags = URB_ISO_ASAP |
+					 URB_NO_TRANSFER_DMA_MAP;
+		u->urb->number_of_packets = 1;
+		u->urb->interval = 1 << ep->syncinterval;
+		u->urb->context = u;
+		u->urb->complete = snd_complete_urb;
+	}
+
+	ep->nurbs = SYNC_URBS;
+
+	return 0;
+
+out_of_memory:
+	release_urbs(ep, 0);
+	return -ENOMEM;
+}
+
+int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
+				struct snd_pcm_hw_params *hw_params,
+				struct audioformat *fmt,
+				struct snd_usb_endpoint *sync_ep)
+{
+	int err;
+
+	if (ep->use_count != 0) {
+		snd_printk(KERN_WARNING "Unable to change format on ep #%x: already in use\n",
+			   ep->ep_num);
+		return -EBUSY;
+	}
+
+	/* release old buffers, if any */
+	release_urbs(ep, 0);
+
+	ep->datainterval = fmt->datainterval;
+	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(params_rate(hw_params));
+	else
+		ep->freqn = get_usb_high_speed_rate(params_rate(hw_params));
+
+	/* calculate the frequency in 16.16 format */
+	ep->freqm = ep->freqn;
+	ep->freqshift = INT_MIN;
+
+	ep->phase = 0;
+
+	switch (ep->type) {
+	case  SND_USB_ENDPOINT_TYPE_DATA:
+		err = data_ep_set_params(ep, hw_params, fmt, sync_ep);
+		break;
+	case  SND_USB_ENDPOINT_TYPE_SYNC:
+		err = sync_ep_set_params(ep, hw_params, fmt);
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	snd_printdd(KERN_DEBUG "Setting params for ep #%x (type %d, %d urbs), ret=%d\n",
+		   ep->ep_num, ep->type, ep->nurbs, err);
+
+	return err;
+}
+
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
+{
+	int err;
+	unsigned int i;
+
+	if (ep->chip->shutdown)
+		return -EBADFD;
+
+	/* already running? */
+	if (++ep->use_count != 1)
+		return 0;
+
+	if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
+		return -EINVAL;
+
+	/* just to be sure */
+	deactivate_urbs(ep, 0, 1);
+	wait_clear_urbs(ep);
+
+	ep->active_mask = 0;
+	ep->unlink_mask = 0;
+	ep->phase = 0;
+
+	/*
+	 * If this endpoint has a data endpoint as implicit feedback source,
+	 * don't start the urbs here. Instead, mark them all as available,
+	 * wait for the record urbs to arrive and queue from that context.
+	 */
+
+	set_bit(EP_FLAG_RUNNING, &ep->flags);
+
+	if (snd_usb_endpoint_implict_feedback_sink(ep)) {
+		for (i = 0; i < ep->nurbs; i++) {
+			struct snd_urb_ctx *ctx = ep->urb + i;
+			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
+		}
+
+		return 0;
+	}
+
+	for (i = 0; i < ep->nurbs; i++) {
+		struct urb *urb = ep->urb[i].urb;
+
+		if (snd_BUG_ON(!urb))
+			goto __error;
+
+		if (usb_pipeout(ep->pipe)) {
+			prepare_outbound_urb_sizes(ep, urb->context);
+			prepare_outbound_urb(ep, urb->context);
+		} else {
+			prepare_inbound_urb(ep, urb->context);
+		}
+
+		err = usb_submit_urb(urb, GFP_ATOMIC);
+		if (err < 0) {
+			snd_printk(KERN_ERR "cannot submit urb %d, error %d: %s\n",
+				   i, err, usb_error_string(err));
+			goto __error;
+		}
+		set_bit(i, &ep->active_mask);
+	}
+
+	return 0;
+
+__error:
+	clear_bit(EP_FLAG_RUNNING, &ep->flags);
+	ep->use_count--;
+	deactivate_urbs(ep, 0, 0);
+	return -EPIPE;
+}
+
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
+			   int force, int can_sleep, int wait)
+{
+	if (!ep)
+		return;
+
+	if (snd_BUG_ON(ep->use_count == 0))
+		return;
+
+	if (snd_BUG_ON(!test_bit(EP_FLAG_ACTIVATED, &ep->flags)))
+		return;
+
+	if (--ep->use_count == 0) {
+		deactivate_urbs(ep, force, can_sleep);
+		ep->data_subs = NULL;
+		ep->sync_slave = NULL;
+		ep->retire_data_urb = NULL;
+		ep->prepare_data_urb = NULL;
+
+		if (wait)
+			wait_clear_urbs(ep);
+	}
+}
+
+int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
+{
+	if (ep->use_count != 0)
+		return 0;
+
+	if (!ep->chip->shutdown &&
+	    !test_and_set_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
+		int ret;
+
+		ret = usb_set_interface(ep->chip->dev, ep->iface, ep->alt_idx);
+		if (ret < 0) {
+			snd_printk(KERN_ERR "%s() usb_set_interface() failed, ret = %d\n",
+						__func__, ret);
+			clear_bit(EP_FLAG_ACTIVATED, &ep->flags);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
+{
+	if (!ep)
+		return -EINVAL;
+
+	if (ep->use_count != 0)
+		return 0;
+
+	if (!ep->chip->shutdown &&
+	    test_and_clear_bit(EP_FLAG_ACTIVATED, &ep->flags)) {
+		int ret;
+
+		ret = usb_set_interface(ep->chip->dev, ep->iface, 0);
+		if (ret < 0) {
+			snd_printk(KERN_ERR "%s(): usb_set_interface() failed, ret = %d\n",
+						__func__, ret);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	return -EBUSY;
+}
+
+void snd_usb_endpoint_free(struct list_head *head)
+{
+	struct snd_usb_endpoint *ep;
+
+	ep = list_entry(head, struct snd_usb_endpoint, list);
+	release_urbs(ep, 1);
+	kfree(ep);
+}
+
+/*
+ * process after playback sync complete
+ *
+ * Full speed devices report feedback values in 10.14 format as samples per
+ * frame, high speed devices in 16.16 format as samples per microframe.
+ * Because the Audio Class 1 spec was written before USB 2.0, many high speed
+ * devices use a wrong interpretation, some others use an entirely different
+ * format.  Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
+ */
+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;
+	unsigned long flags;
+
+	snd_BUG_ON(ep == sender);
+
+	if (snd_usb_endpoint_implict_feedback_sink(ep) &&
+	    ep->use_count != 0) {
+
+		/* implicit feedback case */
+		int i, bytes = 0;
+		struct snd_urb_ctx *in_ctx;
+		struct snd_usb_packet_info *out_packet;
+
+		in_ctx = urb->context;
+
+		/* Count overall packet size */
+		for (i = 0; i < in_ctx->packets; i++)
+			if (urb->iso_frame_desc[i].status == 0)
+				bytes += urb->iso_frame_desc[i].actual_length;
+
+		/*
+		 * skip empty packets. At least M-Audio's Fast Track Ultra stops
+		 * streaming once it received a 0-byte OUT URB
+		 */
+		if (bytes == 0)
+			return;
+
+		spin_lock_irqsave(&ep->lock, flags);
+		out_packet = ep->next_packet + ep->next_packet_write_pos;
+
+		/*
+		 * Iterate through the inbound packet and prepare the lengths
+		 * for the output packet. The OUT packet we are about to send
+		 * will have the same amount of payload than the IN packet we
+		 * just received.
+		 */
+
+		out_packet->packets = in_ctx->packets;
+		for (i = 0; i < in_ctx->packets; i++) {
+			if (urb->iso_frame_desc[i].status == 0)
+				out_packet->packet_size[i] =
+					urb->iso_frame_desc[i].actual_length / ep->stride;
+			else
+				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);
+
+		return;
+	}
+
+	/* parse sync endpoint packet */
+
+	if (urb->iso_frame_desc[0].status != 0 ||
+	    urb->iso_frame_desc[0].actual_length < 3)
+		return;
+
+	f = le32_to_cpup(urb->transfer_buffer);
+	if (urb->iso_frame_desc[0].actual_length == 3)
+		f &= 0x00ffffff;
+	else
+		f &= 0x0fffffff;
+
+	if (f == 0)
+		return;
+
+	if (unlikely(ep->freqshift == INT_MIN)) {
+		/*
+		 * The first time we see a feedback value, determine its format
+		 * by shifting it left or right until it matches the nominal
+		 * frequency value.  This assumes that the feedback does not
+		 * differ from the nominal value more than +50% or -25%.
+		 */
+		shift = 0;
+		while (f < ep->freqn - ep->freqn / 4) {
+			f <<= 1;
+			shift++;
+		}
+		while (f > ep->freqn + ep->freqn / 2) {
+			f >>= 1;
+			shift--;
+		}
+		ep->freqshift = shift;
+	}
+	else if (ep->freqshift >= 0)
+		f <<= ep->freqshift;
+	else
+		f >>= -ep->freqshift;
+
+	if (likely(f >= ep->freqn - ep->freqn / 8 && f <= ep->freqmax)) {
+		/*
+		 * If the frequency looks valid, set it.
+		 * This value is referred to in prepare_playback_urb().
+		 */
+		spin_lock_irqsave(&ep->lock, flags);
+		ep->freqm = f;
+		spin_unlock_irqrestore(&ep->lock, flags);
+	} else {
+		/*
+		 * Out of range; maybe the shift value is wrong.
+		 * Reset it so that we autodetect again the next time.
+		 */
+		ep->freqshift = INT_MIN;
+	}
+}
+
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 88eb63a..9f083d7 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -18,4 +18,30 @@ int snd_usb_substream_prepare(struct snd_usb_substream *subs,
 int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
 int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
 
+
+#define SND_USB_ENDPOINT_TYPE_DATA     0
+#define SND_USB_ENDPOINT_TYPE_SYNC     1
+
+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_endpoint_set_params(struct snd_usb_endpoint *ep,
+				struct snd_pcm_hw_params *hw_params,
+				struct audioformat *fmt,
+				struct snd_usb_endpoint *sync_ep);
+
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
+			   int force, int can_sleep, int wait);
+int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
+int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
+void snd_usb_endpoint_free(struct list_head *head);
+
+int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+
+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/usbaudio.h b/sound/usb/usbaudio.h
index a16c21d..b8233eb 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -47,6 +47,7 @@ struct snd_usb_audio {
 	int num_suspended_intf;
 
 	struct list_head pcm_list;	/* list of pcm streams */
+	struct list_head ep_list;	/* list of audio-related endpoints */
 	int pcm_devs;
 
 	struct list_head midi_list;	/* list of midi interfaces */
-- 
1.7.7.4

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

* [PATCH 3/6] ALSA: snd-usb: switch over to new endpoint streaming logic
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
  2011-12-23 16:15 ` [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex Daniel Mack
  2011-12-23 16:15 ` [PATCH 2/6] ALSA: snd-usb: implement new endpoint streaming model Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-23 16:15 ` [PATCH 4/6] ALSA: snd-usb: remove old " Daniel Mack
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

With the previous commit that added the new streaming model, all
endpoint and streaming related code is now in endpoint.c, and pcm.c
only acts as a wrapper for handling the packet's payload.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/card.c     |    8 +-
 sound/usb/card.h     |    4 +
 sound/usb/endpoint.c |   40 -----
 sound/usb/endpoint.h |    3 -
 sound/usb/pcm.c      |  417 +++++++++++++++++++++++++++++++++++++++++---------
 sound/usb/stream.c   |   31 ++++-
 6 files changed, 384 insertions(+), 119 deletions(-)

diff --git a/sound/usb/card.c b/sound/usb/card.c
index 6bc88b7..d5b5c33 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -131,8 +131,9 @@ static void snd_usb_stream_disconnect(struct list_head *head)
 		subs = &as->substream[idx];
 		if (!subs->num_formats)
 			continue;
-		snd_usb_release_substream_urbs(subs, 1);
 		subs->interface = -1;
+		subs->data_endpoint = NULL;
+		subs->sync_endpoint = NULL;
 	}
 }
 
@@ -350,6 +351,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 			      le16_to_cpu(dev->descriptor.idProduct));
 	INIT_LIST_HEAD(&chip->pcm_list);
+	INIT_LIST_HEAD(&chip->ep_list);
 	INIT_LIST_HEAD(&chip->midi_list);
 	INIT_LIST_HEAD(&chip->mixer_list);
 
@@ -567,6 +569,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
 		list_for_each(p, &chip->pcm_list) {
 			snd_usb_stream_disconnect(p);
 		}
+		/* release the endpoint resources */
+		list_for_each(p, &chip->ep_list) {
+			snd_usb_endpoint_free(p);
+		}
 		/* release the midi resources */
 		list_for_each(p, &chip->midi_list) {
 			snd_usbmidi_disconnect(p);
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 92228f1..90681f7 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -144,6 +144,10 @@ struct snd_usb_substream {
 	struct snd_urb_ctx syncurb[SYNC_URBS];	/* sync urb table */
 	char *syncbuf;				/* sync buffer for all sync URBs */
 	dma_addr_t sync_dma;			/* DMA address of syncbuf */
+	/* data and sync endpoints for this stream */
+	struct snd_usb_endpoint *data_endpoint;
+	struct snd_usb_endpoint *sync_endpoint;
+	unsigned long flags;
 
 	u64 formats;			/* format bitmasks (all or'ed) */
 	unsigned int num_formats;		/* number of supported audio formats (list) */
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index eb47466..93d6590 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -911,46 +911,6 @@ void snd_usb_init_substream(struct snd_usb_stream *as,
 	subs->fmt_type = fp->fmt_type;
 }
 
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_usb_substream *subs = substream->runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->ops.prepare = prepare_playback_urb;
-		return 0;
-	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs_old(subs, 0, 0);
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->ops.prepare = prepare_nodata_playback_urb;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_usb_substream *subs = substream->runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		subs->ops.retire = retire_capture_urb;
-		return start_urbs(subs, substream->runtime);
-	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs_old(subs, 0, 0);
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->ops.retire = retire_paused_capture_urb;
-		return 0;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->ops.retire = retire_capture_urb;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 int snd_usb_substream_prepare(struct snd_usb_substream *subs,
 			      struct snd_pcm_runtime *runtime)
 {
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 9f083d7..e540768 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -15,9 +15,6 @@ void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
 int snd_usb_substream_prepare(struct snd_usb_substream *subs,
 			      struct snd_pcm_runtime *runtime);
 
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
-
 
 #define SND_USB_ENDPOINT_TYPE_DATA     0
 #define SND_USB_ENDPOINT_TYPE_SYNC     1
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 0220b0f..271579c 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -34,6 +34,9 @@
 #include "clock.h"
 #include "power.h"
 
+#define SUBSTREAM_FLAG_DATA_EP_STARTED	0
+#define SUBSTREAM_FLAG_SYNC_EP_STARTED	1
+
 /* return the estimated delay based on USB frame counters */
 snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
 				    unsigned int rate)
@@ -208,6 +211,84 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
 	}
 }
 
+static int start_endpoints(struct snd_usb_substream *subs)
+{
+	int err;
+
+	if (!subs->data_endpoint)
+		return -EINVAL;
+
+	if (!test_and_set_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags)) {
+		struct snd_usb_endpoint *ep = subs->data_endpoint;
+
+		snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
+
+		ep->data_subs = subs;
+		err = snd_usb_endpoint_start(ep);
+		if (err < 0) {
+			clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
+			return err;
+		}
+	}
+
+	if (subs->sync_endpoint &&
+	    !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
+		struct snd_usb_endpoint *ep = subs->sync_endpoint;
+
+		snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
+
+		ep->sync_slave = subs->data_endpoint;
+		err = snd_usb_endpoint_start(ep);
+		if (err < 0) {
+			clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static void stop_endpoints(struct snd_usb_substream *subs,
+			   int force, int can_sleep, int wait)
+{
+	if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
+		snd_usb_endpoint_stop(subs->sync_endpoint,
+				      force, can_sleep, wait);
+
+	if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
+		snd_usb_endpoint_stop(subs->data_endpoint,
+				      force, can_sleep, wait);
+}
+
+static int activate_endpoints(struct snd_usb_substream *subs)
+{
+	if (subs->sync_endpoint) {
+		int ret;
+
+		ret = snd_usb_endpoint_activate(subs->sync_endpoint);
+		if (ret < 0)
+			return ret;
+	}
+
+	return snd_usb_endpoint_activate(subs->data_endpoint);
+}
+
+static int deactivate_endpoints(struct snd_usb_substream *subs)
+{
+	int reta, retb;
+
+	reta = snd_usb_endpoint_deactivate(subs->sync_endpoint);
+	retb = snd_usb_endpoint_deactivate(subs->data_endpoint);
+
+	if (reta < 0)
+		return reta;
+
+	if (retb < 0)
+		return retb;
+
+	return 0;
+}
+
 /*
  * find a matching format and set up the interface
  */
@@ -232,40 +313,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	if (fmt == subs->cur_audiofmt)
 		return 0;
 
-	/* close the old interface */
-	if (subs->interface >= 0 && subs->interface != fmt->iface) {
-		if (usb_set_interface(subs->dev, subs->interface, 0) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: return to setting 0 failed\n",
-				dev->devnum, fmt->iface, fmt->altsetting);
-			return -EIO;
-		}
-		subs->interface = -1;
-		subs->altset_idx = 0;
-	}
-
-	/* set interface */
-	if (subs->interface != fmt->iface || subs->altset_idx != fmt->altset_idx) {
-		if (usb_set_interface(dev, fmt->iface, fmt->altsetting) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: usb_set_interface failed\n",
-				   dev->devnum, fmt->iface, fmt->altsetting);
-			return -EIO;
-		}
-		snd_printdd(KERN_INFO "setting usb interface %d:%d\n", fmt->iface, fmt->altsetting);
-		subs->interface = fmt->iface;
-		subs->altset_idx = fmt->altset_idx;
-	}
-
-	/* create a data pipe */
-	ep = fmt->endpoint & USB_ENDPOINT_NUMBER_MASK;
-	if (is_playback)
-		subs->datapipe = usb_sndisocpipe(dev, ep);
-	else
-		subs->datapipe = usb_rcvisocpipe(dev, ep);
-	subs->datainterval = fmt->datainterval;
-	subs->syncpipe = subs->syncinterval = 0;
-	subs->maxpacksize = fmt->maxpacksize;
-	subs->syncmaxsize = 0;
-	subs->fill_max = 0;
+	subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+						   alts, fmt->endpoint, subs->direction,
+						   SND_USB_ENDPOINT_TYPE_DATA);
+	if (!subs->data_endpoint)
+		return -EINVAL;
 
 	/* we need a sync pipe in async OUT or adaptive IN mode */
 	/* check the number of EP, since some devices have broken
@@ -276,6 +328,15 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
 	     (! is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
 	    altsd->bNumEndpoints >= 2) {
+		switch (subs->stream->chip->usb_id) {
+		case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
+		case USB_ID(0x0763, 0x2081):
+			ep = 0x81;
+			iface = usb_ifnum_to_if(dev, 2);
+			alts = &iface->altsetting[1];
+			goto add_sync_ep;
+		}
+
 		/* check sync-pipe endpoint */
 		/* ... and check descriptor size before accessing bSynchAddress
 		   because there is a version of the SB Audigy 2 NX firmware lacking
@@ -295,28 +356,16 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 				   dev->devnum, fmt->iface, fmt->altsetting);
 			return -EINVAL;
 		}
-		ep &= USB_ENDPOINT_NUMBER_MASK;
-		if (is_playback)
-			subs->syncpipe = usb_rcvisocpipe(dev, ep);
-		else
-			subs->syncpipe = usb_sndisocpipe(dev, ep);
-		if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		    get_endpoint(alts, 1)->bRefresh >= 1 &&
-		    get_endpoint(alts, 1)->bRefresh <= 9)
-			subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
-		else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
-			subs->syncinterval = 1;
-		else if (get_endpoint(alts, 1)->bInterval >= 1 &&
-			 get_endpoint(alts, 1)->bInterval <= 16)
-			subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
-		else
-			subs->syncinterval = 3;
-		subs->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
-	}
-
-	/* always fill max packet size */
-	if (fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX)
-		subs->fill_max = 1;
+add_sync_ep:
+		subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
+							   alts, ep, !subs->direction,
+							   SND_USB_ENDPOINT_TYPE_SYNC);
+
+		if (!subs->sync_endpoint)
+			return -EINVAL;
+
+		subs->data_endpoint->sync_master = subs->sync_endpoint;
+	}
 
 	if ((err = snd_usb_init_pitch(subs->stream->chip, subs->interface, alts, fmt)) < 0)
 		return err;
@@ -390,12 +439,22 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
 	if (changed) {
 		mutex_lock(&subs->stream->chip->shutdown_mutex);
 		/* format changed */
-		snd_usb_release_substream_urbs(subs, 0);
-		/* influenced: period_bytes, channels, rate, format, */
-		ret = snd_usb_init_substream_urbs(subs, params_period_bytes(hw_params),
-						  params_rate(hw_params),
-						  snd_pcm_format_physical_width(params_format(hw_params)) *
-							params_channels(hw_params));
+		stop_endpoints(subs, 0, 0, 0);
+		deactivate_endpoints(subs);
+
+		ret = activate_endpoints(subs);
+		if (ret < 0)
+			goto unlock;
+
+		ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt,
+						  subs->sync_endpoint);
+		if (ret < 0)
+			goto unlock;
+
+		if (subs->sync_endpoint)
+			ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
+							  hw_params, fmt, NULL);
+unlock:
 		mutex_unlock(&subs->stream->chip->shutdown_mutex);
 	}
 
@@ -415,7 +474,7 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
 	subs->cur_rate = 0;
 	subs->period_bytes = 0;
 	mutex_lock(&subs->stream->chip->shutdown_mutex);
-	snd_usb_release_substream_urbs(subs, 0);
+	stop_endpoints(subs, 0, 1, 1);
 	mutex_unlock(&subs->stream->chip->shutdown_mutex);
 	return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
@@ -435,19 +494,28 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 		return -ENXIO;
 	}
 
+	if (snd_BUG_ON(!subs->data_endpoint))
+		return -EIO;
+
 	/* some unit conversions in runtime */
-	subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize);
-	subs->curframesize = bytes_to_frames(runtime, subs->curpacksize);
+	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;
-	subs->phase = 0;
 	subs->last_delay = 0;
 	subs->last_frame_number = 0;
 	runtime->delay = 0;
 
-	return snd_usb_substream_prepare(subs, runtime);
+	/* for playback, submit the URBs now; otherwise, the first hwptr_done
+	 * updates for all URBs would happen at the same time when starting */
+	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
+		return start_endpoints(subs);
+
+	return 0;
 }
 
 static struct snd_pcm_hardware snd_usb_hardware =
@@ -840,16 +908,171 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 
 static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 {
+	int ret;
 	struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
 	struct snd_usb_substream *subs = &as->substream[direction];
 
-	if (!as->chip->shutdown && subs->interface >= 0) {
-		usb_set_interface(subs->dev, subs->interface, 0);
-		subs->interface = -1;
-	}
+	stop_endpoints(subs, 0, 0, 0);
+	ret = deactivate_endpoints(subs);
 	subs->pcm_substream = NULL;
 	snd_usb_autosuspend(subs->stream->chip);
-	return 0;
+
+	return ret;
+}
+
+/* Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
+ */
+static void retire_capture_urb(struct snd_usb_substream *subs,
+			       struct urb *urb)
+{
+	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+	unsigned int stride, frames, bytes, oldptr;
+	int i, period_elapsed = 0;
+	unsigned long flags;
+	unsigned char *cp;
+
+	stride = runtime->frame_bits >> 3;
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (urb->iso_frame_desc[i].status) {
+			snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+			// continue;
+		}
+		bytes = urb->iso_frame_desc[i].actual_length;
+		frames = bytes / stride;
+		if (!subs->txfr_quirk)
+			bytes = frames * stride;
+		if (bytes % (runtime->sample_bits >> 3) != 0) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+			int oldbytes = bytes;
+#endif
+			bytes = frames * stride;
+			snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+							oldbytes, bytes);
+		}
+		/* update the current pointer */
+		spin_lock_irqsave(&subs->lock, flags);
+		oldptr = subs->hwptr_done;
+		subs->hwptr_done += bytes;
+		if (subs->hwptr_done >= runtime->buffer_size * stride)
+			subs->hwptr_done -= runtime->buffer_size * stride;
+		frames = (bytes + (oldptr % stride)) / stride;
+		subs->transfer_done += frames;
+		if (subs->transfer_done >= runtime->period_size) {
+			subs->transfer_done -= runtime->period_size;
+			period_elapsed = 1;
+		}
+		spin_unlock_irqrestore(&subs->lock, flags);
+		/* copy a data chunk */
+		if (oldptr + bytes > runtime->buffer_size * stride) {
+			unsigned int bytes1 =
+					runtime->buffer_size * stride - oldptr;
+			memcpy(runtime->dma_area + oldptr, cp, bytes1);
+			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
+		} else {
+			memcpy(runtime->dma_area + oldptr, cp, bytes);
+		}
+	}
+
+	if (period_elapsed)
+		snd_pcm_period_elapsed(subs->pcm_substream);
+}
+
+static void prepare_playback_urb(struct snd_usb_substream *subs,
+				 struct urb *urb)
+{
+	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+	struct snd_urb_ctx *ctx = urb->context;
+	unsigned int counts, frames, bytes;
+	int i, stride, period_elapsed = 0;
+	unsigned long flags;
+
+	stride = runtime->frame_bits >> 3;
+
+	frames = 0;
+	urb->number_of_packets = 0;
+	spin_lock_irqsave(&subs->lock, flags);
+	for (i = 0; i < ctx->packets; i++) {
+		counts = ctx->packet_size[i];
+		/* set up descriptor */
+		urb->iso_frame_desc[i].offset = frames * stride;
+		urb->iso_frame_desc[i].length = counts * stride;
+		frames += counts;
+		urb->number_of_packets++;
+		subs->transfer_done += counts;
+		if (subs->transfer_done >= runtime->period_size) {
+			subs->transfer_done -= runtime->period_size;
+			period_elapsed = 1;
+			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+				if (subs->transfer_done > 0) {
+					/* FIXME: fill-max mode is not
+					 * supported yet */
+					frames -= subs->transfer_done;
+					counts -= subs->transfer_done;
+					urb->iso_frame_desc[i].length =
+						counts * stride;
+					subs->transfer_done = 0;
+				}
+				i++;
+				if (i < ctx->packets) {
+					/* add a transfer delimiter */
+					urb->iso_frame_desc[i].offset =
+						frames * stride;
+					urb->iso_frame_desc[i].length = 0;
+					urb->number_of_packets++;
+				}
+				break;
+			}
+		}
+		if (period_elapsed &&
+		    !snd_usb_endpoint_implict_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
+			break;
+	}
+	bytes = frames * stride;
+	if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+		/* err, the transferred area goes over buffer boundary. */
+		unsigned int bytes1 =
+			runtime->buffer_size * stride - subs->hwptr_done;
+		memcpy(urb->transfer_buffer,
+		       runtime->dma_area + subs->hwptr_done, bytes1);
+		memcpy(urb->transfer_buffer + bytes1,
+		       runtime->dma_area, bytes - bytes1);
+	} else {
+		memcpy(urb->transfer_buffer,
+		       runtime->dma_area + subs->hwptr_done, bytes);
+	}
+	subs->hwptr_done += bytes;
+	if (subs->hwptr_done >= runtime->buffer_size * stride)
+		subs->hwptr_done -= runtime->buffer_size * stride;
+	runtime->delay += frames;
+	spin_unlock_irqrestore(&subs->lock, flags);
+	urb->transfer_buffer_length = bytes;
+	if (period_elapsed)
+		snd_pcm_period_elapsed(subs->pcm_substream);
+}
+
+/*
+ * process after playback data complete
+ * - decrease the delay count again
+ */
+static void retire_playback_urb(struct snd_usb_substream *subs,
+			       struct urb *urb)
+{
+	unsigned long flags;
+	struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+	int stride = runtime->frame_bits >> 3;
+	int processed = urb->transfer_buffer_length / stride;
+
+	spin_lock_irqsave(&subs->lock, flags);
+	if (processed > runtime->delay)
+		runtime->delay = 0;
+	else
+		runtime->delay -= processed;
+	spin_unlock_irqrestore(&subs->lock, flags);
 }
 
 static int snd_usb_playback_open(struct snd_pcm_substream *substream)
@@ -872,6 +1095,56 @@ static int snd_usb_capture_close(struct snd_pcm_substream *substream)
 	return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE);
 }
 
+static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream,
+					      int cmd)
+{
+	struct snd_usb_substream *subs = substream->runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		subs->data_endpoint->prepare_data_urb = prepare_playback_urb;
+		subs->data_endpoint->retire_data_urb = retire_playback_urb;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+		stop_endpoints(subs, 0, 0, 0);
+		return 0;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->data_endpoint->prepare_data_urb = NULL;
+		subs->data_endpoint->retire_data_urb = NULL;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int err;
+	struct snd_usb_substream *subs = substream->runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = start_endpoints(subs);
+		if (err < 0)
+			return err;
+
+		subs->data_endpoint->retire_data_urb = retire_capture_urb;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+		stop_endpoints(subs, 0, 0, 0);
+		return 0;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->data_endpoint->retire_data_urb = NULL;
+		return 0;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		subs->data_endpoint->retire_data_urb = retire_capture_urb;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static struct snd_pcm_ops snd_usb_playback_ops = {
 	.open =		snd_usb_playback_open,
 	.close =	snd_usb_playback_close,
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 5ff8010..6b7d7a2 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -73,6 +73,31 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
 	}
 }
 
+/*
+ * initialize the substream instance.
+ */
+
+static void snd_usb_init_substream(struct snd_usb_stream *as,
+				   int stream,
+				   struct audioformat *fp)
+{
+	struct snd_usb_substream *subs = &as->substream[stream];
+
+	INIT_LIST_HEAD(&subs->fmt_list);
+	spin_lock_init(&subs->lock);
+
+	subs->stream = as;
+	subs->direction = stream;
+	subs->dev = as->chip->dev;
+	subs->txfr_quirk = as->chip->txfr_quirk;
+
+	snd_usb_set_pcm_ops(as->pcm, stream);
+
+	list_add_tail(&fp->list, &subs->fmt_list);
+	subs->formats |= fp->formats;
+	subs->num_formats++;
+	subs->fmt_type = fp->fmt_type;
+}
 
 /*
  * add this endpoint to the chip instance.
@@ -94,9 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
 		if (as->fmt_type != fp->fmt_type)
 			continue;
 		subs = &as->substream[stream];
-		if (!subs->endpoint)
+		if (!subs->data_endpoint)
 			continue;
-		if (subs->endpoint == fp->endpoint) {
+		if (subs->data_endpoint->ep_num == fp->endpoint) {
 			list_add_tail(&fp->list, &subs->fmt_list);
 			subs->num_formats++;
 			subs->formats |= fp->formats;
@@ -109,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
 		if (as->fmt_type != fp->fmt_type)
 			continue;
 		subs = &as->substream[stream];
-		if (subs->endpoint)
+		if (subs->data_endpoint)
 			continue;
 		err = snd_pcm_new_stream(as->pcm, stream, 1);
 		if (err < 0)
-- 
1.7.7.4

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

* [PATCH 4/6] ALSA: snd-usb: remove old streaming logic
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
                   ` (2 preceding siblings ...)
  2011-12-23 16:15 ` [PATCH 3/6] ALSA: snd-usb: switch over to new endpoint streaming logic Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-23 16:15 ` [PATCH 5/6] ALSA: snd-usb: add support for implicit feedback Daniel Mack
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/endpoint.c |  851 +-------------------------------------------------
 sound/usb/endpoint.h |   15 -
 2 files changed, 8 insertions(+), 858 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 93d6590..78d9eb6 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -53,727 +53,19 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate)
 }
 
 /*
- * unlink active urbs.
- */
-static int deactivate_urbs_old(struct snd_usb_substream *subs, int force, int can_sleep)
-{
-	struct snd_usb_audio *chip = subs->stream->chip;
-	unsigned int i;
-	int async;
-
-	subs->running = 0;
-
-	if (!force && subs->stream->chip->shutdown) /* to be sure... */
-		return -EBADFD;
-
-	async = !can_sleep && chip->async_unlink;
-
-	if (!async && in_interrupt())
-		return 0;
-
-	for (i = 0; i < subs->nurbs; i++) {
-		if (test_bit(i, &subs->active_mask)) {
-			if (!test_and_set_bit(i, &subs->unlink_mask)) {
-				struct urb *u = subs->dataurb[i].urb;
-				if (async)
-					usb_unlink_urb(u);
-				else
-					usb_kill_urb(u);
-			}
-		}
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			if (test_bit(i+16, &subs->active_mask)) {
-				if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
-					struct urb *u = subs->syncurb[i].urb;
-					if (async)
-						usb_unlink_urb(u);
-					else
-						usb_kill_urb(u);
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-
-/*
  * release a urb data
  */
 static void release_urb_ctx(struct snd_urb_ctx *u)
 {
-	if (u->urb) {
-		if (u->buffer_size)
-			usb_free_coherent(u->subs->dev, u->buffer_size,
-					u->urb->transfer_buffer,
-					u->urb->transfer_dma);
-		usb_free_urb(u->urb);
-		u->urb = NULL;
-	}
-}
-
-/*
- *  wait until all urbs are processed.
- */
-static int wait_clear_urbs_old(struct snd_usb_substream *subs)
-{
-	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
-	unsigned int i;
-	int alive;
-
-	do {
-		alive = 0;
-		for (i = 0; i < subs->nurbs; i++) {
-			if (test_bit(i, &subs->active_mask))
-				alive++;
-		}
-		if (subs->syncpipe) {
-			for (i = 0; i < SYNC_URBS; i++) {
-				if (test_bit(i + 16, &subs->active_mask))
-					alive++;
-			}
-		}
-		if (! alive)
-			break;
-		schedule_timeout_uninterruptible(1);
-	} while (time_before(jiffies, end_time));
-	if (alive)
-		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
-	return 0;
-}
-
-/*
- * release a substream
- */
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
-{
-	int i;
-
-	/* stop urbs (to be sure) */
-	deactivate_urbs_old(subs, force, 1);
-	wait_clear_urbs_old(subs);
-
-	for (i = 0; i < MAX_URBS; i++)
-		release_urb_ctx(&subs->dataurb[i]);
-	for (i = 0; i < SYNC_URBS; i++)
-		release_urb_ctx(&subs->syncurb[i]);
-	usb_free_coherent(subs->dev, SYNC_URBS * 4,
-			subs->syncbuf, subs->sync_dma);
-	subs->syncbuf = NULL;
-	subs->nurbs = 0;
-}
-
-/*
- * complete callback from data urb
- */
-static void snd_complete_urb_old(struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-	struct snd_usb_substream *subs = ctx->subs;
-	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-	int err = 0;
-
-	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
-	    !subs->running || /* can be stopped during retire callback */
-	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
-	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		clear_bit(ctx->index, &subs->active_mask);
-		if (err < 0) {
-			snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		}
-	}
-}
-
-
-/*
- * complete callback from sync urb
- */
-static void snd_complete_sync_urb(struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-	struct snd_usb_substream *subs = ctx->subs;
-	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-	int err = 0;
-
-	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
-	    !subs->running || /* can be stopped during retire callback */
-	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
-	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		clear_bit(ctx->index + 16, &subs->active_mask);
-		if (err < 0) {
-			snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		}
-	}
-}
-
-
-/*
- * initialize a substream for plaback/capture
- */
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-				unsigned int period_bytes,
-				unsigned int rate,
-				unsigned int frame_bits)
-{
-	unsigned int maxsize, i;
-	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int urb_packs, total_packs, packs_per_ms;
-	struct snd_usb_audio *chip = subs->stream->chip;
-
-	/* calculate the frequency in 16.16 format */
-	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
-		subs->freqn = get_usb_full_speed_rate(rate);
-	else
-		subs->freqn = get_usb_high_speed_rate(rate);
-	subs->freqm = subs->freqn;
-	subs->freqshift = INT_MIN;
-	/* calculate max. frequency */
-	if (subs->maxpacksize) {
-		/* whatever fits into a max. size packet */
-		maxsize = subs->maxpacksize;
-		subs->freqmax = (maxsize / (frame_bits >> 3))
-				<< (16 - subs->datainterval);
-	} else {
-		/* no max. packet size: just take 25% higher than nominal */
-		subs->freqmax = subs->freqn + (subs->freqn >> 2);
-		maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
-				>> (16 - subs->datainterval);
-	}
-	subs->phase = 0;
-
-	if (subs->fill_max)
-		subs->curpacksize = subs->maxpacksize;
-	else
-		subs->curpacksize = maxsize;
-
-	if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
-		packs_per_ms = 8 >> subs->datainterval;
-	else
-		packs_per_ms = 1;
-
-	if (is_playback) {
-		urb_packs = max(chip->nrpacks, 1);
-		urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
-	} else
-		urb_packs = 1;
-	urb_packs *= packs_per_ms;
-	if (subs->syncpipe)
-		urb_packs = min(urb_packs, 1U << subs->syncinterval);
-
-	/* decide how many packets to be used */
-	if (is_playback) {
-		unsigned int minsize, maxpacks;
-		/* determine how small a packet can be */
-		minsize = (subs->freqn >> (16 - subs->datainterval))
-			  * (frame_bits >> 3);
-		/* with sync from device, assume it can be 12% lower */
-		if (subs->syncpipe)
-			minsize -= minsize >> 3;
-		minsize = max(minsize, 1u);
-		total_packs = (period_bytes + minsize - 1) / minsize;
-		/* we need at least two URBs for queueing */
-		if (total_packs < 2) {
-			total_packs = 2;
-		} else {
-			/* and we don't want too long a queue either */
-			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
-			total_packs = min(total_packs, maxpacks);
-		}
-	} else {
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-			urb_packs >>= 1;
-		total_packs = MAX_URBS * urb_packs;
-	}
-	subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
-	if (subs->nurbs > MAX_URBS) {
-		/* too much... */
-		subs->nurbs = MAX_URBS;
-		total_packs = MAX_URBS * urb_packs;
-	} else if (subs->nurbs < 2) {
-		/* too little - we need at least two packets
-		 * to ensure contiguous playback/capture
-		 */
-		subs->nurbs = 2;
-	}
-
-	/* allocate and initialize data urbs */
-	for (i = 0; i < subs->nurbs; i++) {
-		struct snd_urb_ctx *u = &subs->dataurb[i];
-		u->index = i;
-		u->subs = subs;
-		u->packets = (i + 1) * total_packs / subs->nurbs
-			- i * total_packs / subs->nurbs;
-		u->buffer_size = maxsize * u->packets;
-		if (subs->fmt_type == UAC_FORMAT_TYPE_II)
-			u->packets++; /* for transfer delimiter */
-		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
-		if (!u->urb)
-			goto out_of_memory;
-		u->urb->transfer_buffer =
-			usb_alloc_coherent(subs->dev, u->buffer_size,
-					   GFP_KERNEL, &u->urb->transfer_dma);
-		if (!u->urb->transfer_buffer)
-			goto out_of_memory;
-		u->urb->pipe = subs->datapipe;
-		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		u->urb->interval = 1 << subs->datainterval;
-		u->urb->context = u;
-		u->urb->complete = snd_complete_urb_old;
-	}
-
-	if (subs->syncpipe) {
-		/* allocate and initialize sync urbs */
-		subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
-						 GFP_KERNEL, &subs->sync_dma);
-		if (!subs->syncbuf)
-			goto out_of_memory;
-		for (i = 0; i < SYNC_URBS; i++) {
-			struct snd_urb_ctx *u = &subs->syncurb[i];
-			u->index = i;
-			u->subs = subs;
-			u->packets = 1;
-			u->urb = usb_alloc_urb(1, GFP_KERNEL);
-			if (!u->urb)
-				goto out_of_memory;
-			u->urb->transfer_buffer = subs->syncbuf + i * 4;
-			u->urb->transfer_dma = subs->sync_dma + i * 4;
-			u->urb->transfer_buffer_length = 4;
-			u->urb->pipe = subs->syncpipe;
-			u->urb->transfer_flags = URB_ISO_ASAP |
-						 URB_NO_TRANSFER_DMA_MAP;
-			u->urb->number_of_packets = 1;
-			u->urb->interval = 1 << subs->syncinterval;
-			u->urb->context = u;
-			u->urb->complete = snd_complete_sync_urb;
-		}
-	}
-	return 0;
-
-out_of_memory:
-	snd_usb_release_substream_urbs(subs, 0);
-	return -ENOMEM;
-}
-
-/*
- * prepare urb for full speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 10.14 frequency is passed through the pipe.
- */
-static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
-				    struct snd_pcm_runtime *runtime,
-				    struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = 3;
-	urb->iso_frame_desc[0].offset = 0;
-	cp[0] = subs->freqn >> 2;
-	cp[1] = subs->freqn >> 10;
-	cp[2] = subs->freqn >> 18;
-	return 0;
-}
-
-/*
- * prepare urb for high speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 12.13 frequency is passed as 16.16 through the pipe.
- */
-static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
-				       struct snd_pcm_runtime *runtime,
-				       struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = 4;
-	urb->iso_frame_desc[0].offset = 0;
-	cp[0] = subs->freqn;
-	cp[1] = subs->freqn >> 8;
-	cp[2] = subs->freqn >> 16;
-	cp[3] = subs->freqn >> 24;
-	return 0;
-}
-
-/*
- * process after capture sync complete
- * - nothing to do
- */
-static int retire_capture_sync_urb(struct snd_usb_substream *subs,
-				   struct snd_pcm_runtime *runtime,
-				   struct urb *urb)
-{
-	return 0;
-}
-
-/*
- * prepare urb for capture data pipe
- *
- * fill the offset and length of each descriptor.
- *
- * we use a temporary buffer to write the captured data.
- * since the length of written data is determined by host, we cannot
- * write onto the pcm buffer directly...  the data is thus copied
- * later at complete callback to the global buffer.
- */
-static int prepare_capture_urb(struct snd_usb_substream *subs,
-			       struct snd_pcm_runtime *runtime,
-			       struct urb *urb)
-{
-	int i, offs;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	offs = 0;
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = 0; i < ctx->packets; i++) {
-		urb->iso_frame_desc[i].offset = offs;
-		urb->iso_frame_desc[i].length = subs->curpacksize;
-		offs += subs->curpacksize;
-	}
-	urb->transfer_buffer_length = offs;
-	urb->number_of_packets = ctx->packets;
-	return 0;
-}
-
-/*
- * process after capture complete
- *
- * copy the data from each desctiptor to the pcm buffer, and
- * update the current position.
- */
-static int retire_capture_urb(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime,
-			      struct urb *urb)
-{
-	unsigned long flags;
-	unsigned char *cp;
-	int i;
-	unsigned int stride, frames, bytes, oldptr;
-	int period_elapsed = 0;
-
-	stride = runtime->frame_bits >> 3;
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-		if (urb->iso_frame_desc[i].status) {
-			snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
-			// continue;
-		}
-		bytes = urb->iso_frame_desc[i].actual_length;
-		frames = bytes / stride;
-		if (!subs->txfr_quirk)
-			bytes = frames * stride;
-		if (bytes % (runtime->sample_bits >> 3) != 0) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-			int oldbytes = bytes;
-#endif
-			bytes = frames * stride;
-			snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
-							oldbytes, bytes);
-		}
-		/* update the current pointer */
-		spin_lock_irqsave(&subs->lock, flags);
-		oldptr = subs->hwptr_done;
-		subs->hwptr_done += bytes;
-		if (subs->hwptr_done >= runtime->buffer_size * stride)
-			subs->hwptr_done -= runtime->buffer_size * stride;
-		frames = (bytes + (oldptr % stride)) / stride;
-		subs->transfer_done += frames;
-		if (subs->transfer_done >= runtime->period_size) {
-			subs->transfer_done -= runtime->period_size;
-			period_elapsed = 1;
-		}
-		spin_unlock_irqrestore(&subs->lock, flags);
-		/* copy a data chunk */
-		if (oldptr + bytes > runtime->buffer_size * stride) {
-			unsigned int bytes1 =
-					runtime->buffer_size * stride - oldptr;
-			memcpy(runtime->dma_area + oldptr, cp, bytes1);
-			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
-		} else {
-			memcpy(runtime->dma_area + oldptr, cp, bytes);
-		}
-	}
-	if (period_elapsed)
-		snd_pcm_period_elapsed(subs->pcm_substream);
-	return 0;
-}
-
-/*
- * Process after capture complete when paused.  Nothing to do.
- */
-static int retire_paused_capture_urb(struct snd_usb_substream *subs,
-				     struct snd_pcm_runtime *runtime,
-				     struct urb *urb)
-{
-	return 0;
-}
-
-
-/*
- * prepare urb for playback sync pipe
- *
- * set up the offset and length to receive the current frequency.
- */
-static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
-				     struct snd_pcm_runtime *runtime,
-				     struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
-	urb->iso_frame_desc[0].offset = 0;
-	return 0;
-}
-
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format.  Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
- */
-static int retire_playback_sync_urb(struct snd_usb_substream *subs,
-				    struct snd_pcm_runtime *runtime,
-				    struct urb *urb)
-{
-	unsigned int f;
-	int shift;
-	unsigned long flags;
-
-	if (urb->iso_frame_desc[0].status != 0 ||
-	    urb->iso_frame_desc[0].actual_length < 3)
-		return 0;
-
-	f = le32_to_cpup(urb->transfer_buffer);
-	if (urb->iso_frame_desc[0].actual_length == 3)
-		f &= 0x00ffffff;
-	else
-		f &= 0x0fffffff;
-	if (f == 0)
-		return 0;
-
-	if (unlikely(subs->freqshift == INT_MIN)) {
-		/*
-		 * The first time we see a feedback value, determine its format
-		 * by shifting it left or right until it matches the nominal
-		 * frequency value.  This assumes that the feedback does not
-		 * differ from the nominal value more than +50% or -25%.
-		 */
-		shift = 0;
-		while (f < subs->freqn - subs->freqn / 4) {
-			f <<= 1;
-			shift++;
-		}
-		while (f > subs->freqn + subs->freqn / 2) {
-			f >>= 1;
-			shift--;
-		}
-		subs->freqshift = shift;
-	}
-	else if (subs->freqshift >= 0)
-		f <<= subs->freqshift;
-	else
-		f >>= -subs->freqshift;
-
-	if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
-		/*
-		 * If the frequency looks valid, set it.
-		 * This value is referred to in prepare_playback_urb().
-		 */
-		spin_lock_irqsave(&subs->lock, flags);
-		subs->freqm = f;
-		spin_unlock_irqrestore(&subs->lock, flags);
-	} else {
-		/*
-		 * Out of range; maybe the shift value is wrong.
-		 * Reset it so that we autodetect again the next time.
-		 */
-		subs->freqshift = INT_MIN;
-	}
-
-	return 0;
-}
-
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
-	if (subs->fill_max)
-		return subs->maxframesize;
-	else {
-		subs->phase = (subs->phase & 0xffff)
-			+ (subs->freqm << subs->datainterval);
-		return min(subs->phase >> 16, subs->maxframesize);
-	}
-}
-
-/*
- * Prepare urb for streaming before playback starts or when paused.
- *
- * We don't have any data, so we send silence.
- */
-static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
-				       struct snd_pcm_runtime *runtime,
-				       struct urb *urb)
-{
-	unsigned int i, offs, counts;
-	struct snd_urb_ctx *ctx = urb->context;
-	int stride = runtime->frame_bits >> 3;
-
-	offs = 0;
-	urb->dev = ctx->subs->dev;
-	for (i = 0; i < ctx->packets; ++i) {
-		counts = snd_usb_audio_next_packet_size(subs);
-		urb->iso_frame_desc[i].offset = offs * stride;
-		urb->iso_frame_desc[i].length = counts * stride;
-		offs += counts;
-	}
-	urb->number_of_packets = ctx->packets;
-	urb->transfer_buffer_length = offs * stride;
-	memset(urb->transfer_buffer,
-	       runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
-	       offs * stride);
-	return 0;
-}
-
-/*
- * prepare urb for playback data pipe
- *
- * Since a URB can handle only a single linear buffer, we must use double
- * buffering when the data to be transferred overflows the buffer boundary.
- * To avoid inconsistencies when updating hwptr_done, we use double buffering
- * for all URBs.
- */
-static int prepare_playback_urb(struct snd_usb_substream *subs,
-				struct snd_pcm_runtime *runtime,
-				struct urb *urb)
-{
-	int i, stride;
-	unsigned int counts, frames, bytes;
-	unsigned long flags;
-	int period_elapsed = 0;
-	struct snd_urb_ctx *ctx = urb->context;
+	if (!u->urb)
+		return;
 
-	stride = runtime->frame_bits >> 3;
-
-	frames = 0;
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->number_of_packets = 0;
-	spin_lock_irqsave(&subs->lock, flags);
-	for (i = 0; i < ctx->packets; i++) {
-		counts = snd_usb_audio_next_packet_size(subs);
-		/* set up descriptor */
-		urb->iso_frame_desc[i].offset = frames * stride;
-		urb->iso_frame_desc[i].length = counts * stride;
-		frames += counts;
-		urb->number_of_packets++;
-		subs->transfer_done += counts;
-		if (subs->transfer_done >= runtime->period_size) {
-			subs->transfer_done -= runtime->period_size;
-			period_elapsed = 1;
-			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
-				if (subs->transfer_done > 0) {
-					/* FIXME: fill-max mode is not
-					 * supported yet */
-					frames -= subs->transfer_done;
-					counts -= subs->transfer_done;
-					urb->iso_frame_desc[i].length =
-						counts * stride;
-					subs->transfer_done = 0;
-				}
-				i++;
-				if (i < ctx->packets) {
-					/* add a transfer delimiter */
-					urb->iso_frame_desc[i].offset =
-						frames * stride;
-					urb->iso_frame_desc[i].length = 0;
-					urb->number_of_packets++;
-				}
-				break;
-			}
-		}
-		if (period_elapsed) /* finish at the period boundary */
-			break;
-	}
-	bytes = frames * stride;
-	if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
-		/* err, the transferred area goes over buffer boundary. */
-		unsigned int bytes1 =
-			runtime->buffer_size * stride - subs->hwptr_done;
-		memcpy(urb->transfer_buffer,
-		       runtime->dma_area + subs->hwptr_done, bytes1);
-		memcpy(urb->transfer_buffer + bytes1,
-		       runtime->dma_area, bytes - bytes1);
-	} else {
-		memcpy(urb->transfer_buffer,
-		       runtime->dma_area + subs->hwptr_done, bytes);
-	}
-	subs->hwptr_done += bytes;
-	if (subs->hwptr_done >= runtime->buffer_size * stride)
-		subs->hwptr_done -= runtime->buffer_size * stride;
-
-	/* update delay with exact number of samples queued */
-	runtime->delay = subs->last_delay;
-	runtime->delay += frames;
-	subs->last_delay = runtime->delay;
-
-	/* realign last_frame_number */
-	subs->last_frame_number = usb_get_current_frame_number(subs->dev);
-	subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
-
-	spin_unlock_irqrestore(&subs->lock, flags);
-	urb->transfer_buffer_length = bytes;
-	if (period_elapsed)
-		snd_pcm_period_elapsed(subs->pcm_substream);
-	return 0;
-}
-
-/*
- * process after playback data complete
- * - decrease the delay count again
- */
-static int retire_playback_urb(struct snd_usb_substream *subs,
-			       struct snd_pcm_runtime *runtime,
-			       struct urb *urb)
-{
-	unsigned long flags;
-	int stride = runtime->frame_bits >> 3;
-	int processed = urb->transfer_buffer_length / stride;
-	int est_delay;
-
-	spin_lock_irqsave(&subs->lock, flags);
-
-	est_delay = snd_usb_pcm_delay(subs, runtime->rate);
-	/* update delay with exact number of samples played */
-	if (processed > subs->last_delay)
-		subs->last_delay = 0;
-	else
-		subs->last_delay -= processed;
-	runtime->delay = subs->last_delay;
-
-	/*
-	 * Report when delay estimate is off by more than 2ms.
-	 * The error should be lower than 2ms since the estimate relies
-	 * on two reads of a counter updated every ms.
-	 */
-	if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
-		snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
-			est_delay, subs->last_delay);
-
-	spin_unlock_irqrestore(&subs->lock, flags);
-	return 0;
+	if (u->buffer_size)
+		usb_free_coherent(u->ep->chip->dev, u->buffer_size,
+				  u->urb->transfer_buffer,
+				  u->urb->transfer_dma);
+	usb_free_urb(u->urb);
+	u->urb = NULL;
 }
 
 static const char *usb_error_string(int err)
@@ -801,133 +93,6 @@ static const char *usb_error_string(int err)
 	}
 }
 
-/*
- * set up and start data/sync urbs
- */
-static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
-{
-	unsigned int i;
-	int err;
-
-	if (subs->stream->chip->shutdown)
-		return -EBADFD;
-
-	for (i = 0; i < subs->nurbs; i++) {
-		if (snd_BUG_ON(!subs->dataurb[i].urb))
-			return -EINVAL;
-		if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
-			snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
-			goto __error;
-		}
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			if (snd_BUG_ON(!subs->syncurb[i].urb))
-				return -EINVAL;
-			if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
-				snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
-				goto __error;
-			}
-		}
-	}
-
-	subs->active_mask = 0;
-	subs->unlink_mask = 0;
-	subs->running = 1;
-	for (i = 0; i < subs->nurbs; i++) {
-		err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
-		if (err < 0) {
-			snd_printk(KERN_ERR "cannot submit datapipe "
-				   "for urb %d, error %d: %s\n",
-				   i, err, usb_error_string(err));
-			goto __error;
-		}
-		set_bit(i, &subs->active_mask);
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
-			if (err < 0) {
-				snd_printk(KERN_ERR "cannot submit syncpipe "
-					   "for urb %d, error %d: %s\n",
-					   i, err, usb_error_string(err));
-				goto __error;
-			}
-			set_bit(i + 16, &subs->active_mask);
-		}
-	}
-	return 0;
-
- __error:
-	// snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
-	deactivate_urbs_old(subs, 0, 0);
-	return -EPIPE;
-}
-
-
-/*
- */
-static struct snd_urb_ops audio_urb_ops[2] = {
-	{
-		.prepare =	prepare_nodata_playback_urb,
-		.retire =	retire_playback_urb,
-		.prepare_sync =	prepare_playback_sync_urb,
-		.retire_sync =	retire_playback_sync_urb,
-	},
-	{
-		.prepare =	prepare_capture_urb,
-		.retire =	retire_capture_urb,
-		.prepare_sync =	prepare_capture_sync_urb,
-		.retire_sync =	retire_capture_sync_urb,
-	},
-};
-
-/*
- * initialize the substream instance.
- */
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
-			    int stream, struct audioformat *fp)
-{
-	struct snd_usb_substream *subs = &as->substream[stream];
-
-	INIT_LIST_HEAD(&subs->fmt_list);
-	spin_lock_init(&subs->lock);
-
-	subs->stream = as;
-	subs->direction = stream;
-	subs->dev = as->chip->dev;
-	subs->txfr_quirk = as->chip->txfr_quirk;
-	subs->ops = audio_urb_ops[stream];
-	if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
-		subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
-
-	snd_usb_set_pcm_ops(as->pcm, stream);
-
-	list_add_tail(&fp->list, &subs->fmt_list);
-	subs->formats |= fp->formats;
-	subs->endpoint = fp->endpoint;
-	subs->num_formats++;
-	subs->fmt_type = fp->fmt_type;
-}
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime)
-{
-	/* clear urbs (to be sure) */
-	deactivate_urbs_old(subs, 0, 1);
-	wait_clear_urbs_old(subs);
-
-	/* for playback, submit the URBs now; otherwise, the first hwptr_done
-	 * updates for all URBs would happen at the same time when starting */
-	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		subs->ops.prepare = prepare_nodata_playback_urb;
-		return start_urbs(subs, runtime);
-	}
-
-	return 0;
-}
-
 int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
 {
 	return  ep->sync_master &&
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index e540768..ee2723f 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -1,21 +1,6 @@
 #ifndef __USBAUDIO_ENDPOINT_H
 #define __USBAUDIO_ENDPOINT_H
 
-void snd_usb_init_substream(struct snd_usb_stream *as,
-			    int stream,
-			    struct audioformat *fp);
-
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-				unsigned int period_bytes,
-				unsigned int rate,
-				unsigned int frame_bits);
-
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime);
-
-
 #define SND_USB_ENDPOINT_TYPE_DATA     0
 #define SND_USB_ENDPOINT_TYPE_SYNC     1
 
-- 
1.7.7.4

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

* [PATCH 5/6] ALSA: snd-usb: add support for implicit feedback
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
                   ` (3 preceding siblings ...)
  2011-12-23 16:15 ` [PATCH 4/6] ALSA: snd-usb: remove old " Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-23 16:15 ` [PATCH 6/6] ALSA: snd-usb: add some documentation Daniel Mack
  2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

Implicit feedback is a streaming mode that does not rely on dedicated
sync endpoints but uses the information provided by record streams to
clock output streams. Now that the streaming logic is decoupled from the
PCM streams, this is easy to implement.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/pcm.c |   37 ++++++++++++++++++++++++++-----------
 1 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 271579c..69cc912 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -300,7 +300,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	struct usb_interface *iface;
 	unsigned int ep, attr;
 	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	int err;
+	int err, implicit_fb = 0;
 
 	iface = usb_ifnum_to_if(dev, fmt->iface);
 	if (WARN_ON(!iface))
@@ -325,25 +325,34 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 	 * 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)) &&
-	    altsd->bNumEndpoints >= 2) {
-		switch (subs->stream->chip->usb_id) {
-		case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
-		case USB_ID(0x0763, 0x2081):
+
+	switch (subs->stream->chip->usb_id) {
+	case USB_ID(0x0763, 0x2080): /* M-Audio FastTrack Ultra */
+	case USB_ID(0x0763, 0x2081):
+		if (is_playback) {
+			implicit_fb = 1;
 			ep = 0x81;
 			iface = usb_ifnum_to_if(dev, 2);
+
+			if (!iface || iface->num_altsetting == 0)
+				return -EINVAL;
+
 			alts = &iface->altsetting[1];
 			goto add_sync_ep;
 		}
+	}
 
+	if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) ||
+	     (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) &&
+	    altsd->bNumEndpoints >= 2) {
 		/* check sync-pipe endpoint */
 		/* ... 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) != 0x01 ||
 		    (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
-		     get_endpoint(alts, 1)->bSynchAddress != 0)) {
+		     get_endpoint(alts, 1)->bSynchAddress != 0 &&
+		     !implicit_fb)) {
 			snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
 				   dev->devnum, fmt->iface, fmt->altsetting);
 			return -EINVAL;
@@ -351,16 +360,22 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
 		ep = get_endpoint(alts, 1)->bEndpointAddress;
 		if (get_endpoint(alts, 0)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
 		    (( is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress | USB_DIR_IN)) ||
-		     (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)))) {
+		     (!is_playback && ep != (unsigned int)(get_endpoint(alts, 0)->bSynchAddress & ~USB_DIR_IN)) ||
+		     ( is_playback && !implicit_fb))) {
 			snd_printk(KERN_ERR "%d:%d:%d : invalid synch pipe\n",
 				   dev->devnum, fmt->iface, fmt->altsetting);
 			return -EINVAL;
 		}
+
+		implicit_fb = (get_endpoint(alts, 1)->bmAttributes & USB_ENDPOINT_USAGE_MASK)
+				== USB_ENDPOINT_USAGE_IMPLICIT_FB;
+
 add_sync_ep:
 		subs->sync_endpoint = snd_usb_add_endpoint(subs->stream->chip,
 							   alts, ep, !subs->direction,
-							   SND_USB_ENDPOINT_TYPE_SYNC);
-
+							   implicit_fb ?
+								SND_USB_ENDPOINT_TYPE_DATA :
+								SND_USB_ENDPOINT_TYPE_SYNC);
 		if (!subs->sync_endpoint)
 			return -EINVAL;
 
-- 
1.7.7.4

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

* [PATCH 6/6] ALSA: snd-usb: add some documentation
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
                   ` (4 preceding siblings ...)
  2011-12-23 16:15 ` [PATCH 5/6] ALSA: snd-usb: add support for implicit feedback Daniel Mack
@ 2011-12-23 16:15 ` Daniel Mack
  2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
  6 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-23 16:15 UTC (permalink / raw)
  To: alsa-devel; +Cc: gdiffey, tiwai, clemens, linuxaudio, Daniel Mack, blablack

Document the new streaming code and some of the functions so that
contributers can catch up easier.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/endpoint.c |  182 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 171 insertions(+), 11 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 78d9eb6..9edeace 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -35,6 +35,32 @@
 #define EP_FLAG_RUNNING		1
 
 /*
+ * snd_usb_endpoint is a model that abstracts everything related to an
+ * USB endpoint and its streaming.
+ *
+ * There are functions to activate and deactivate the streaming URBs and
+ * optinal callbacks to let the pcm logic handle the actual content of the
+ * packets for playback and record. Thus, the bus streaming and the audio
+ * handlers are fully decoupled.
+ *
+ * There are two different types of endpoints in for audio applications.
+ *
+ * SND_USB_ENDPOINT_TYPE_DATA handles full audio data payload for both
+ * inbound and outbound traffic.
+ *
+ * SND_USB_ENDPOINT_TYPE_SYNC are for inbound traffic only and expect the
+ * payload to carry Q16.16 formatted sync information (3 or 4 bytes).
+ *
+ * Each endpoint has to be configured (by calling
+ * snd_usb_endpoint_set_params()) before it can be used.
+ *
+ * The model incorporates a reference counting, so that multiple users
+ * can call snd_usb_endpoint_start() and snd_usb_endpoint_stop(), and
+ * only the first user will effectively start the URBs, and only the last
+ * one will tear them down again.
+ */
+
+/*
  * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
  * this will overflow at approx 524 kHz
  */
@@ -93,6 +119,14 @@ static const char *usb_error_string(int err)
 	}
 }
 
+/**
+ * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
+ *
+ * @ep: The endpoint
+ *
+ * Determine whether an endpoint is driven by an implicit feedback
+ * data endpoint source.
+ */
 int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
 {
 	return  ep->sync_master &&
@@ -101,7 +135,13 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
 		usb_pipeout(ep->pipe);
 }
 
-/* determine the number of frames in the next packet */
+/*
+ * For streaming based on information derived from sync endpoints,
+ * prepare_outbound_urb_sizes() will call next_packet_size() to
+ * determine the number of samples to be sent in the next packet.
+ *
+ * For implicit feedback, next_packet_size() is unused.
+ */
 static int next_packet_size(struct snd_usb_endpoint *ep)
 {
 	unsigned long flags;
@@ -239,6 +279,19 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
 	}
 }
 
+/*
+ * Send output urbs that have been prepared previously. Urbs are dequeued
+ * from ep->ready_playback_urbs and in case there there aren't any available
+ * or there are no packets that have been prepared, this function does
+ * nothing.
+ *
+ * The reason why the functionality of sending and preparing urbs is separated
+ * is that host controllers don't guarantee an ordering in returing inbound
+ * and outbound packets to their submitters.
+ *
+ * This function is only used for implicit feedback endpoints. For endpoints
+ * driven by sync endpoints, urbs are submitted from their completion handler.
+ */
 static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 {
 	unsigned long flags;
@@ -268,6 +321,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		for (i = 0; i < packet->packets; i++)
 			ctx->packet_size[i] = packet->packet_size[i];
 
+		/* call the data handler to fill in playback data */
 		prepare_outbound_urb(ep, ctx);
 
 		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
@@ -335,6 +389,22 @@ exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);
 }
 
+/**
+ * snd_usb_add_endpoint: Add an endpoint to an 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.
+ *
+ * New endpoints will be added to chip->ep_list and must be freed by
+ * calling snd_usb_endpoint_free().
+ */
 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)
@@ -507,6 +577,9 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 	ep->nurbs = 0;
 }
 
+/*
+ * configure a data endpoint
+ */
 static int data_ep_set_params(struct snd_usb_endpoint *ep,
 			      struct snd_pcm_hw_params *hw_params,
 			      struct audioformat *fmt,
@@ -629,6 +702,9 @@ out_of_memory:
 	return -ENOMEM;
 }
 
+/*
+ * configure a sync endpoint
+ */
 static int sync_ep_set_params(struct snd_usb_endpoint *ep,
 			      struct snd_pcm_hw_params *hw_params,
 			      struct audioformat *fmt)
@@ -669,6 +745,15 @@ out_of_memory:
 	return -ENOMEM;
 }
 
+/**
+ * snd_usb_endpoint_set_params: configure an snd_endpoint
+ *
+ * @ep: the endpoint to configure
+ *
+ * Determine the number of 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,
 				struct snd_pcm_hw_params *hw_params,
 				struct audioformat *fmt,
@@ -717,6 +802,19 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 	return err;
 }
 
+/**
+ * snd_usb_endpoint_start: start an snd_usb_endpoint
+ *
+ * @ep: the endpoint to start
+ *
+ * A call to this function will increment the use count of the endpoint.
+ * In case this not already running, the URBs for this endpoint will be
+ * submitted. Otherwise, this function does nothing.
+ *
+ * Must be balanced to calls of snd_usb_endpoint_stop().
+ *
+ * Returns an error if the URB submission failed, 0 in all other cases.
+ */
 int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 {
 	int err;
@@ -788,6 +886,17 @@ __error:
 	return -EPIPE;
 }
 
+/**
+ * snd_usb_endpoint_stop: stop an snd_usb_endpoint
+ *
+ * @ep: the endpoint to stop (may be NULL)
+ *
+ * A call to this function will decrement the use count of the endpoint.
+ * In case the last user has requested the endpoint stop, the URBs will
+ * actually deactivated.
+ *
+ * Must be balanced to calls of snd_usb_endpoint_start().
+ */
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 			   int force, int can_sleep, int wait)
 {
@@ -812,6 +921,19 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 	}
 }
 
+/**
+ * snd_usb_endpoint_activate: activate an snd_usb_endpoint
+ *
+ * @ep: the endpoint to activate
+ *
+ * If the endpoint is not currently in use, this functions will select the
+ * correct alternate interface setting for the interface of this endpoint.
+ *
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
+ */
 int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
 {
 	if (ep->use_count != 0)
@@ -835,6 +957,19 @@ int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
 	return -EBUSY;
 }
 
+/**
+ * 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 select the
+ * alternate interface setting 0 for the interface of this endpoint.
+ *
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
+ */
 int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 {
 	if (!ep)
@@ -860,6 +995,13 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 	return -EBUSY;
 }
 
+/** snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint
+ *
+ * @ep: the list header of the endpoint to free
+ *
+ * This function does not care for the endpoint's use count but will tear
+ * down all the streaming URBs immediately and free all resources.
+ */
 void snd_usb_endpoint_free(struct list_head *head)
 {
 	struct snd_usb_endpoint *ep;
@@ -869,15 +1011,15 @@ void snd_usb_endpoint_free(struct list_head *head)
 	kfree(ep);
 }
 
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format.  Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
+/**
+ * snd_usb_handle_sync_urb: parse an USB sync packet
+ *
+ * @ep: the endpoint to handle the packet
+ * @sender: the sending endpoint
+ * @urb: the received packet
+ *
+ * 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,
@@ -889,6 +1031,11 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 
 	snd_BUG_ON(ep == sender);
 
+	/*
+	 * In case the endpoint is operating in implicit feedback mode, prepare
+	 * and a new outbound URB that has the same layout as the received
+	 * packet and add it to the list of pending urbs.
+	 */
 	if (snd_usb_endpoint_implict_feedback_sink(ep) &&
 	    ep->use_count != 0) {
 
@@ -938,7 +1085,20 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 		return;
 	}
 
-	/* parse sync endpoint packet */
+	/*
+	 * process after playback sync complete
+	 *
+	 * Full speed devices report feedback values in 10.14 format as samples
+	 * per frame, high speed devices in 16.16 format as samples per
+	 * microframe.
+	 *
+	 * Because the Audio Class 1 spec was written before USB 2.0, many high
+	 * speed devices use a wrong interpretation, some others use an
+	 * entirely different format.
+	 *
+	 * Therefore, we cannot predict what format any particular device uses
+	 * and must detect it automatically.
+	 */
 
 	if (urb->iso_frame_desc[0].status != 0 ||
 	    urb->iso_frame_desc[0].actual_length < 3)
-- 
1.7.7.4

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
                   ` (5 preceding siblings ...)
  2011-12-23 16:15 ` [PATCH 6/6] ALSA: snd-usb: add some documentation Daniel Mack
@ 2011-12-30 13:56 ` Daniel Mack
  2011-12-30 15:22   ` Felix Homann
                     ` (3 more replies)
  6 siblings, 4 replies; 28+ messages in thread
From: Daniel Mack @ 2011-12-30 13:56 UTC (permalink / raw)
  To: Daniel Mack; +Cc: alsa-devel, tiwai, clemens, gdiffey, linuxaudio, blablack

On 12/23/2011 05:15 PM, Daniel Mack wrote:
> Fortunately, the effects reported by Aurélien were easy to fix, and
> indeed just regressions from previous version of the patch set. Those
> are now out of the way, so here's version 6.
> 
> One thing that has also been added here is a sixth patch that adds
> some documentation to endpoint.c to explain the concept of the new
> implementation.
> 
> Thanks, and please have more test results coming.

Any chance that more people who've been waiting for support of the FTU
can use the lazy time between the years and quickly test this set?

As it affects all USB devices, results from all other snd-usb users are
as important and welcome :)


Thanks,
Daniel


_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
@ 2011-12-30 15:22   ` Felix Homann
       [not found]   ` <CAFz=ag6XNJSXvYQnAEbx=M+zXVH7sEw=_CJQKx63MmdQBWFuwA@mail.gmail.com>
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 28+ messages in thread
From: Felix Homann @ 2011-12-30 15:22 UTC (permalink / raw)
  To: alsa-devel

Hi Daniel,

2011/12/30 Daniel Mack <zonque@gmail.com>:
> Any chance that more people who've been waiting for support of the FTU
> can use the lazy time between the years and quickly test this set?

Could you please put a combined patch on your github place?
Should it be OK to use the alsa-driver/alsa-kernel update approach or
would I need to build a complete kernel image?

Thanks,

Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
       [not found]   ` <CAFz=ag6XNJSXvYQnAEbx=M+zXVH7sEw=_CJQKx63MmdQBWFuwA@mail.gmail.com>
@ 2011-12-30 15:24     ` Daniel Mack
       [not found]       ` <CACckToWP-C5H2xhvdJ5ykNf4BcuNCa4cMyFh2hppcwW0u33fQQ@mail.gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Mack @ 2011-12-30 15:24 UTC (permalink / raw)
  To: Felix Homann; +Cc: tiwai, blablack, alsa-devel, clemens, gdiffey

On 12/30/2011 04:16 PM, Felix Homann wrote:
> Hi Daniel,
> 
> 2011/12/30 Daniel Mack <zonque@gmail.com>:
>>
>> Any chance that more people who've been waiting for support of the FTU
>> can use the lazy time between the years and quickly test this set?
> 
> Could you please put a combined patch on your github place?

Done:

  https://gist.github.com/1168715

> Should it be OK to use the alsa-driver/alsa-kernel update approach or
> would I need to build a complete kernel image?

Take Linus' tree, merge Takashi's tree (from
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git master)
and then apply the gist.


Daniel

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
       [not found]         ` <4EFE6E52.4050503@gmail.com>
@ 2011-12-31  4:35           ` Grant Diffey
  2011-12-31  8:04             ` Grant Diffey
  0 siblings, 1 reply; 28+ messages in thread
From: Grant Diffey @ 2011-12-31  4:35 UTC (permalink / raw)
  To: Daniel Mack, alsa-devel

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

> Yes, any kind of USB audio device is good.
>
> Thanks for heling test! :)
>
>
>
So sadly not all is well in my world the logitech is only registering as a
mono device for some reason.

nevyn@cetacea:~$ speaker-test -c 2 -D hw:Headset

speaker-test 1.0.24.2

Playback device is hw:Headset
Stream parameters are 48000Hz, S16_LE, 2 channels
Using 16 octaves of pink noise
Channels count (2) not available for playbacks: Invalid argument
Setting of hwparams failed: Invalid argument


it's clearly stereo. lsusb -vv attached for reference

h

[-- Attachment #2: Logitech-Headset.lsusb --]
[-- Type: application/octet-stream, Size: 12224 bytes --]


Bus 005 Device 005: ID 046d:0a01 Logitech, Inc. USB Headset
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0         8
  idVendor           0x046d Logitech, Inc.
  idProduct          0x0a01 USB Headset
  bcdDevice           10.13
  iManufacturer           1 Logitech
  iProduct                2 Logitech USB Headset
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          318
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      1 Control Device
      bInterfaceProtocol      0 
      iInterface              0 
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      1 (HEADER)
        bcdADC               1.00
        wTotalLength          117
        bInCollection           2
        baInterfaceNr( 0)       1
        baInterfaceNr( 1)       2
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            13
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0001
          Left Front (L)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 6
        bSourceID              13
        bControlSize            1
        bmaControls( 0)      0x03
          Mute Control
          Volume Control
        bmaControls( 1)      0x00
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            12
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                13
        bDescriptorType        36
        bDescriptorSubtype      4 (MIXER_UNIT)
        bUnitID                 9
        bNrInPins               2
        baSourceID( 0)         12
        baSourceID( 1)          6
        bNrChannels             2
        wChannelConfig     0x0003
          Left Front (L)
          Right Front (R)
        iChannelNames           0 
        bmControls         0x00
        iMixer                  0 
      AudioControl Interface Descriptor:
        bLength                10
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 1
        bSourceID               9
        bControlSize            1
        bmaControls( 0)      0x01
          Mute Control
        bmaControls( 1)      0x02
          Volume Control
        bmaControls( 2)      0x02
          Volume Control
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            14
        wTerminalType      0x0301 Speaker
        bAssocTerminal          0
        bSourceID               1
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      2 (INPUT_TERMINAL)
        bTerminalID            11
        wTerminalType      0x0201 Microphone
        bAssocTerminal          0
        bNrChannels             1
        wChannelConfig     0x0001
          Left Front (L)
        iChannelNames           0 
        iTerminal               0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      6 (FEATURE_UNIT)
        bUnitID                 2
        bSourceID              11
        bControlSize            1
        bmaControls( 0)      0x03
          Mute Control
          Volume Control
        bmaControls( 1)      0x00
        iFeature                0 
      AudioControl Interface Descriptor:
        bLength                12
        bDescriptorType        36
        bDescriptorSubtype      4 (MIXER_UNIT)
        bUnitID                 7
        bNrInPins               1
        baSourceID( 0)          2
        bNrChannels             1
        wChannelConfig     0x0001
          Left Front (L)
        iChannelNames           0 
        bmControls         0x00
        iMixer                  0 
      AudioControl Interface Descriptor:
        bLength                 9
        bDescriptorType        36
        bDescriptorSubtype      3 (OUTPUT_TERMINAL)
        bTerminalID            10
        wTerminalType      0x0101 USB Streaming
        bAssocTerminal          0
        bSourceID               7
        iTerminal               0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          12
        bDelay                  1 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                23
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             2
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            5 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        11025
        tSamFreq[ 2]        22050
        tSamFreq[ 3]        44100
        tSamFreq[ 4]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            9
          Transfer Type            Isochronous
          Synch Type               Adaptive
          Usage Type               Data
        wMaxPacketSize     0x00c0  1x 192 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         0 Undefined
          wLockDelay              0 Undefined
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       2
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          12
        bDelay                  1 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                23
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            5 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        11025
        tSamFreq[ 2]        22050
        tSamFreq[ 3]        44100
        tSamFreq[ 4]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            9
          Transfer Type            Isochronous
          Synch Type               Adaptive
          Usage Type               Data
        wMaxPacketSize     0x0060  1x 96 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         0 Undefined
          wLockDelay              0 Undefined
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       1
      bNumEndpoints           1
      bInterfaceClass         1 Audio
      bInterfaceSubClass      2 Streaming
      bInterfaceProtocol      0 
      iInterface              0 
      AudioStreaming Interface Descriptor:
        bLength                 7
        bDescriptorType        36
        bDescriptorSubtype      1 (AS_GENERAL)
        bTerminalLink          10
        bDelay                  0 frames
        wFormatTag              1 PCM
      AudioStreaming Interface Descriptor:
        bLength                23
        bDescriptorType        36
        bDescriptorSubtype      2 (FORMAT_TYPE)
        bFormatType             1 (FORMAT_TYPE_I)
        bNrChannels             1
        bSubframeSize           2
        bBitResolution         16
        bSamFreqType            5 Discrete
        tSamFreq[ 0]         8000
        tSamFreq[ 1]        11025
        tSamFreq[ 2]        22050
        tSamFreq[ 3]        44100
        tSamFreq[ 4]        48000
      Endpoint Descriptor:
        bLength                 9
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            9
          Transfer Type            Isochronous
          Synch Type               Adaptive
          Usage Type               Data
        wMaxPacketSize     0x0060  1x 96 bytes
        bInterval               1
        bRefresh                0
        bSynchAddress           0
        AudioControl Endpoint Descriptor:
          bLength                 7
          bDescriptorType        37
          bDescriptorSubtype      1 (EP_GENERAL)
          bmAttributes         0x01
            Sampling Frequency
          bLockDelayUnits         2 Decoded PCM samples
          wLockDelay              1 Decoded PCM samples
Device Status:     0x0000
  (Bus Powered)

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-31  4:35           ` Grant Diffey
@ 2011-12-31  8:04             ` Grant Diffey
  0 siblings, 0 replies; 28+ messages in thread
From: Grant Diffey @ 2011-12-31  8:04 UTC (permalink / raw)
  To: Daniel Mack, alsa-devel

On Sat, Dec 31, 2011 at 3:35 PM, Grant Diffey <gdiffey@gmail.com> wrote:

>
> Yes, any kind of USB audio device is good.
>>
>> Thanks for heling test! :)
>>
>>
>>
> So sadly not all is well in my world the logitech is only registering as a
> mono device for some reason.
>
> nevyn@cetacea:~$ speaker-test -c 2 -D hw:Headset
>
> speaker-test 1.0.24.2
>
> Playback device is hw:Headset
> Stream parameters are 48000Hz, S16_LE, 2 channels
> Using 16 octaves of pink noise
> Channels count (2) not available for playbacks: Invalid argument
> Setting of hwparams failed: Invalid argument
>
>
> it's clearly stereo. lsusb -vv attached for reference
>


This also affects the 3.2-rc2 version I compiled a few weeks ago

3.0.0-rc5 correctly registers the device as stereo.

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
  2011-12-30 15:22   ` Felix Homann
       [not found]   ` <CAFz=ag6XNJSXvYQnAEbx=M+zXVH7sEw=_CJQKx63MmdQBWFuwA@mail.gmail.com>
@ 2011-12-31 14:23   ` Felix Homann
  2011-12-31 15:02     ` Aurélien Leblond
       [not found]   ` <CAFz=ag7_qzPJq44havp=EbFVKud5VvKaOLJk0i0dM43X3urp9Q@mail.gmail.com>
  3 siblings, 1 reply; 28+ messages in thread
From: Felix Homann @ 2011-12-31 14:23 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Takashi Iwai, Aurélien Leblond, alsa-devel, Clemens Ladisch,
	Grant Diffey

> On 12/23/2011 05:15 PM, Daniel Mack wrote:
> Any chance that more people who've been waiting for support of the FTU
> can use the lazy time between the years and quickly test this set?


OK, it doesn't work for me. Each time I try to start a stream I get
error messages like this:

cannot submit urb 0, error -28: not enough bandwidth


This doesn't need to be related to your patch. I might even have
messed something up in the rc3 kernels config. How can I tell?

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-31 14:23   ` Felix Homann
@ 2011-12-31 15:02     ` Aurélien Leblond
  2011-12-31 15:39       ` Felix Homann
  0 siblings, 1 reply; 28+ messages in thread
From: Aurélien Leblond @ 2011-12-31 15:02 UTC (permalink / raw)
  To: Felix Homann
  Cc: Takashi Iwai, alsa-devel, Clemens Ladisch, Grant Diffey, Daniel Mack

> OK, it doesn't work for me. Each time I try to start a stream I get
> error messages like this:
>
> cannot submit urb 0, error -28: not enough bandwidth

Hi Felix,

Is this when using the FTU or another USB device?

Would your USB device by any chance be of type USB 1, and the type of
the USB port on your machine EHCI?

If so, could it be related to this problem?
http://lists.linuxaudio.org/pipermail/linux-audio-user/2011-November/081814.html

There used to be a problem with EHCI and USB1 soundcards.
I never got my Edirol UA-25Ex to work on my machine, gettting the
exact same error as the one you described.

But, few weeks ago, while testing the RC 3.2 kernel with Daniel's
patch, it worked.
I don't believe Daniel's patch fixed the problem, but more the changes
done in 3.2 by Clemens.

Now, after more testing, it turns out my Edirol UA25-Ex works only if
I have a pretty high latency on Jack (25ms).
If I try and decrease the Frames/Period, then the bandwitdh issue
occurs again (mind me, it's way better then before where the sound
card wouldn't work in Full Duplex)...

Hope this helps,
Aurélien

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2011-12-31 15:02     ` Aurélien Leblond
@ 2011-12-31 15:39       ` Felix Homann
  0 siblings, 0 replies; 28+ messages in thread
From: Felix Homann @ 2011-12-31 15:39 UTC (permalink / raw)
  To: Aurélien Leblond
  Cc: Takashi Iwai, alsa-devel, Clemens Ladisch, Grant Diffey, Daniel Mack

Hi Aurélien,
2011/12/31 Aurélien Leblond <blablack@gmail.com>:> Is this when using
the FTU or another USB device?
It's the FTU. I don't have any other USB audio devices here which I could test.

> Would your USB device by any chance be of type USB 1, and the type of> the USB port on your machine EHCI?
So, no, it's not a USB 1 device. But it's on a EHCI port.
Unfortunately, I can't test the patch on a different machine at
thistime. But I will try the same kernel without Daniel's patch set
assoon as possible.
Regards,
Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
       [not found]   ` <CAFz=ag7_qzPJq44havp=EbFVKud5VvKaOLJk0i0dM43X3urp9Q@mail.gmail.com>
@ 2012-01-01 17:09     ` Felix Homann
  2012-01-16 20:26       ` Grant Diffey
  2012-04-10 15:40       ` Grant Diffey
  0 siblings, 2 replies; 28+ messages in thread
From: Felix Homann @ 2012-01-01 17:09 UTC (permalink / raw)
  To: Daniel Mack; +Cc: tiwai, blablack, alsa-devel, clemens, gdiffey

Happy New Year!

That being said, I've tested a kernel without Daniel's patch set. It
doesn't work either. The error messages are only slightly different:

Jan  1 11:52:31 weasel mtp-probe: checking bus 1, device 4:
"/sys/devices/pci0000:00/0000:00:1a.7/usb1/1-1"
Jan  1 11:52:31 weasel mtp-probe: bus: 1, device: 4 was not an MTP device
Jan  1 11:52:31 weasel kernel: [  161.880773] usbcore: registered new
interface driver snd-usb-audio
Jan  1 11:52:34 weasel kernel: [  164.284980] cannot submit datapipe
for urb 0, error -28: not enough bandwidth

So, It's not related to Daniel's rework. But nevertheless, something's broken...

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-01-01 17:09     ` Felix Homann
@ 2012-01-16 20:26       ` Grant Diffey
  2012-01-16 20:27         ` Grant Diffey
  2012-04-09 19:21         ` Daniel Mack
  2012-04-10 15:40       ` Grant Diffey
  1 sibling, 2 replies; 28+ messages in thread
From: Grant Diffey @ 2012-01-16 20:26 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Aurélien Leblond, alsa-devel, Clemens Ladisch, Felix Homann

So I've had a chance to do some testing. I can reliably generate then
following trace with daniels patch on 3.2-rt10

[  188.561901] ------------[ cut here ]------------
[  188.561908] WARNING: at fs/proc/generic.c:586 proc_register+0x181/0x1c7()
[  188.561909] Hardware name: HP Compaq 6910p
[  188.561911] proc_dir_entry 'card1/pcm0p' already registered
[  188.561912] Modules linked in: snd_usb_audio snd_usbmidi_lib
snd_seq_dummy acpi_cpufreq mperf cpufreq_userspace cpufreq_stats
cpufreq_conservative cpufreq_powersave ppdev lp parport microcode
binfmt_misc uinput fuse nfsd exportfs nfs lockd fscache auth_rpcgss nfs_acl
sunrpc ext2 firewire_sbp2 loop btusb bluetooth snd_hda_codec_analog arc4
iwl4965 iwl_legacy i915 mac80211 uhci_hcd snd_hda_intel snd_hda_codec
ehci_hcd drm_kms_helper snd_hwdep drm snd_pcm_oss snd_mixer_oss snd_pcm
snd_seq_midi cfg80211 snd_rawmidi snd_seq_midi_event snd_seq usbcore sr_mod
mmc_block snd_timer tpm_infineon pata_pcmcia snd_seq_device firewire_ohci
snd sdhci_pci i2c_algo_bit irda cdrom sdhci joydev pcmcia tpm_tis
ata_generic ata_piix hp_wmi firewire_core i2c_core yenta_socket pcmcia_rsrc
iTCO_wdt mmc_core battery pcmcia_core sparse_keymap ac power_supply rfkill
pcspkr soundcore tpm tpm_bios wmi iTCO_vendor_support evdev crc_itu_t
crc_ccitt psmouse processor container video usb_common snd_page_alloc
serio_raw button ext3 jbd mbcache sha256_generic aes_x86_64 aes_generic cbc
dm_crypt dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod fan thermal
thermal_sys
[  188.561979] Pid: 621, comm: khubd Not tainted 3.2.0-rt10-00255-g530565d
#5
[  188.561980] Call Trace:
[  188.561986]  [<ffffffff81036273>] ? warn_slowpath_common+0x78/0x8c
[  188.561989]  [<ffffffff8103631f>] ? warn_slowpath_fmt+0x45/0x4a
[  188.561993]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
[  188.561995]  [<ffffffff81123ac5>] ? proc_register+0x181/0x1c7
[  188.561997]  [<ffffffff81123e2c>] ? create_proc_entry+0x6e/0x85
[  188.562020]  [<ffffffffa0237c18>] ? snd_info_register+0x35/0xbd [snd]
[  188.562026]  [<ffffffffa02cdf89>] ? snd_pcm_new_stream+0xd6/0x417
[snd_pcm]
[  188.562031]  [<ffffffffa05b69e3>] ? snd_usb_add_audio_stream+0xd5/0x21c
[snd_usb_audio]
[  188.562035]  [<ffffffffa05b6fd3>] ?
snd_usb_parse_audio_interface+0x4a9/0x556 [snd_usb_audio]
[  188.562039]  [<ffffffffa05ae276>] ? snd_usb_create_stream+0xed/0x126
[snd_usb_audio]
[  188.562043]  [<ffffffffa05aea74>] ? usb_audio_probe+0x61d/0x72d
[snd_usb_audio]
[  188.562057]  [<ffffffffa028c6e3>] ? usb_probe_interface+0xf8/0x163
[usbcore]
[  188.562062]  [<ffffffff812170f1>] ? driver_probe_device+0xa8/0x138
[  188.562064]  [<ffffffff812171f0>] ? __driver_attach+0x6f/0x6f
[  188.562066]  [<ffffffff81216120>] ? bus_for_each_drv+0x4a/0x7e
[  188.562069]  [<ffffffff81217012>] ? device_attach+0x6f/0x8f
[  188.562071]  [<ffffffff8121692c>] ? bus_probe_device+0x1f/0x37
[  188.562073]  [<ffffffff8121520a>] ? device_add+0x3d4/0x577
[  188.562076]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
[  188.562078]  [<ffffffff81030bf0>] ? migrate_enable+0x150/0x16a
[  188.562085]  [<ffffffffa028b2b0>] ? usb_set_configuration+0x53f/0x594
[usbcore]
[  188.562088]  [<ffffffff811304e6>] ? sysfs_do_create_link+0x149/0x194
[  188.562094]  [<ffffffffa029231a>] ? generic_probe+0x45/0x73 [usbcore]
[  188.562097]  [<ffffffff812170f1>] ? driver_probe_device+0xa8/0x138
[  188.562099]  [<ffffffff812171f0>] ? __driver_attach+0x6f/0x6f
[  188.562101]  [<ffffffff81216120>] ? bus_for_each_drv+0x4a/0x7e
[  188.562104]  [<ffffffff81217012>] ? device_attach+0x6f/0x8f
[  188.562106]  [<ffffffff8121692c>] ? bus_probe_device+0x1f/0x37
[  188.562108]  [<ffffffff8121520a>] ? device_add+0x3d4/0x577
[  188.562110]  [<ffffffff81214793>] ? dev_printk+0x48/0x4d
[  188.562116]  [<ffffffffa0285188>] ? usb_new_device+0x124/0x198 [usbcore]
[  188.562122]  [<ffffffffa02861eb>] ? hub_thread+0x964/0xe54 [usbcore]
[  188.562124]  [<ffffffff8102abf4>] ? hrtick_start_fair+0x1a/0x15b
[  188.562127]  [<ffffffff8102000a>] ? kern_addr_valid+0x5/0x93
[  188.562131]  [<ffffffff8131adb9>] ? __schedule+0x531/0x548
[  188.562135]  [<ffffffff8104ff82>] ? __init_waitqueue_head+0x39/0x39
[  188.562140]  [<ffffffffa0285887>] ? usb_remote_wakeup+0x2f/0x2f [usbcore]
[  188.562142]  [<ffffffff8104f8b8>] ? kthread+0x78/0x80
[  188.562145]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
[  188.562148]  [<ffffffff81310000>] ? init_amd+0x112/0x3e4
[  188.562151]  [<ffffffff81322d74>] ? kernel_thread_helper+0x4/0x10
[  188.562154]  [<ffffffff8104f840>] ? __init_kthread_worker+0x41/0x41
[  188.562156]  [<ffffffff81322d70>] ? gs_change+0x13/0x13
[  188.562161] ---[ end trace 0000000000000002 ]---


Grant

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-01-16 20:26       ` Grant Diffey
@ 2012-01-16 20:27         ` Grant Diffey
  2012-04-09 19:21         ` Daniel Mack
  1 sibling, 0 replies; 28+ messages in thread
From: Grant Diffey @ 2012-01-16 20:27 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Aurélien Leblond, alsa-devel, Clemens Ladisch, Felix Homann

oh steps to reproduce remove logitech headset

Additionally there seems to be an issue with correctly detecting the number
of audio channels.

the logitech is only showing up as a mono output device with the new
streaming code.

Grant.

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-01-16 20:26       ` Grant Diffey
  2012-01-16 20:27         ` Grant Diffey
@ 2012-04-09 19:21         ` Daniel Mack
  2012-04-10 15:35           ` Grant Diffey
  2012-04-10 18:52           ` Felix Homann
  1 sibling, 2 replies; 28+ messages in thread
From: Daniel Mack @ 2012-04-09 19:21 UTC (permalink / raw)
  To: Grant Diffey
  Cc: Aurélien Leblond, alsa-devel, Clemens Ladisch, Felix Homann

Hi Grant et al,


Again sorry for catching up so late on this.


On 16.01.2012 21:26, Grant Diffey wrote:
> So I've had a chance to do some testing. I can reliably generate then
> following trace with daniels patch on 3.2-rt10
> 
> [  188.561901] ------------[ cut here ]------------
> [  188.561908] WARNING: at fs/proc/generic.c:586 proc_register+0x181/0x1c7()
> [  188.561909] Hardware name: HP Compaq 6910p
> [  188.561911] proc_dir_entry 'card1/pcm0p' already registered

There might have been a race condition in the shutdown path which I fixed.

Could you repeat the tests you did some months ago and report whether
you still see this issue? I would also appreciate test input from other
people. Any kind of USB device is good to track these issues.

Regarding the difference in reported channel numbers, I can't really
point my finger to any specific line. It really puzzles me, as my patch
set leaves the detection of interfaces and the registration of pcm
streams untouched. It would help to know whether there is any difference
in the output of "aplay -l" with and without my patches applied.

To test the new set of patches, please start off with a 3.4.0 vanilla
kernel and then either

  git pull git://github.com/zonque/linux.git usb-audio

or manually apply the combined patch from https://gist.github.com/1168715


I hope to *finally* get this topic finished in this round, but I need
the some helpers for testing :)



Daniel



> [  188.561912] Modules linked in: snd_usb_audio snd_usbmidi_lib
> snd_seq_dummy acpi_cpufreq mperf cpufreq_userspace cpufreq_stats
> cpufreq_conservative cpufreq_powersave ppdev lp parport microcode
> binfmt_misc uinput fuse nfsd exportfs nfs lockd fscache auth_rpcgss
> nfs_acl sunrpc ext2 firewire_sbp2 loop btusb bluetooth
> snd_hda_codec_analog arc4 iwl4965 iwl_legacy i915 mac80211 uhci_hcd
> snd_hda_intel snd_hda_codec ehci_hcd drm_kms_helper snd_hwdep drm
> snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_midi cfg80211 snd_rawmidi
> snd_seq_midi_event snd_seq usbcore sr_mod mmc_block snd_timer
> tpm_infineon pata_pcmcia snd_seq_device firewire_ohci snd sdhci_pci
> i2c_algo_bit irda cdrom sdhci joydev pcmcia tpm_tis ata_generic ata_piix
> hp_wmi firewire_core i2c_core yenta_socket pcmcia_rsrc iTCO_wdt mmc_core
> battery pcmcia_core sparse_keymap ac power_supply rfkill pcspkr
> soundcore tpm tpm_bios wmi iTCO_vendor_support evdev crc_itu_t crc_ccitt
> psmouse processor container video usb_common snd_page_alloc serio_raw
> button ext3 jbd mbcache sha256_generic aes_x86_64 aes_generic cbc
> dm_crypt dm_mod sd_mod crc_t10dif ahci libahci libata scsi_mod fan
> thermal thermal_sys
> [  188.561979] Pid: 621, comm: khubd Not tainted
> 3.2.0-rt10-00255-g530565d #5
> [  188.561980] Call Trace:
> [  188.561986]  [<ffffffff81036273>] ? warn_slowpath_common+0x78/0x8c
> [  188.561989]  [<ffffffff8103631f>] ? warn_slowpath_fmt+0x45/0x4a
> [  188.561993]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
> [  188.561995]  [<ffffffff81123ac5>] ? proc_register+0x181/0x1c7
> [  188.561997]  [<ffffffff81123e2c>] ? create_proc_entry+0x6e/0x85
> [  188.562020]  [<ffffffffa0237c18>] ? snd_info_register+0x35/0xbd [snd]
> [  188.562026]  [<ffffffffa02cdf89>] ? snd_pcm_new_stream+0xd6/0x417
> [snd_pcm]
> [  188.562031]  [<ffffffffa05b69e3>] ?
> snd_usb_add_audio_stream+0xd5/0x21c [snd_usb_audio]
> [  188.562035]  [<ffffffffa05b6fd3>] ?
> snd_usb_parse_audio_interface+0x4a9/0x556 [snd_usb_audio]
> [  188.562039]  [<ffffffffa05ae276>] ? snd_usb_create_stream+0xed/0x126
> [snd_usb_audio]
> [  188.562043]  [<ffffffffa05aea74>] ? usb_audio_probe+0x61d/0x72d
> [snd_usb_audio]
> [  188.562057]  [<ffffffffa028c6e3>] ? usb_probe_interface+0xf8/0x163
> [usbcore]
> [  188.562062]  [<ffffffff812170f1>] ? driver_probe_device+0xa8/0x138
> [  188.562064]  [<ffffffff812171f0>] ? __driver_attach+0x6f/0x6f
> [  188.562066]  [<ffffffff81216120>] ? bus_for_each_drv+0x4a/0x7e
> [  188.562069]  [<ffffffff81217012>] ? device_attach+0x6f/0x8f
> [  188.562071]  [<ffffffff8121692c>] ? bus_probe_device+0x1f/0x37
> [  188.562073]  [<ffffffff8121520a>] ? device_add+0x3d4/0x577
> [  188.562076]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
> [  188.562078]  [<ffffffff81030bf0>] ? migrate_enable+0x150/0x16a
> [  188.562085]  [<ffffffffa028b2b0>] ? usb_set_configuration+0x53f/0x594
> [usbcore]
> [  188.562088]  [<ffffffff811304e6>] ? sysfs_do_create_link+0x149/0x194
> [  188.562094]  [<ffffffffa029231a>] ? generic_probe+0x45/0x73 [usbcore]
> [  188.562097]  [<ffffffff812170f1>] ? driver_probe_device+0xa8/0x138
> [  188.562099]  [<ffffffff812171f0>] ? __driver_attach+0x6f/0x6f
> [  188.562101]  [<ffffffff81216120>] ? bus_for_each_drv+0x4a/0x7e
> [  188.562104]  [<ffffffff81217012>] ? device_attach+0x6f/0x8f
> [  188.562106]  [<ffffffff8121692c>] ? bus_probe_device+0x1f/0x37
> [  188.562108]  [<ffffffff8121520a>] ? device_add+0x3d4/0x577
> [  188.562110]  [<ffffffff81214793>] ? dev_printk+0x48/0x4d
> [  188.562116]  [<ffffffffa0285188>] ? usb_new_device+0x124/0x198 [usbcore]
> [  188.562122]  [<ffffffffa02861eb>] ? hub_thread+0x964/0xe54 [usbcore]
> [  188.562124]  [<ffffffff8102abf4>] ? hrtick_start_fair+0x1a/0x15b
> [  188.562127]  [<ffffffff8102000a>] ? kern_addr_valid+0x5/0x93
> [  188.562131]  [<ffffffff8131adb9>] ? __schedule+0x531/0x548
> [  188.562135]  [<ffffffff8104ff82>] ? __init_waitqueue_head+0x39/0x39
> [  188.562140]  [<ffffffffa0285887>] ? usb_remote_wakeup+0x2f/0x2f [usbcore]
> [  188.562142]  [<ffffffff8104f8b8>] ? kthread+0x78/0x80
> [  188.562145]  [<ffffffff8102df06>] ? get_parent_ip+0x9/0x1b
> [  188.562148]  [<ffffffff81310000>] ? init_amd+0x112/0x3e4
> [  188.562151]  [<ffffffff81322d74>] ? kernel_thread_helper+0x4/0x10
> [  188.562154]  [<ffffffff8104f840>] ? __init_kthread_worker+0x41/0x41
> [  188.562156]  [<ffffffff81322d70>] ? gs_change+0x13/0x13
> [  188.562161] ---[ end trace 0000000000000002 ]---
> 
> 
> Grant

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-04-09 19:21         ` Daniel Mack
@ 2012-04-10 15:35           ` Grant Diffey
  2012-04-10 18:52           ` Felix Homann
  1 sibling, 0 replies; 28+ messages in thread
From: Grant Diffey @ 2012-04-10 15:35 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Aurélien Leblond, alsa-devel, Clemens Ladisch, Felix Homann

On Tue, Apr 10, 2012 at 5:21 AM, Daniel Mack <zonque@gmail.com> wrote:

> Hi Grant et al,
>
>
> Again sorry for catching up so late on this.
>
>
> On 16.01.2012 21:26, Grant Diffey wrote:
> > So I've had a chance to do some testing. I can reliably generate then
> > following trace with daniels patch on 3.2-rt10
> >
> > [  188.561901] ------------[ cut here ]------------
> > [  188.561908] WARNING: at fs/proc/generic.c:586
> proc_register+0x181/0x1c7()
> > [  188.561909] Hardware name: HP Compaq 6910p
> > [  188.561911] proc_dir_entry 'card1/pcm0p' already registered
>
> There might have been a race condition in the shutdown path which I fixed.
>
> Could you repeat the tests you did some months ago and report whether
> you still see this issue? I would also appreciate test input from other
> people. Any kind of USB device is good to track these issues.
>
> Regarding the difference in reported channel numbers, I can't really
> point my finger to any specific line. It really puzzles me, as my patch
> set leaves the detection of interfaces and the registration of pcm
> streams untouched. It would help to know whether there is any difference
> in the output of "aplay -l" with and without my patches applied.
>
> To test the new set of patches, please start off with a 3.4.0 vanilla
> kernel and then either
>
>  git pull git://github.com/zonque/linux.git usb-audio
>
> or manually apply the combined patch from https://gist.github.com/1168715
>
>
> I hope to *finally* get this topic finished in this round, but I need
> the some helpers for testing :)
>
>
>
> Daniel
>
>
So this seems to be good it solves the clicking problem for me generating
sine wave's

I need to do some further testing. which is unlikely to happen this morning.

Grant.

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-01-01 17:09     ` Felix Homann
  2012-01-16 20:26       ` Grant Diffey
@ 2012-04-10 15:40       ` Grant Diffey
  1 sibling, 0 replies; 28+ messages in thread
From: Grant Diffey @ 2012-04-10 15:40 UTC (permalink / raw)
  To: Felix Homann; +Cc: tiwai, blablack, alsa-devel, clemens, Daniel Mack

On Mon, Jan 2, 2012 at 4:09 AM, Felix Homann <linuxaudio@showlabor.de>wrote:

> Happy New Year!
>
> That being said, I've tested a kernel without Daniel's patch set. It
> doesn't work either. The error messages are only slightly different:
>
> Jan  1 11:52:31 weasel mtp-probe: checking bus 1, device 4:
> "/sys/devices/pci0000:00/0000:00:1a.7/usb1/1-1"
> Jan  1 11:52:31 weasel mtp-probe: bus: 1, device: 4 was not an MTP device
> Jan  1 11:52:31 weasel kernel: [  161.880773] usbcore: registered new
> interface driver snd-usb-audio
> Jan  1 11:52:34 weasel kernel: [  164.284980] cannot submit datapipe
> for urb 0, error -28: not enough bandwidth
>
> So, It's not related to Daniel's rework. But nevertheless, something's
> broken...
>

are you sure it's connected to an EHCI (usb2) controller?

Grant.

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-04-09 19:21         ` Daniel Mack
  2012-04-10 15:35           ` Grant Diffey
@ 2012-04-10 18:52           ` Felix Homann
  2012-04-11 15:08             ` Daniel Mack
  1 sibling, 1 reply; 28+ messages in thread
From: Felix Homann @ 2012-04-10 18:52 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Aurélien Leblond, Grant Diffey, Clemens Ladisch, alsa-devel

Hi,

this time I can get the device to work. It produces clickless playback
at higher latencies. But trying to run JACK @44.1kHz with 128
frames/period (i.e. -p 128) I can reliably reproduce a kernel oops
which either completely freezes my system or at least blocks keyboard
an mouse. Here it is:

 Apr 10 20:25:43 weasel kernel: [  164.243214] usbcore: registered new
interface driver snd-usb-audio
Apr 10 20:27:00 weasel kernel: [  240.453704] BUG: unable to handle
kernel paging request at 00100104
Apr 10 20:27:00 weasel kernel: [  240.457673] IP: [<f90a7409>]
queue_pending_output_urbs+0x89/0x130 [snd_usb_audio]
Apr 10 20:27:00 weasel kernel: [  240.457673] *pde = 00000000
Apr 10 20:27:00 weasel kernel: [  240.457673] Oops: 0002 [#1] SMP
Apr 10 20:27:00 weasel kernel: [  240.457673] Modules linked in:
snd_usb_audio snd_usbmidi_lib snd_seq_dummy rfcomm bnep parport_pc
dm_crypt ppdev binfmt_misc snd_hda_c
odec_hdmi snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep
snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq joydev
coretemp snd_timer snd_seq_devi
ce uvcvideo hid_multitouch videobuf2_core snd microcode videodev
videobuf2_vmalloc videobuf2_memops btusb soundcore bluetooth
snd_page_alloc psmouse serio_raw lp parpor
t usbhid hid atl1c ahci libahci i915 drm_kms_helper drm wmi i2c_algo_bit video
Apr 10 20:27:00 weasel kernel: [  240.457673]
Apr 10 20:27:00 weasel kernel: [  240.457673] Pid: 0, comm: swapper/0
Not tainted 3.4.0-rc2-daniel+ #2 Acer Aspire 1420P/JM12-MS
Apr 10 20:27:00 weasel kernel: [  240.457673] EIP: 0060:[<f90a7409>]
EFLAGS: 00010002 CPU: 0
Apr 10 20:27:00 weasel kernel: [  240.457673] EIP is at
queue_pending_output_urbs+0x89/0x130 [snd_usb_audio]
Apr 10 20:27:00 weasel kernel: [  240.457673] EAX: 00200200 EBX:
edb08000 ECX: edb097ac EDX: edb08028
Apr 10 20:27:00 weasel kernel: [  240.457673] ESI: edb082c0 EDI:
00100100 EBP: f380be64 ESP: f380be3c
Apr 10 20:27:00 weasel kernel: [  240.457673]  DS: 007b ES: 007b FS:
00d8 GS: 00e0 SS: 0068
Apr 10 20:27:00 weasel kernel: [  240.457673] CR0: 8005003b CR2:
00100104 CR3: 018af000 CR4: 000407d0
Apr 10 20:27:00 weasel kernel: [  240.457673] DR0: 00000000 DR1:
00000000 DR2: 00000000 DR3: 00000000
Apr 10 20:27:00 weasel kernel: [  240.457673] DR6: ffff0ff0 DR7: 00000400
Apr 10 20:27:00 weasel kernel: [  240.457673] Process swapper/0 (pid:
0, ti=f380a000 task=c1794020 task.ti=c1788000)
Apr 10 20:27:00 weasel kernel: [  240.457673] Stack:
Apr 10 20:27:00 weasel kernel: [  240.457673]  f380be44 f380be4c
c105dfd2 f380be50 00000096 edb0a9b4 edb0a950 edeb5f08
Apr 10 20:27:00 weasel kernel: [  240.457673]  edb0c2c8 edb097ac
f380be94 f90a86bf edb0c2c8 f7007300 f7007300 edeb5e00
Apr 10 20:27:00 weasel kernel: [  240.457673]  00000092 edb0a9b4
edb08000 edb0c000 edb0c2c8 edeb5e00 f380beb8 f90a882d
Apr 10 20:27:00 weasel kernel: [  240.457673] Call Trace:
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c105dfd2>] ?
resched_task+0x22/0x70
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<f90a86bf>]
snd_usb_handle_sync_urb+0x1ef/0x260 [snd_usb_audio]
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<f90a882d>]
snd_complete_urb+0xfd/0x200 [snd_usb_audio]
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13dec0d>]
usb_hcd_giveback_urb+0x4d/0xc0
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1551f6d>] ?
_raw_spin_lock+0xd/0x10
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f3571>]
ehci_urb_done+0xc1/0xf0
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f4afc>]
ehci_work+0x8ec/0xa10
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f4ea1>] ehci_irq+0x221/0x250
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1080cb3>] ?
tick_do_periodic_broadcast+0x33/0x40
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13de3b2>]
usb_hcd_irq+0x32/0x50

Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10ad52c>]
handle_irq_event_percpu+0x4c/0x210
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c155219d>] ?
_raw_spin_lock_irqsave+0x2d/0x40
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10ad72b>]
handle_irq_event+0x3b/0x60
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10aff20>] ?
unmask_irq+0x30/0x30
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10aff6e>]
handle_fasteoi_irq+0x4e/0xd0
Apr 10 20:27:00 weasel kernel: [  240.457673]  <IRQ>
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1559432>] ? do_IRQ+0x42/0xc0
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10084f8>] ?
sched_clock+0x8/0x10
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1062e8b>] ?
sched_clock_local+0xcb/0x1c0
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1559370>] ?
common_interrupt+0x30/0x38
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10600d8>] ?
rt_mutex_setprio+0x98/0x200
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c131b5d6>] ?
arch_local_irq_enable+0x5/0xb
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c131c30f>] ?
acpi_idle_enter_bm+0x228/0x268
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c143b785>] ?
cpuidle_enter+0x15/0x20
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c143bd1c>] ?
cpuidle_idle_call+0x9c/0x260
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c100a10a>] ? cpu_idle+0xaa/0xe0
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c152e135>] ?
rest_init+0x5d/0x68
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f976c>] ?
start_kernel+0x367/0x36d
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f9186>] ? loglevel+0x2b/0x2b
Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f9078>] ?
i386_start_kernel+0x78/0x7d
Apr 10 20:27:00 weasel kernel: [  240.457673] Code: 00 83 c0 01 8d 8c
13 28 15 00 00 89 c2 c1 fa 1f c1 ea 1d 01 d0 83 e0 07 29 d0 89 83 48
29 00 00 8b 46 04 8d 96 68 fd ff ff 8b 3e <89> 47 04 89 38 c7 06 00 01
10 00 c7 46 04 00 02 20 00 8b 81 80
Apr 10 20:27:00 weasel kernel: [  240.457673] EIP: [<f90a7409>]
queue_pending_output_urbs+0x89/0x130 [snd_usb_audio] SS:ESP
0068:f380be3c
Apr 10 20:27:00 weasel kernel: [  240.457673] CR2: 0000000000100104


After this messageand only ahter this oops I'm getting lots of ACPI errors:

Apr 10 20:27:06 weasel kernel: [  247.021871] ACPI Exception: AE_TIME,
Returned by Handler for [EmbeddedControl] (20120320/evregion-501)
Apr 10 20:27:06 weasel kernel: [  247.024423] ACPI Error: Method
parse/execution failed [\_SB_.BAT1._BST] (Node f382b2d0), AE_TIME
(20120320/psparse-536)
Apr 10 20:27:06 weasel kernel: [  247.025805] ACPI Exception: AE_TIME,
Evaluating _BST (20120320/battery-455)
Apr 10 20:27:07 weasel kernel: [  248.178058] ACPI Exception: AE_TIME,
Returned by Handler for [EmbeddedControl] (20120320/evregion-501)
Apr 10 20:27:07 weasel kernel: [  248.180657] ACPI Error: Method
parse/execution failed [\_SB_.BAT1._BST] (Node f382b2d0), AE_TIME
(20120320/psparse-536)
Apr 10 20:27:07 weasel kernel: [  248.182039] ACPI Exception: AE_TIME,
Evaluating _BST (20120320/battery-455)


Any ideas?

Regards,

Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-04-10 18:52           ` Felix Homann
@ 2012-04-11 15:08             ` Daniel Mack
  2012-04-12  9:05               ` Felix Homann
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Mack @ 2012-04-11 15:08 UTC (permalink / raw)
  To: Felix Homann
  Cc: Aurélien Leblond, Grant Diffey, Clemens Ladisch, alsa-devel

Hi,

On 10.04.2012 20:52, Felix Homann wrote:
> this time I can get the device to work. It produces clickless playback
> at higher latencies. But trying to run JACK @44.1kHz with 128
> frames/period (i.e. -p 128) I can reliably reproduce a kernel oops
> which either completely freezes my system or at least blocks keyboard
> an mouse. Here it is:

Good catch, thanks! I was able to trigger that one too, and fixed it.
Just refreshed my tree and the combined patch (gist). Could you give it
another shot?


Thanks,
Daniel



> 
>  Apr 10 20:25:43 weasel kernel: [  164.243214] usbcore: registered new
> interface driver snd-usb-audio
> Apr 10 20:27:00 weasel kernel: [  240.453704] BUG: unable to handle
> kernel paging request at 00100104
> Apr 10 20:27:00 weasel kernel: [  240.457673] IP: [<f90a7409>]
> queue_pending_output_urbs+0x89/0x130 [snd_usb_audio]
> Apr 10 20:27:00 weasel kernel: [  240.457673] *pde = 00000000
> Apr 10 20:27:00 weasel kernel: [  240.457673] Oops: 0002 [#1] SMP
> Apr 10 20:27:00 weasel kernel: [  240.457673] Modules linked in:
> snd_usb_audio snd_usbmidi_lib snd_seq_dummy rfcomm bnep parport_pc
> dm_crypt ppdev binfmt_misc snd_hda_c
> odec_hdmi snd_hda_codec_realtek snd_hda_intel snd_hda_codec snd_hwdep
> snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq joydev
> coretemp snd_timer snd_seq_devi
> ce uvcvideo hid_multitouch videobuf2_core snd microcode videodev
> videobuf2_vmalloc videobuf2_memops btusb soundcore bluetooth
> snd_page_alloc psmouse serio_raw lp parpor
> t usbhid hid atl1c ahci libahci i915 drm_kms_helper drm wmi i2c_algo_bit video
> Apr 10 20:27:00 weasel kernel: [  240.457673]
> Apr 10 20:27:00 weasel kernel: [  240.457673] Pid: 0, comm: swapper/0
> Not tainted 3.4.0-rc2-daniel+ #2 Acer Aspire 1420P/JM12-MS
> Apr 10 20:27:00 weasel kernel: [  240.457673] EIP: 0060:[<f90a7409>]
> EFLAGS: 00010002 CPU: 0
> Apr 10 20:27:00 weasel kernel: [  240.457673] EIP is at
> queue_pending_output_urbs+0x89/0x130 [snd_usb_audio]
> Apr 10 20:27:00 weasel kernel: [  240.457673] EAX: 00200200 EBX:
> edb08000 ECX: edb097ac EDX: edb08028
> Apr 10 20:27:00 weasel kernel: [  240.457673] ESI: edb082c0 EDI:
> 00100100 EBP: f380be64 ESP: f380be3c
> Apr 10 20:27:00 weasel kernel: [  240.457673]  DS: 007b ES: 007b FS:
> 00d8 GS: 00e0 SS: 0068
> Apr 10 20:27:00 weasel kernel: [  240.457673] CR0: 8005003b CR2:
> 00100104 CR3: 018af000 CR4: 000407d0
> Apr 10 20:27:00 weasel kernel: [  240.457673] DR0: 00000000 DR1:
> 00000000 DR2: 00000000 DR3: 00000000
> Apr 10 20:27:00 weasel kernel: [  240.457673] DR6: ffff0ff0 DR7: 00000400
> Apr 10 20:27:00 weasel kernel: [  240.457673] Process swapper/0 (pid:
> 0, ti=f380a000 task=c1794020 task.ti=c1788000)
> Apr 10 20:27:00 weasel kernel: [  240.457673] Stack:
> Apr 10 20:27:00 weasel kernel: [  240.457673]  f380be44 f380be4c
> c105dfd2 f380be50 00000096 edb0a9b4 edb0a950 edeb5f08
> Apr 10 20:27:00 weasel kernel: [  240.457673]  edb0c2c8 edb097ac
> f380be94 f90a86bf edb0c2c8 f7007300 f7007300 edeb5e00
> Apr 10 20:27:00 weasel kernel: [  240.457673]  00000092 edb0a9b4
> edb08000 edb0c000 edb0c2c8 edeb5e00 f380beb8 f90a882d
> Apr 10 20:27:00 weasel kernel: [  240.457673] Call Trace:
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c105dfd2>] ?
> resched_task+0x22/0x70
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<f90a86bf>]
> snd_usb_handle_sync_urb+0x1ef/0x260 [snd_usb_audio]
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<f90a882d>]
> snd_complete_urb+0xfd/0x200 [snd_usb_audio]
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13dec0d>]
> usb_hcd_giveback_urb+0x4d/0xc0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1551f6d>] ?
> _raw_spin_lock+0xd/0x10
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f3571>]
> ehci_urb_done+0xc1/0xf0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f4afc>]
> ehci_work+0x8ec/0xa10
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13f4ea1>] ehci_irq+0x221/0x250
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1080cb3>] ?
> tick_do_periodic_broadcast+0x33/0x40
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c13de3b2>]
> usb_hcd_irq+0x32/0x50
> 
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10ad52c>]
> handle_irq_event_percpu+0x4c/0x210
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c155219d>] ?
> _raw_spin_lock_irqsave+0x2d/0x40
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10ad72b>]
> handle_irq_event+0x3b/0x60
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10aff20>] ?
> unmask_irq+0x30/0x30
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10aff6e>]
> handle_fasteoi_irq+0x4e/0xd0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  <IRQ>
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1559432>] ? do_IRQ+0x42/0xc0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10084f8>] ?
> sched_clock+0x8/0x10
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1062e8b>] ?
> sched_clock_local+0xcb/0x1c0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c1559370>] ?
> common_interrupt+0x30/0x38
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c10600d8>] ?
> rt_mutex_setprio+0x98/0x200
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c131b5d6>] ?
> arch_local_irq_enable+0x5/0xb
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c131c30f>] ?
> acpi_idle_enter_bm+0x228/0x268
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c143b785>] ?
> cpuidle_enter+0x15/0x20
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c143bd1c>] ?
> cpuidle_idle_call+0x9c/0x260
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c100a10a>] ? cpu_idle+0xaa/0xe0
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c152e135>] ?
> rest_init+0x5d/0x68
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f976c>] ?
> start_kernel+0x367/0x36d
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f9186>] ? loglevel+0x2b/0x2b
> Apr 10 20:27:00 weasel kernel: [  240.457673]  [<c17f9078>] ?
> i386_start_kernel+0x78/0x7d
> Apr 10 20:27:00 weasel kernel: [  240.457673] Code: 00 83 c0 01 8d 8c
> 13 28 15 00 00 89 c2 c1 fa 1f c1 ea 1d 01 d0 83 e0 07 29 d0 89 83 48
> 29 00 00 8b 46 04 8d 96 68 fd ff ff 8b 3e <89> 47 04 89 38 c7 06 00 01
> 10 00 c7 46 04 00 02 20 00 8b 81 80
> Apr 10 20:27:00 weasel kernel: [  240.457673] EIP: [<f90a7409>]
> queue_pending_output_urbs+0x89/0x130 [snd_usb_audio] SS:ESP
> 0068:f380be3c
> Apr 10 20:27:00 weasel kernel: [  240.457673] CR2: 0000000000100104
> 
> 
> After this messageand only ahter this oops I'm getting lots of ACPI errors:
> 
> Apr 10 20:27:06 weasel kernel: [  247.021871] ACPI Exception: AE_TIME,
> Returned by Handler for [EmbeddedControl] (20120320/evregion-501)
> Apr 10 20:27:06 weasel kernel: [  247.024423] ACPI Error: Method
> parse/execution failed [\_SB_.BAT1._BST] (Node f382b2d0), AE_TIME
> (20120320/psparse-536)
> Apr 10 20:27:06 weasel kernel: [  247.025805] ACPI Exception: AE_TIME,
> Evaluating _BST (20120320/battery-455)
> Apr 10 20:27:07 weasel kernel: [  248.178058] ACPI Exception: AE_TIME,
> Returned by Handler for [EmbeddedControl] (20120320/evregion-501)
> Apr 10 20:27:07 weasel kernel: [  248.180657] ACPI Error: Method
> parse/execution failed [\_SB_.BAT1._BST] (Node f382b2d0), AE_TIME
> (20120320/psparse-536)
> Apr 10 20:27:07 weasel kernel: [  248.182039] ACPI Exception: AE_TIME,
> Evaluating _BST (20120320/battery-455)
> 
> 
> Any ideas?
> 
> Regards,
> 
> Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-04-11 15:08             ` Daniel Mack
@ 2012-04-12  9:05               ` Felix Homann
  2012-04-12 11:45                 ` Daniel Mack
  0 siblings, 1 reply; 28+ messages in thread
From: Felix Homann @ 2012-04-12  9:05 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Aurélien Leblond, Grant Diffey, Clemens Ladisch, alsa-devel

Hi,

2012/4/11 Daniel Mack <zonque@gmail.com>:
> Just refreshed my tree and the combined patch (gist). Could you give it
> another shot?

I've just tested the new version and have not found any issues. Great
work! Thank you very much!

BTW, didn't you have a patch for switching to an external clock source
on the FTUs? Maybe it would be useful for me to clean up the dirty
hack I've got somewhere for the effects controls. (Don't hurry, it
will take me a couple of weeks anyway due to time constraints)

Regards,

Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-04-12  9:05               ` Felix Homann
@ 2012-04-12 11:45                 ` Daniel Mack
  0 siblings, 0 replies; 28+ messages in thread
From: Daniel Mack @ 2012-04-12 11:45 UTC (permalink / raw)
  To: Felix Homann
  Cc: Aurélien Leblond, Grant Diffey, Clemens Ladisch, alsa-devel

On 12.04.2012 11:05, Felix Homann wrote:
> Hi,
> 
> 2012/4/11 Daniel Mack <zonque@gmail.com>:
>> Just refreshed my tree and the combined patch (gist). Could you give it
>> another shot?
> 
> I've just tested the new version and have not found any issues. Great
> work! Thank you very much!

Good news indeed. As Grant is also signalling green light, I'll post
version 7 of the patch series now.

> BTW, didn't you have a patch for switching to an external clock source
> on the FTUs? Maybe it would be useful for me to clean up the dirty
> hack I've got somewhere for the effects controls. (Don't hurry, it
> will take me a couple of weeks anyway due to time constraints)

Can't find it right now. But that should be comparatively easy to do in
a subsequent patch.


Thanks,
Daniel

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-02-22 18:50 ` Daniel Mack
@ 2012-03-05  8:01   ` Felix Homann
  0 siblings, 0 replies; 28+ messages in thread
From: Felix Homann @ 2012-03-05  8:01 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Takashi Iwai, Aurélien Leblond, alsa-devel, Clemens Ladisch,
	Grant Diffey

Hi Daniel,

2012/2/22 Daniel Mack <zonque@gmail.com>:
>
> Sorry for the silence on this topic. I've been distracted by work that
> isn't even remotely kernel related during the last weeks, so I lost
> track on this. I'll catch up again soon, and review the reports from
> around christmas last year, rebase the series and resubmit.

great to see you back here on the list! As you can tell from my
silence on all of this, I've been very busy, too.

Kind regards,
Felix

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

* Re: [PATCH 0/6] snd-usb endpoint rework, version 6
  2012-02-13 20:41 Aurélien Leblond
@ 2012-02-22 18:50 ` Daniel Mack
  2012-03-05  8:01   ` Felix Homann
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Mack @ 2012-02-22 18:50 UTC (permalink / raw)
  To: Aurélien Leblond
  Cc: Takashi Iwai, alsa-devel, Grant Diffey, Clemens Ladisch, Felix Homann

On 13.02.2012 21:41, Aurélien Leblond wrote:
> Hello everyone,
> 
> My laptop has been in reparation for a while and I just got it back
> now, so I have been out of sync with any update on the snd-usb module,
> the support of the M-Audio Fast Track Ultra, and I now need to
> re-setup my laptop.
> 
> As far as I can see, the kernel 3.2.5 doesn't have the update of Alsa
> 1.0.25, so the first thing I did was to compile those two separately
> (compile first the kernel without any sound support, then compile and
> install 1.0.25), but the midi was then not working on the M-Audio FTU,
> the Roland UA-25Ex and my E-Mu USB keyboard. All modules are probed,
> no messages in dmesg, but jack doesn't see any alsa midi driver.
> In addition, I cannot make out if Daniel's changes are part of this
> release of Alsa!
> 
> My next step was to get a git version of the kernel, add Takashi's
> branch and Daniel's one on top of it (process I used to do 2 months
> ago), but I get a conflicting error when pulling/merging Daniel's
> patch, so I guess it is not in sync with the latest kernel anymore...
> 
> So my questions are:
> - Did I do something wrong with the kernel 3.2.5/alsa 1.0.25 that
> broke the USB Midi or is it a bug? I ran through the mailing list but
> couldn't see anything mentionned about USB Midi. As far as I can tell,
> I have all the necessary modules.
> - What is the status of Daniel's work on the snd-usb module? Again I
> ran through the changelog of alsa 1.0.25 but couldn't make out if it
> was integrated or not.

Sorry for the silence on this topic. I've been distracted by work that
isn't even remotely kernel related during the last weeks, so I lost
track on this. I'll catch up again soon, and review the reports from
around christmas last year, rebase the series and resubmit.

Again, sorry for the delay.

Daniel

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

* [PATCH 0/6] snd-usb endpoint rework, version 6
@ 2012-02-13 20:41 Aurélien Leblond
  2012-02-22 18:50 ` Daniel Mack
  0 siblings, 1 reply; 28+ messages in thread
From: Aurélien Leblond @ 2012-02-13 20:41 UTC (permalink / raw)
  To: alsa-devel, Daniel Mack, Takashi Iwai, Felix Homann,
	Clemens Ladisch, Grant Diffey

Hello everyone,

My laptop has been in reparation for a while and I just got it back
now, so I have been out of sync with any update on the snd-usb module,
the support of the M-Audio Fast Track Ultra, and I now need to
re-setup my laptop.

As far as I can see, the kernel 3.2.5 doesn't have the update of Alsa
1.0.25, so the first thing I did was to compile those two separately
(compile first the kernel without any sound support, then compile and
install 1.0.25), but the midi was then not working on the M-Audio FTU,
the Roland UA-25Ex and my E-Mu USB keyboard. All modules are probed,
no messages in dmesg, but jack doesn't see any alsa midi driver.
In addition, I cannot make out if Daniel's changes are part of this
release of Alsa!

My next step was to get a git version of the kernel, add Takashi's
branch and Daniel's one on top of it (process I used to do 2 months
ago), but I get a conflicting error when pulling/merging Daniel's
patch, so I guess it is not in sync with the latest kernel anymore...

So my questions are:
- Did I do something wrong with the kernel 3.2.5/alsa 1.0.25 that
broke the USB Midi or is it a bug? I ran through the mailing list but
couldn't see anything mentionned about USB Midi. As far as I can tell,
I have all the necessary modules.
- What is the status of Daniel's work on the snd-usb module? Again I
ran through the changelog of alsa 1.0.25 but couldn't make out if it
was integrated or not.


So as usual, thanks in advance for your help and if there is anymore
information I can provide, please let me know.

Aurélien

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

end of thread, other threads:[~2012-04-12 11:46 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
2011-12-23 16:15 ` [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex Daniel Mack
2011-12-23 16:15 ` [PATCH 2/6] ALSA: snd-usb: implement new endpoint streaming model Daniel Mack
2011-12-23 16:15 ` [PATCH 3/6] ALSA: snd-usb: switch over to new endpoint streaming logic Daniel Mack
2011-12-23 16:15 ` [PATCH 4/6] ALSA: snd-usb: remove old " Daniel Mack
2011-12-23 16:15 ` [PATCH 5/6] ALSA: snd-usb: add support for implicit feedback Daniel Mack
2011-12-23 16:15 ` [PATCH 6/6] ALSA: snd-usb: add some documentation Daniel Mack
2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
2011-12-30 15:22   ` Felix Homann
     [not found]   ` <CAFz=ag6XNJSXvYQnAEbx=M+zXVH7sEw=_CJQKx63MmdQBWFuwA@mail.gmail.com>
2011-12-30 15:24     ` Daniel Mack
     [not found]       ` <CACckToWP-C5H2xhvdJ5ykNf4BcuNCa4cMyFh2hppcwW0u33fQQ@mail.gmail.com>
     [not found]         ` <4EFE6E52.4050503@gmail.com>
2011-12-31  4:35           ` Grant Diffey
2011-12-31  8:04             ` Grant Diffey
2011-12-31 14:23   ` Felix Homann
2011-12-31 15:02     ` Aurélien Leblond
2011-12-31 15:39       ` Felix Homann
     [not found]   ` <CAFz=ag7_qzPJq44havp=EbFVKud5VvKaOLJk0i0dM43X3urp9Q@mail.gmail.com>
2012-01-01 17:09     ` Felix Homann
2012-01-16 20:26       ` Grant Diffey
2012-01-16 20:27         ` Grant Diffey
2012-04-09 19:21         ` Daniel Mack
2012-04-10 15:35           ` Grant Diffey
2012-04-10 18:52           ` Felix Homann
2012-04-11 15:08             ` Daniel Mack
2012-04-12  9:05               ` Felix Homann
2012-04-12 11:45                 ` Daniel Mack
2012-04-10 15:40       ` Grant Diffey
2012-02-13 20:41 Aurélien Leblond
2012-02-22 18:50 ` Daniel Mack
2012-03-05  8:01   ` Felix Homann

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.