linux - 将参数从 alsa 应用程序传递到内核驱动程序

标签 linux kernel driver alsa

我尝试遵循从 linux 用户空间 (arecord/aplay) 到内核驱动程序的参数设置路径。我们以 arecords --period-size 为例。

这一切都始于 aplay.c 中的 set_params 函数:

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() 定义在 [pcm.c : 5186](alsa-lib https://github.com/alsa-project/alsa-lib/blob/master/src/pcm/pcm.c#L5186 ) 中,我开始头疼了……这个函数开始了一系列调用其他功能对我来说没有多大意义,似乎不会导致驱动程序的任何结束调用。

_end 标签,所以我跳过了所有调用,例如 snd_pcm_hw_param_set_min()snd_pcm_hw_param_set_max() 并转到了 snd_pcm_hw_param_set_last() 希望有一些驱动程序调用,例如:

drv->hw_params_set(...);

但是我发现了一个结束调用:

MASK_INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
{
    int i;
    assert(!snd_mask_empty(mask));
    for (i = 0; i < MASK_SIZE; i++) {
        if (mask->bits[i])
            return ffs(mask->bits[i]) - 1 + (i << 5);
    }
    return 0;
}

其中返回值应为参数集。

总而言之,我发现 alsa-lib 很难阅读和理解。也许我缺乏一些知识。我的问题很简单,用户空间参数如何传递给内核驱动程序。你能提供一个软件路径显示调用的接口(interface)吗?

谢谢。

最佳答案

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]。

关于linux - 将参数从 alsa 应用程序传递到内核驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56318054/

相关文章:

linux - dpkg-dep 错误 : paste subprocess was killed by signal(Broken Pipe) Ubuntu WSL2

Chardevice 主设备号释放

linux - 为什么这个内核模块在 2.6.39 上标记为永久

linux - 如何在ubuntu 13.04中安装Huawei Modem E303C的驱动?

printing - Canon 打印机驱动程序生成的 Postscript 中出现意外的二进制序列

linux bash,用破折号分隔的驼峰式字符串

linux - 如何在 OpenWRT 上启动 Snort?

linux - 内核模式——物理地址还是虚拟地址?

python - 在 Python 上使用 OpenCV 选择最佳 SVM 内核类型和参数

java - 有没有更简单的方法将 mysql 驱动程序加载到类路径?