前些日子写了一篇snd_kcontrol探究,该文主要从内核源码出发简单讲述一下kcontrol接口的始末。这几天因为要在Android里面添加一些音频控制接口,配合alsa_amixer scontents分析,对此有了更深的体会,记录于此。因为这方面的资料实在太少,很多东西都是自我理解的,如有错误请见谅并指出。
name字段是名称标识,这个字段非常重要,因为kcontrol的作用由名称来区分,对于名称相同的kcontrol,则使用index区分。name定义的标准是“SOURCE DIRECTION FUNCTION”即“源 方向 功能”,SOURCE定义了kcontrol的源,如“Master”、“PCM”等;DIRECTION 则为“Playback”、“Capture”等,如果DIRECTION忽略,意味着Playback和capture双向;FUNCTION则可以是“Switch”、“Volume”和“Route”等。
以上的说法比较简略,下面会较详细补充一下。
先内核源码中的文档ControlNames.txt:
- This document describes standard names of mixer controls.
- Syntax: SOURCE [DIRECTION] FUNCTION
- DIRECTION:
- <nothing> (both directions)
- Playback
- Capture
- Bypass Playback
- Bypass Capture
- FUNCTION:
- Switch (on/off switch)
- Volume
- Route (route control, hardware specific)
- SOURCE:
- Master
- Master Mono
- Hardware Master
- Headphone
- PC Speaker
- Phone
- Phone Input
- Phone Output
- Synth
- FM
- Mic
- Line
- CD
- Video
- Zoom Video
- Aux
- PCM
- PCM Front
- PCM Rear
- PCM Pan
- Loopback
- Analog Loopback (D/A -> A/D loopback)
- Digital Loopback (playback -> capture loopback - without analog path)
- Mono
- Mono Output
- Multi
- ADC
- Wave
- Music
- I2S
- IEC958
- Exceptions:
- [Digital] Capture Source
- [Digital] Capture Switch (aka input gain switch)
- [Digital] Capture Volume (aka input gain volume)
- [Digital] Playback Switch (aka output gain switch)
- [Digital] Playback Volume (aka output gain volume)
- Tone Control - Switch
- Tone Control - Bass
- Tone Control - Treble
- 3D Control - Switch
- 3D Control - Center
- 3D Control - Depth
- 3D Control - Wide
- 3D Control - Space
- 3D Control - Level
- Mic Boost [(?dB)]
- PCM interface:
- Sample Clock Source { "Word", "Internal", "AutoSync" }
- Clock Sync Status { "Lock", "Sync", "No Lock" }
- External Rate /* external capture rate */
- Capture Rate /* capture rate taken from external source */
- IEC958 (S/PDIF) interface:
- IEC958 [...] [Playback|Capture] Switch /* turn on/off the IEC958 interface */
- IEC958 [...] [Playback|Capture] Volume /* digital volume control */
- IEC958 [...] [Playback|Capture] Default /* default or global value - read/write */
- IEC958 [...] [Playback|Capture] Mask /* consumer and professional mask */
- IEC958 [...] [Playback|Capture] Con Mask /* consumer mask */
- IEC958 [...] [Playback|Capture] Pro Mask /* professional mask */
- IEC958 [...] [Playback|Capture] PCM Stream /* the settings assigned to a PCM stream */
- IEC958 Q-subcode [Playback|Capture] Default /* Q-subcode bits */
- IEC958 Preamble [Playback|Capture] Default /* burst preamble words (4*16bits) */
可以看到表示方向DIRECTION有五种,其中DIRECTION为空时则表示Playback、Capture双向。
一个标准的kcontrol如:SOC_DOUBLE("PCM Playback Volume", AC97_PHONE, 8, 0, 31, 1),其中“PCM”为源SOURCE、“Playback”为方向DIRECTION、“Volume”为功能FUNCTION--音量调节,这个kcontrol是调节放音PCM的Volume的。
又如:SOC_SINGLE("Mic Switch", AC97_CD, 15, 1, 1),其中“Mic”为源SOURCE、方向DIRECTION为空表示Playback和Capture双向、“Switch”为功能FUNCTION--开关切换,这个kcontrol是用于切换Mic开关的。
实际应用中,并不是所有的kcontrol命名都符合ControlNames.txt规则。如:SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),这个kcontrol的name只有名为“ALC Hold Time”的SOURCE字段,DIRECTION和FUNCTION都欠缺。
alsa_amixer命令可以输出这些kcontrol的名称、numid和当前值等信息。而选项sconctols/controls、scontents/contents、sset/cset、sget/cget有所不同,前者是mixer simple control信息,后者是control信息;前者的handle通过snd_mixer_open取得,后者的handle通过snd_ctl_open取得。
两个kcontrol:1、SOC_SINGLE("Capture Switch", AC97_CD, 15, 1, 1), 2、SOC_DOUBLE("Capture Volume", AC97_CD, 8, 0, 31, 0):
在alsa_amixer scontrols来看,显示一个名称为“Capture”的mixer simple control,根据我的结果,一般这个mixer simple control对应的是后者。【猜测:之所以有这样的结果,是因为两个kcontrol的SOURCE名称相同,而mixer simple control是匹配kcontrol的SOURCE字段的;因此SOURCE字段区别体现在mixer simple control上,而name区别体现在control上,待验证。】
在alsa_amixer controls来看,列表会显示所有的kcontrol,因此会显示“Capture Switch”和“Capture Volume”这两个kcontrol。这不难理解,在snd_kcontrol探究中就提到,上层是根据name来找到底层的kcontrol的,这个name包含了SOURCE、DIRECTION和FUNCTION这三个字段。
【建议:编写snd_kcontrol时,尽量使用标准的ControlName,留意SOURCE字段是否有重复。在上层应用中,很多都是使用snd_mixer_open得到的mixer simple control,一个典型的例子就是Android2.2的AlsaMixer.cpp。之前我在为Android添加mic mute接口时,发现无论如何都找不到“Capture Switch”的kcontrol,因为它与“Capture Volume”的kcontrol的SOURCE字段重名了。将其改名为“Mic Switch”就行了。】
4/16 2011
找到一个alsa基本架构图