ALSA PCM中间层,非常强大,驱动只需要实现底层的函数以访问硬件 浅追一下录放音流程 kernel/sound/core/pcm_native.c const struct file_operations snd_pcm_f_ops[2] = { { .owner = THIS_MODULE, .write = snd_pcm_write, .write_iter = snd_pcm_writev, .open = snd_pcm_playback_open, .release = snd_pcm_release, .llseek = no_llseek, .poll = snd_pcm_poll, .unlocked_ioctl = snd_pcm_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, .read_iter = snd_pcm_readv, .open = snd_pcm_capture_open, .release = snd_pcm_release, .llseek = no_llseek, .poll = snd_pcm_poll, .unlocked_ioctl = snd_pcm_ioctl, .compat_ioctl = snd_pcm_ioctl_compat, .mmap = snd_pcm_mmap, .fasync = snd_pcm_fasync, .get_unmapped_area = snd_pcm_get_unmapped_area, } }; 其中snd_pcm_f_ops[0]是播放,snd_pcm_f_ops[1]是录音 播放: .open-->snd_pcm_playback_open-->snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK) 录音: .open-->snd_pcm_capture_open-->snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE)
snd_pcm_open的原型static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)可以看到就是通过传入的int stream来区分录放音的,也就是说录放音的具体处理都是从此处开始 snd_card_file_add(pcm->card, file) //这个函数将打开的文件保存,放入snd_card的files_list链表。作用是用于跟踪连接状态,避免热插拔释放繁忙资源。 snd_pcm_open_file(file, pcm, stream) //将操作该声卡card的应用程序添加到card->files_list snd_pcm_open_file-->snd_pcm_open_substream-->snd_pcm_attach_substream //获取snd_pcm_substream数据 snd_pcm_open_file-->snd_pcm_attach_substream-->pstr = &pcm->streams[stream] //得到播放/录音的snd_pcm_str snd_pcm_open_file-->snd_pcm_open_substream-->snd_pcm_hw_constraints_init(substream); //初始化substream结构体 snd_pcm_open_file-->snd_pcm_open_substream-->snd_pcm_hw_constraints_complete(substream); //重新设置SNDRV_PCM_HW_PARAM_ACCESS,SNDRV_PCM_HW_PARAM_FORMAT,等参数、最小/大值区间,设置到runtime.hw_constraints.rules里面去 |
|小黑屋|
飞凌嵌入式
( 冀ICP备12004394号-1 )
GMT+8, 2025-3-24 13:36
Powered by Discuz! X3.4
© 2001-2013 Comsenz Inc.