ALSA架构应用程序aplay及amixer调用关系(应用层到内核驱动)

ALSA架构应用程序aplay及amixer调用关系(应用层到内核驱动)ALSA架构应用程序aplay及amixer调用关系(应用层到内核驱动)

一、整体架构

	   +--------+  +--------+  +--------+
	   |apaly   |  |arecord |  |amixer  |
	   +--------+  +--------+  +--------+
	      |            ^            ^
	      V            |            V
	   +--------------------------------+
	   |        ALSA Library API        |
	   |      (tinyalsa, alsa-lib)      |
	   +--------------------------------+
 user space           ^
----------------------|---------------------
 kernel space         V
       +--------------------------------+
       |            ALSA CORE           |
       | +-------+ +-------+ +------+   |
       | | PCM   | |CONTROL| | MIDI |...|
       | +-------+ +-------+ +------+   |
       +--------------------------------+
                       |
       +--------------------------------+
       |            ASoC CORE           |
       +--------------------------------+
                       |
       +--------------------------------+
       |        hardware driver         |
       | +-------+ +--------+ +-----+   |
       | |Machine| |Platform| |Codec|   |
       | +-------+ +--------+ +-----+   |
       +--------------------------------+ 
+------------------------------------------+
|                 Machine                  |
| +--------------+      +--------------+   |
| |  Platform    |      |   Codec      |   |
| |              | I2S  |              |   |
| |       cpu_dai|<---->|codec_dai     |   |
| |              |      |              |   |
| +--------------+      +--------------+   |
+------------------------------------------+ 
        copy_from_user           DMA                 I2S           DAC
              ^                   ^                   ^             ^
+---------+   |    +----------+   |   +-----------+   |   +-----+   |   +------+
|userspace+-------->DMA Buffer+------->I2S TX FIFO+------->CODEC+------->SPK/HP|
+---------+        +----------+       +-----------+       +-----+       +------+

aplay.c涉及alsa-lib及alsa-utils源码下载地址:
alsa-lib 1.2.6源码
alsa-utils 1.2.6源码

二、使用aplay指令调用关系

strace分析: aplay Windows.wav

1. /dev/snd/controlC0 对应的file_operations是snd_ctl_f_ops
open : snd_ctl_open
SNDRV_CTL_IOCTL_PVERSION : snd_ctl_ioctl -> put_user(SNDRV_CTL_VERSION, ip) 
SNDRV_CTL_IOCTL_CARD_INFO : snd_ctl_ioctl -> snd_ctl_card_info(card, ctl, cmd, argp);
                                               copy_to_user
                                               
SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE : snd_ctl_ioctl -> snd_pcm_control_ioctl -> control->prefer_pcm_subdevice = val;
close
上述三个ioctl不涉及硬件操作

2. /dev/snd/pcmC0D0p 对应的file_operations是snd_pcm_f_ops[0]
open :  snd_pcm_playback_open
           snd_pcm_open
              snd_pcm_open_file
              	struct snd_pcm_substream *substream;
              	snd_pcm_open_substream
              		err = snd_pcm_hw_constraints_init(substream);
              					snd_mask_any
              					snd_interval_any
              					......
              		err = substream->ops->open(substream) // substream->ops : snd_pcm_ops结构体
              						soc_pcm_open
              							依次调用cpu_dai, dma, codec_dai, machine的open或startup函数
              									uda134x_startup 里:snd_pcm_hw_constraint_minmax(SNDRV_PCM_HW_PARAM_RATE),snd_pcm_hw_constraint_minmax(SNDRV_PCM_HW_PARAM_SAMPLE_BITS)
              									dma_open里: snd_pcm_hw_constraint_integer,snd_soc_set_runtime_hwparams
              									            runtime->hw.info = hw->info; = SNDRV_PCM_INFO_INTERLEAVED |
																						    SNDRV_PCM_INFO_BLOCK_TRANSFER |
																						    SNDRV_PCM_INFO_MMAP |
																						    SNDRV_PCM_INFO_MMAP_VALID |
																						    SNDRV_PCM_INFO_PAUSE |
																						    SNDRV_PCM_INFO_RESUME,
              		snd_pcm_hw_constraints_complete
              	pcm_file->substream = substream;
              	file->private_data = pcm_file;

注意:substream->ops =  soc_new_pcm函数里的soc_pcm_ops

以下的ioctl入口都是:snd_pcm_playback_ioctl              	
SNDRV_PCM_IOCTL_INFO : snd_pcm_info_user(substream, arg);
							substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
							  snd_pcm_lib_ioctl
														  	
SNDRV_PCM_IOCTL_PVERSION : put_user(SNDRV_PCM_VERSION, (int __user *)arg)
SNDRV_PCM_IOCTL_TTSTAMP  : snd_pcm_tstamp(substream, arg);
                              
SNDRV_PCM_IOCTL_SYNC_PTR : snd_pcm_sync_ptr(substream, arg); 先不管

SNDRV_PCM_IOCTL_HW_REFINE ....snd_pcm_hw_refine_user(substream, arg);
                                    memdup_user
                                    snd_pcm_hw_refine(substream, params); 先不管
                                    copy_to_user
SNDRV_PCM_IOCTL_HW_PARAMS : snd_pcm_hw_params_user(substream, arg);
                               snd_pcm_hw_params
                                  substream->ops->hw_params(substream, params);
                                     soc_pcm_hw_params
                                     	依次调用machine,codec_dai,cpu_dai,platform(dma)的hw_params函数
SNDRV_PCM_IOCTL_SYNC_PTR 
SNDRV_PCM_IOCTL_SW_PARAMS : snd_pcm_sw_params_user(substream, arg);
                               snd_pcm_sw_params 不涉及硬件操作
                                  
SNDRV_PCM_IOCTL_SYNC_PTR
SNDRV_PCM_IOCTL_PREPARE  : snd_pcm_prepare(substream, file);
                               snd_power_wait // 电源管理相关,先不管
                               .... 调用到platform里的prepare
                                  
SNDRV_PCM_IOCTL_SYNC_PTR
SNDRV_PCM_IOCTL_SW_PARAMS

循环:
SNDRV_PCM_IOCTL_WRITEI_FRAMES : copy_from_user
                                snd_pcm_lib_write
                                		snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_write_transfer)
                                				snd_pcm_lib_write_transfer
                                						copy_from_user
                                						snd_pcm_start(substream);  // 启动传输
                                						
 
SNDRV_PCM_IOCTL_SYNC_PTR

SNDRV_PCM_IOCTL_DRAIN
SNDRV_PCM_IOCTL_DROP
SNDRV_PCM_IOCTL_HW_FREE
close

三、strace分析: amixer cset numid=1 30 (设置音量)

/dev/snd/controlC0
open
SNDRV_CTL_IOCTL_CARD_INFO
SNDRV_CTL_IOCTL_PVERSION
SNDRV_CTL_IOCTL_ELEM_INFO
SNDRV_CTL_IOCTL_ELEM_READ
SNDRV_CTL_IOCTL_ELEM_WRITE : snd_ctl_elem_write_user
									snd_ctl_elem_write
										// 找到一个snd_kcontrol
										kctl = snd_ctl_find_id(card, &control->id);
										// 调用它的put
										result = kctl->put(kctl, control);

上面是从其他地方找的一份关于aplay和amixer调用后使用strace记录整个过程后分析的,目前我们还没有时间去分析梳理,这里仅仅先记录起来。

今天的文章ALSA架构应用程序aplay及amixer调用关系(应用层到内核驱动)分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/11600.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注