ALSA的Prepare流程
snd_pcm_prepare => snd_pcm_action_nonatomic => snd_pcm_action_group => snd_pcm_do_prepare =>
substream->ops->prepare =>soc_pcm_prepare =>rtd->dai_link->ops->prepare => platform->driver->ops->prepare
=>codec_dai->driver->ops->prepare => cpu_dai->driver->ops->prepare
int pcm_write(struct pcm *pcm, const void *data, unsigned int count)
{
struct snd_xferi x;
if (pcm->flags & PCM_IN)
return -EINVAL;
x.buf = (void*)data;
x.frames = count / (pcm->config.channels *
pcm_format_to_bits(pcm->config.format) / 8);
for (;;) {
if (!pcm->running) {
int prepare_error = pcm_prepare(pcm);//write之前先prepare
if (prepare_error)
return prepare_error;
if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
return oops(pcm, errno, "cannot write initial data");
pcm->running = 1;
return 0;
}
if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
pcm->prepared = 0;
pcm->running = 0;
if (errno == EPIPE) {
pcm->underruns++;
if (pcm->flags & PCM_NORESTART)
return -EPIPE;
continue;
}
return oops(pcm, errno, "cannot write stream data");
}
return 0;
}
}
// /external/tinyalsa/pcm.c,用户层通过ioctl的方式来调用kernel
int pcm_prepare(struct pcm *pcm)
{
if (pcm->prepared)
return 0;
if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0)
return oops(pcm, errno, "cannot prepare channel");
pcm->prepared = 1;
return 0;
}
// /kernel-3.18/sound/core/pcm_native.c,kernel层的实现
// 在内核中发起系统调用,执行本应用户空间发起调用的fops函数集,完成参数设置任务
/*const struct file_operations snd_pcm_f_ops[2] = {
{
.owner = THIS_MODULE,
.write = snd_pcm_write,
.aio_write = snd_pcm_aio_write,
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_playback_poll,
.unlocked_ioctl = snd_pcm_playback_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
.get_unmapped_area = snd_pcm_get_unmapped_area,
},
{
.owner = THIS_MODULE,
.read = snd_pcm_read,
.aio_read = snd_pcm_aio_read,
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_capture_poll,
.unlocked_ioctl = snd_pcm_capture_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
.fasync = snd_pcm_fasync,
.get_unmapped_area = snd_pcm_get_unmapped_area,
}
};*/
static long snd_pcm_playback_ioctl(struct file *file, unsigned