Skip to content

Commit

Permalink
[ALSA] usbaudio - Fix Oops with unconventional sample rates
Browse files Browse the repository at this point in the history
The patch fixes the memory corruption by the support of unconventional
sample rates.  Also, it avoids the too restrictive constraints if
any of usb descriptions contain continuous rates.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Feb 9, 2007
1 parent 3b6baa5 commit 8fec560
Showing 1 changed file with 26 additions and 19 deletions.
45 changes: 26 additions & 19 deletions sound/usb/usbaudio.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ struct snd_usb_substream {
u64 formats; /* format bitmasks (all or'ed) */
unsigned int num_formats; /* number of supported audio formats (list) */
struct list_head fmt_list; /* format list */
struct snd_pcm_hw_constraint_list rate_list; /* limited rates */
spinlock_t lock;

struct snd_urb_ops ops; /* callbacks (must be filled at init) */
Expand Down Expand Up @@ -1818,28 +1819,33 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs)
{
struct list_head *p;
struct snd_pcm_hw_constraint_list constraints_rates;
struct audioformat *fp;
int count = 0, needs_knot = 0;
int err;

list_for_each(p, &subs->fmt_list) {
struct audioformat *fp;
fp = list_entry(p, struct audioformat, list);

if (!fp->needs_knot)
continue;

constraints_rates.count = fp->nr_rates;
constraints_rates.list = fp->rate_table;
constraints_rates.mask = 0;

err = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_rates);

if (err < 0)
return err;
list_for_each_entry(fp, &subs->fmt_list, list) {
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
count += fp->nr_rates;
if (fp->needs_knot)
needs_knot = 1;
}
if (!needs_knot)
return 0;

subs->rate_list.count = count;
subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
subs->rate_list.mask = 0;
count = 0;
list_for_each_entry(fp, &subs->fmt_list, list) {
int i;
for (i = 0; i < fp->nr_rates; i++)
subs->rate_list.list[count++] = fp->rate_table[i];
}
err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&subs->rate_list);
if (err < 0)
return err;

return 0;
}
Expand Down Expand Up @@ -2238,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs)
kfree(fp->rate_table);
kfree(fp);
}
kfree(subs->rate_list.list);
}


Expand Down

0 comments on commit 8fec560

Please sign in to comment.