snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
printk(KERN_DEBUG "pcm_oss: write: "
"recovering from XRUN\n");
else
printk(KERN_DEBUG "pcm_oss: write: "
"recovering from SUSPEND\n");
#endif
ret = snd_pcm_oss_prepare(substream);// 调用snd_pcm_kernel_ioctl发送SNDRV_PCM_IOCTL_PREPARE
if (ret < 0) // 准备就绪,音频数据从现在开始可以操作了[luther.gliethttp]
break;
}
if (in_kernel) {
// get_fs()和set_fs()位于include/asm-generic/uaccess.h
mm_segment_t fs;
《浅析get_fs()和set_fs()设置user用户空间所能访问的最大虚拟地址》 fs = snd_enter_user(); // 设置fs的addr_limit最大可访问地址为0xffffffff,而非原来正常的0xc0000000, 应用程序所能访问的最大虚拟地址[luther.gliethttp]
ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
《浅析alsa声卡驱动snd_pcm_lib_write函数》 snd_leave_user(fs);
} else {
ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
《浅析alsa声卡驱动snd_pcm_lib_write函数》 }
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
/* has not been started */
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
return -EAGAIN;
}
return ret;
}
阅读(1669) | 评论(0) | 转发(0) |