我尝试遵循从Linux用户空间(arecord / aplay)到内核驱动程序的参数设置路径。让我们以记录--period-size为例。
这一切都始于set_params
的{{1}}函数:
aplay.c
在{pcm.c:5186](alsa-lib https://github.com/alsa-project/alsa-lib/blob/master/src/pcm/pcm.c#L5186)中定义了函数if (period_time > 0)
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);
else
err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_frames, 0);
,这让我头疼。对我来说没有多大意义,而且似乎也不会导致驱动程序终止。
有snd_pcm_hw_params_set_period_size_near()
标签,所以我跳过了所有类似_end
或snd_pcm_hw_param_set_min()
的呼叫,而去了snd_pcm_hw_param_set_max()
,希望调用一些驱动程序,例如:
snd_pcm_hw_param_set_last()
但是相反,我找到了结束呼叫:
drv->hw_params_set(...);
其中返回值应为参数集。
因此,总而言之,我发现alsa-lib很难阅读和理解。也许我缺少一些知识。我的问题很简单,如何将用户空间参数传递给内核驱动程序。您可以提供显示称为的接口的软件路径吗?
谢谢。
答案 0 :(得分:1)
hw_params
结构包含一个配置空间,该空间描述了设备可以支持的所有可能的配置。数字参数描述为间隔(即最小和最大),访问和格式描述为位掩码。
更改一个参数时,库将调用内核驱动程序(SNDRV_PCM_IOCTL_HW_REFINE
)来调整hw_params
结构中依赖于已更改参数的所有其他参数。
在将配置空间减少到实际所需的配置之后,请调用snd_pcm_hw_params()
(→SNDRV_PCM_IOCTL_HW_PARAMS
)为这些参数实际配置设备。 (如果某些参数未减小为单个值,则snd_pcm_hw_params()
将选择一个随机值。)
snd_pcm_hw_params_set_xxx_near()
更复杂,因为没有SET_NEAR
ioctl。此功能尝试调整间隔,以使其最大值或最小值为所需的值,然后检查实际的最大值或最小值是否更接近。
例如,假设设备支持的周期大小为1024、2048、4096和8192帧。最初,间隔描述为[1024,8192]。当您调用snd_pcm_hw_params_set_period_size_near(4000)
时,snd_pcm_hw_param_set_near()
帮助函数将调用set_min(4000)
和set_max(4000)
(在hw_params
结构的单独副本上),因此间隔为[1024, 4000]和[4000,8192];精炼后,驱动程序返回间隔[1024,2048]和[4096,8192]。 snd_pcm_hw_param_set_near()
然后看到4096最接近所需的卡路里,因此它在第二个间隔调用set_first
,结果为[4096,4096]。