[ALSA] usb-audio: don't use empty packets at start of playback

Modules: USB generic driver

Some widespread USB interface chips with adaptive iso endpoints hang
after receiving a series of empty packets when they expect data (ALSA
bug#1585).  To avoid this, we have to send packets containing silence
(zero samples) instead.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
This commit is contained in:
Clemens Ladisch 2006-01-12 08:17:49 +01:00 committed by Jaroslav Kysela
parent 54c63cfc15
commit 4b28492834

View File

@ -478,22 +478,38 @@ static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
/* /*
* Prepare urb for streaming before playback starts. * Prepare urb for streaming before playback starts.
* *
* We don't care about (or have) any data, so we just send a transfer delimiter. * We don't yet have data, so we send a frame of silence.
*/ */
static int prepare_startup_playback_urb(struct snd_usb_substream *subs, static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
struct snd_pcm_runtime *runtime, struct snd_pcm_runtime *runtime,
struct urb *urb) struct urb *urb)
{ {
unsigned int i; unsigned int i, offs, counts;
struct snd_urb_ctx *ctx = urb->context; struct snd_urb_ctx *ctx = urb->context;
int stride = runtime->frame_bits >> 3;
offs = 0;
urb->dev = ctx->subs->dev; urb->dev = ctx->subs->dev;
urb->number_of_packets = subs->packs_per_ms; urb->number_of_packets = subs->packs_per_ms;
for (i = 0; i < subs->packs_per_ms; ++i) { for (i = 0; i < subs->packs_per_ms; ++i) {
urb->iso_frame_desc[i].offset = 0; /* calculate the size of a packet */
urb->iso_frame_desc[i].length = 0; if (subs->fill_max)
counts = subs->maxframesize; /* fixed */
else {
subs->phase = (subs->phase & 0xffff)
+ (subs->freqm << subs->datainterval);
counts = subs->phase >> 16;
if (counts > subs->maxframesize)
counts = subs->maxframesize;
}
urb->iso_frame_desc[i].offset = offs * stride;
urb->iso_frame_desc[i].length = counts * stride;
offs += counts;
} }
urb->transfer_buffer_length = 0; urb->transfer_buffer_length = offs * stride;
memset(urb->transfer_buffer,
subs->cur_audiofmt->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
offs * stride);
return 0; return 0;
} }