if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk("%s = ", snd_pcm_hw_param_names[k]);
+ printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
#endif
changed = snd_mask_refine(m, constrs_mask(constrs, k));
if (!(params->rmask & (1 << k)))
continue;
#ifdef RULES_DEBUG
- printk("%s = ", snd_pcm_hw_param_names[k]);
+ printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
if (i->empty)
printk("empty");
else
if (!doit)
continue;
#ifdef RULES_DEBUG
- printk("Rule %d [%p]: ", k, r->func);
+ printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
if (r->var >= 0) {
printk("%s = ", snd_pcm_hw_param_names[r->var]);
if (hw_is_mask(r->var)) {
struct snd_pcm_hw_params *params;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(params, _params, sizeof(*params))) {
- err = -EFAULT;
- goto out;
- }
+ params = memdup_user(_params, sizeof(*params));
+ if (IS_ERR(params))
+ return PTR_ERR(params);
+
err = snd_pcm_hw_refine(substream, params);
if (copy_to_user(_params, params, sizeof(*params))) {
if (!err)
err = -EFAULT;
}
-out:
+
kfree(params);
return err;
}
struct snd_pcm_hw_params *params;
int err;
- params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(params, _params, sizeof(*params))) {
- err = -EFAULT;
- goto out;
- }
+ params = memdup_user(_params, sizeof(*params));
+ if (IS_ERR(params))
+ return PTR_ERR(params);
+
err = snd_pcm_hw_params(substream, params);
if (copy_to_user(_params, params, sizeof(*params))) {
if (!err)
err = -EFAULT;
}
-out:
+
kfree(params);
return err;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
status->avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
- runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
status->delay = runtime->buffer_size - status->avail;
- else
+ status->delay += runtime->delay;
+ } else
status->delay = 0;
} else {
status->avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- status->delay = status->avail;
+ status->delay = status->avail + runtime->delay;
else
status->delay = 0;
}
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
+ runtime->hw_ptr_jiffies = jiffies;
runtime->status->state = state;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
};
/**
- * snd_pcm_start
+ * snd_pcm_start - start all linked streams
* @substream: the PCM substream instance
- *
- * Start all linked streams.
*/
int snd_pcm_start(struct snd_pcm_substream *substream)
{
};
/**
- * snd_pcm_stop
+ * snd_pcm_stop - try to stop all running streams in the substream group
* @substream: the PCM substream instance
* @state: PCM state after stopping the stream
*
- * Try to stop all running streams in the substream group.
- * The state of each stream is changed to the given value after that unconditionally.
+ * The state of each stream is then changed to the given state unconditionally.
*/
int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
{
EXPORT_SYMBOL(snd_pcm_stop);
/**
- * snd_pcm_drain_done
+ * snd_pcm_drain_done - stop the DMA only when the given stream is playback
* @substream: the PCM substream
*
- * Stop the DMA only when the given stream is playback.
- * The state is changed to SETUP.
+ * After stopping, the state is changed to SETUP.
* Unlike snd_pcm_stop(), this affects only the given stream.
*/
int snd_pcm_drain_done(struct snd_pcm_substream *substream)
{
if (substream->runtime->trigger_master != substream)
return 0;
+ /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
+ * a delta betwen the current jiffies, this gives a large enough
+ * delta, effectively to skip the check once.
+ */
+ substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
return substream->ops->trigger(substream,
push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
};
/**
- * snd_pcm_suspend
+ * snd_pcm_suspend - trigger SUSPEND to all linked streams
* @substream: the PCM substream
*
- * Trigger SUSPEND to all linked streams.
* After this call, all streams are changed to SUSPENDED state.
*/
int snd_pcm_suspend(struct snd_pcm_substream *substream)
EXPORT_SYMBOL(snd_pcm_suspend);
/**
- * snd_pcm_suspend_all
+ * snd_pcm_suspend_all - trigger SUSPEND to all substreams in the given pcm
* @pcm: the PCM instance
*
- * Trigger SUSPEND to all substreams in the given pcm.
* After this call, all streams are changed to SUSPENDED state.
*/
int snd_pcm_suspend_all(struct snd_pcm *pcm)
};
/**
- * snd_pcm_prepare
+ * snd_pcm_prepare - prepare the PCM substream to be triggerable
* @substream: the PCM substream instance
* @file: file to refer f_flags
- *
- * Prepare the PCM substream to be triggerable.
*/
static int snd_pcm_prepare(struct snd_pcm_substream *substream,
struct file *file)
if (snd_BUG_ON(!substream))
return -ENXIO;
pcm = substream->pcm;
- fasync_helper(-1, file, 0, &substream->runtime->fasync);
mutex_lock(&pcm->open_mutex);
snd_pcm_release_substream(substream);
kfree(pcm_file);
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
+ n += runtime->delay;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
- bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
- kfree(bufs);
- return -EFAULT;
- }
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
return -EFAULT;
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
return -EFAULT;
- bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
- if (bufs == NULL)
- return -ENOMEM;
- if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
- kfree(bufs);
- return -EFAULT;
- }
+
+ bufs = memdup_user(xfern.bufs,
+ sizeof(void *) * runtime->channels);
+ if (IS_ERR(bufs))
+ return PTR_ERR(bufs);
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
__put_user(result, &_xfern->result);
err = fasync_helper(fd, file, on, &runtime->fasync);
out:
unlock_kernel();
- if (err < 0)
- return err;
- return 0;
+ return err;
}
/*
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
- if (!oparams) {
- err = -ENOMEM;
- goto out;
- }
+ if (!params)
+ return -ENOMEM;
- if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
- err = -EFAULT;
+ oparams = memdup_user(_oparams, sizeof(*oparams));
+ if (IS_ERR(oparams)) {
+ err = PTR_ERR(oparams);
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams);
if (!err)
err = -EFAULT;
}
+
+ kfree(oparams);
out:
kfree(params);
- kfree(oparams);
return err;
}
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
- if (!params) {
- err = -ENOMEM;
- goto out;
- }
- oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
- if (!oparams) {
- err = -ENOMEM;
- goto out;
- }
- if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
- err = -EFAULT;
+ if (!params)
+ return -ENOMEM;
+
+ oparams = memdup_user(_oparams, sizeof(*oparams));
+ if (IS_ERR(oparams)) {
+ err = PTR_ERR(oparams);
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams);
if (!err)
err = -EFAULT;
}
+
+ kfree(oparams);
out:
kfree(params);
- kfree(oparams);
return err;
}
#endif /* CONFIG_SND_SUPPORT_OLD_API */
+#ifndef CONFIG_MMU
+unsigned long dummy_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return 0;
+}
+#else
+# define dummy_get_unmapped_area NULL
+#endif
+
/*
* Register section
*/
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
+ .get_unmapped_area = dummy_get_unmapped_area,
},
{
.owner = THIS_MODULE,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
+ .get_unmapped_area = dummy_get_unmapped_area,
}
};