Re: Getting pcm_usb_stream plugin to know its limits. [Kind of SOLVED]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Takashi Iwai <tiwai@xxxxxxx> writes:

> At Mon, 11 Jan 2010 13:35:19 -0500,
> Michaël Cadilhac wrote:
>> 
>> michael@xxxxxxxxxxxxx (Michaël Cadilhac) writes:
>> 
>> > michael@xxxxxxxxxxxxx (Michaël Cadilhac) writes:
>> >
>> >> So, my final saying is the following patch.  It fixes the segfault on
>> >> stopping a non-started usb_stream, plus it adds the ability to set a
>> >> period size and sound rate.  The latter offers a workaround for the
>> >> second issue I came with (that the default values for period bytes, and
>> >> hence period size, were too high for us122l to work).
>> >
>> > Any comment on that patch would be greatly appreciated.  I'm just
>> > wondering if it's safe for me to give it to some people.
>> 
>> Anyone?  Note that this also fixes a real bug, so it might be of
>> interest to include it in the trunk.
>
> Through a quick glance, the patch looks OK to me.
> Could you give a proper subject and changelog to merge your patch
> to git tree?

Hi there Takashi, and sorry for the delay.  Here are the patch,
subdivised in two distinct logical changes.  I hope the format is what
you asked for.

	* usb_stream/pcm_usb_stream.c (snd_pcm_us_stop): Prevent
	dereferencing when structure is not initialized.

--- usb_stream/pcm_usb_stream.c	2009-12-16 10:18:55.000000000 -0500
+++ usb_stream/pcm_usb_stream.c	2010-01-23 10:19:09.032559296 -0500
@@ -1,7 +1,7 @@
 /*
  *  PCM - USB_STREAM plugin
  *
- *  Copyright (c) 2008 by Karsten Wiese <fzu@xxxxxxxxxxxxxxxxxxxxx>
+ *  Copyright (c) 2008, 2010 by Karsten Wiese <fzu@xxxxxxxxxxxxxxxxxxxxx>
  *
  * This library is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as
@@ -256,8 +256,11 @@
 static int snd_pcm_us_stop(snd_pcm_ioplug_t *io)
 {
 	snd_pcm_us_t *us = io->private_data;
-	VDBG("%u", us->uus->s->periods_done);
 
+	if (!us->uus->s)
+	  return 0;
+
+	VDBG("%u", us->uus->s->periods_done);
 	if (io->stream == SND_PCM_STREAM_PLAYBACK)
 		memset(us->uus->write_area, 0, us->uus->s->write_size);
 
	* usb_stream/pcm_usb_stream.c: Allow user-set period-size and
	rate.

--- usb_stream/pcm_usb_stream.c	2010-01-23 10:19:09.032559296 -0500
+++ usb_stream/pcm_usb_stream.c	2010-01-23 10:20:36.006628021 -0500
@@ -48,6 +48,8 @@
 #define VDBG(f, ...)
 #endif
 
+#define FRAME_SIZE 6
+
 #define LCARD 32
 struct user_usb_stream {
 	char			card[LCARD];
@@ -70,6 +72,8 @@
 	unsigned		periods_done;
 
 	unsigned 		channels;
+	snd_pcm_uframes_t	period_size;
+	unsigned int		rate;
 } snd_pcm_us_t;
 
 static struct user_usb_stream *uus;
@@ -177,7 +181,7 @@
 	VDBG("");
 
 	us_cfg.version = USB_STREAM_INTERFACE_VERSION;
-	us_cfg.frame_size = 6;
+	us_cfg.frame_size = FRAME_SIZE;
 	us_cfg.sample_rate = io->rate;
 	us_cfg.period_frames = io->period_size;
 
@@ -373,6 +377,10 @@
 	};
 
 	int err;
+	unsigned int rate_min = us->rate ? us->rate : 44100,
+		rate_max = us->rate ? us->rate : 96000,
+		period_bytes_min = us->period_size ? FRAME_SIZE * us->period_size : 128,
+		period_bytes_max = us->period_size ? FRAME_SIZE * us->period_size : 64*4096;
 
 	if ((err = snd_pcm_ioplug_set_param_list(&us->io, SND_PCM_IOPLUG_HW_ACCESS,
 						 ARRAY_SIZE(access_list), access_list)) < 0 ||
@@ -381,9 +389,9 @@
 	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_CHANNELS,
 						   us->channels, us->channels)) < 0 ||
 	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_RATE,
-						   44100, 96000)) < 0 ||
+						   rate_min, rate_max)) < 0 ||
 	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
-						   128, 64*4096)) < 0 ||
+						   period_bytes_min, period_bytes_max)) < 0 ||
 	    (err = snd_pcm_ioplug_set_param_minmax(&us->io, SND_PCM_IOPLUG_HW_PERIODS,
 						   2, 2)) < 0)
 		return err;
@@ -393,7 +401,9 @@
 
 static int snd_pcm_us_open(snd_pcm_t **pcmp, const char *name,
 				   const char *card,
-				   snd_pcm_stream_t stream, int mode)
+				   snd_pcm_stream_t stream, int mode,
+				   snd_pcm_uframes_t period_size,
+				   unsigned int rate)
 {
 	snd_pcm_us_t *us;
 	int err;
@@ -424,6 +434,8 @@
 	snd_hwdep_poll_descriptors(us->hwdep, &us->pfd, 1);
 
 	us->channels = 2;
+	us->period_size = period_size;
+	us->rate = rate;
 
 	us->io.version = SND_PCM_IOPLUG_VERSION;
 	us->io.name = "ALSA <-> USB_STREAM PCM I/O Plugin";
@@ -458,6 +470,7 @@
 	snd_config_iterator_t i, next;
 	const char *card;
 	int err;
+	long period_size = 0, rate = 0;
 
 	snd_config_for_each(i, next, conf) {
 		snd_config_t *n = snd_config_iterator_entry(i);
@@ -475,11 +488,27 @@
 			snd_config_get_string(n, &card);
 			continue;
 		}
+		if (strcmp(id, "period_size") == 0) {
+			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
+				SNDERR("Invalid type for %s", id);
+				return -EINVAL;
+			}
+			snd_config_get_integer(n, &period_size);
+			continue;
+		}
+		if (strcmp(id, "rate") == 0) {
+			if (snd_config_get_type(n) != SND_CONFIG_TYPE_INTEGER) {
+				SNDERR("Invalid type for %s", id);
+				return -EINVAL;
+			}
+			snd_config_get_integer(n, &rate);
+			continue;
+		}
 		SNDERR("Unknown field %s", id);
 		return -EINVAL;
 	}
 
-	err = snd_pcm_us_open(pcmp, name, card, stream, mode);
+	err = snd_pcm_us_open(pcmp, name, card, stream, mode, period_size, rate);
 
 	return err;
 }
  I can write the according documentation, if needed.

  Have a great day.

-- 
Michaël `Micha' Cadilhac (LITQ, U. de Montréal) -- http://michael.cadilhac.name
	||   This .sig has been generated by Outlook Express 98
	||        $@(%@#%$*@(#)%$!%)(%$#(@#$%**!@#$+!#?%
	||  and triple-checked on Windows Mail Vista.
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux