[alsa-devel] [PATCH 2/3] snd-bcd2000: add playback and capture support

Takashi Iwai tiwai at suse.de
Sun Feb 1 11:40:45 CET 2015


At Sun, 01 Feb 2015 10:29:24 +0100,
Takashi Iwai wrote:
> 
> At Sat, 31 Jan 2015 22:34:24 +0100,
> Mario Kicherer wrote:
> > 
> > +/* handle incoming URB with captured data */
> > +static void bcd2000_pcm_in_urb_handler(struct urb *usb_urb)
> > +{
> > +	struct bcd2000_urb *bcd2k_urb = usb_urb->context;
> > +	struct bcd2000_pcm *pcm = &bcd2k_urb->bcd2k->pcm;
> > +	struct bcd2000_substream *stream = bcd2k_urb->stream;
> > +	unsigned long flags;
> > +	int ret, k, period_bytes;
> > +	struct usb_iso_packet_descriptor *packet;
> > +
> > +	if (pcm->panic || stream->state == STREAM_STOPPING)
> > +		return;
> 
> Don't you need protection for these flags and state variables?
> 
> > +
> > +	if (unlikely(usb_urb->status == -ENOENT ||	/* unlinked */
> > +		usb_urb->status == -ENODEV ||		/* device removed */
> > +		usb_urb->status == -ECONNRESET ||	/* unlinked */
> > +		usb_urb->status == -ESHUTDOWN))		/* device disabled */
> > +	{
> > +		goto out_fail;
> 
> This isn't always an error, e.g. active URBS at disconnection.
> 
> > +	}
> > +
> > +	if (stream->state == STREAM_STARTING) {
> > +		stream->wait_cond = true;
> > +		wake_up(&stream->wait_queue);
> > +	}
> > +
> > +	if (stream->active) {
> > +		spin_lock_irqsave(&stream->lock, flags);
> > +
> > +		/* copy captured data into ALSA buffer */
> > +		bcd2000_pcm_capture(stream, bcd2k_urb);
> > +
> > +		period_bytes = snd_pcm_lib_period_bytes(stream->instance);
> > +
> > +		/* do we have enough data for one period? */
> > +		if (stream->period_off > period_bytes) {
> > +			stream->period_off %= period_bytes;
> > +
> > +			spin_unlock_irqrestore(&stream->lock, flags);
> > +
> > +			/*
> > +			 * call this only once even if multiple periods
> > +			 * are ready
> > +			 */
> > +			snd_pcm_period_elapsed(stream->instance);
> > +
> > +			memset(bcd2k_urb->buffer, 0, USB_BUFFER_SIZE);
> > +		} else {
> > +			spin_unlock_irqrestore(&stream->lock, flags);
> > +			memset(bcd2k_urb->buffer, 0, USB_BUFFER_SIZE);
> > +		}
> > +	} else {
> > +		memset(bcd2k_urb->buffer, 0, USB_BUFFER_SIZE);
> 
> We see three same lines of memset...  It shows something to improve.
> 
> 
> > +	}
> > +
> > +	/* reset URB data */
> > +	for (k = 0; k < USB_N_PACKETS_PER_URB; k++) {
> > +		packet = &bcd2k_urb->packets[k];
> > +		packet->offset = k * USB_PACKET_SIZE;
> > +		packet->length = USB_PACKET_SIZE;
> > +		packet->actual_length = 0;
> > +		packet->status = 0;
> > +	}
> > +	bcd2k_urb->instance.number_of_packets = USB_N_PACKETS_PER_URB;
> > +
> > +	/* send the URB back to the BCD2000 */
> > +	ret = usb_submit_urb(&bcd2k_urb->instance, GFP_ATOMIC);
> > +	if (ret < 0)
> > +		goto out_fail;
> > +
> > +	return;
> > +
> > +out_fail:
> > +	dev_info(&bcd2k_urb->bcd2k->dev->dev, PREFIX "error in in_urb handler");
> > +	pcm->panic = true;
> 
> How is pcm->panic recovered?
> I see it's cleared in bcd2000_pcm_stream_start().  But then some
> doubts:
> 
> - who will refill / resubmit urbs at restart?
> 
> - the flag is common to both playback and capture, and it's cleared in
>   the trigger for one direction?
> 
> Also, does the disconnection while playing/recording works reliably?
> snd_card_disconnect() doesn't close the PCM stream by itself, it
> merely triggers STOP and sets the state to DISCONNECTED.  That is,
> with your code, the URBs are still pending, and it's killed after
> disconnection callback returns.

After reading through this patch, I now wonder whether the standard
usb-audio would work with a simple quirk for the PCM of this device.
If so, it'd be easier to merge bcd2000 stuff into usb-audio, as a
quirk for MIDI and additional controls, where already some devices do.

Writing the whole stuff from the scratch is error-prone.  With the
merger, you'll get the suspend/resume, auto PM, and the proper
disconnection with gratis.


thanks,

Takashi


More information about the Alsa-devel mailing list