提交 8fec560d 编写于 作者: T Takashi Iwai 提交者: Jaroslav Kysela

[ALSA] usbaudio - Fix Oops with unconventional sample rates

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: NTakashi Iwai <tiwai@suse.de>
Signed-off-by: NJaroslav Kysela <perex@suse.cz>
上级 3b6baa5a
...@@ -186,6 +186,7 @@ struct snd_usb_substream { ...@@ -186,6 +186,7 @@ struct snd_usb_substream {
u64 formats; /* format bitmasks (all or'ed) */ u64 formats; /* format bitmasks (all or'ed) */
unsigned int num_formats; /* number of supported audio formats (list) */ unsigned int num_formats; /* number of supported audio formats (list) */
struct list_head fmt_list; /* format list */ struct list_head fmt_list; /* format list */
struct snd_pcm_hw_constraint_list rate_list; /* limited rates */
spinlock_t lock; spinlock_t lock;
struct snd_urb_ops ops; /* callbacks (must be filled at init) */ struct snd_urb_ops ops; /* callbacks (must be filled at init) */
...@@ -1818,28 +1819,33 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) ...@@ -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, static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs) struct snd_usb_substream *subs)
{ {
struct list_head *p; struct audioformat *fp;
struct snd_pcm_hw_constraint_list constraints_rates; int count = 0, needs_knot = 0;
int err; int err;
list_for_each(p, &subs->fmt_list) { list_for_each_entry(fp, &subs->fmt_list, list) {
struct audioformat *fp; if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
fp = list_entry(p, struct audioformat, list); return 0;
count += fp->nr_rates;
if (!fp->needs_knot) if (fp->needs_knot)
continue; needs_knot = 1;
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;
} }
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; return 0;
} }
...@@ -2238,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs) ...@@ -2238,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs)
kfree(fp->rate_table); kfree(fp->rate_table);
kfree(fp); kfree(fp);
} }
kfree(subs->rate_list.list);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册