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记录整个过程后分析的,目前我们还没有时间去分析梳理,这里仅仅先记录起来。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值