我目前正在开发一个Rust库/CLI/UI,用于管理Focusrite Scarlett个USB音频设备specifically on Linux.这些设备通常有many种不同的内部设置(我的18i8有近300个单独的控制),所以我试图在我的设计中考虑所有这些设置,以便用户可以轻松地更改布线配置、输入/输出/混合增益、静音切换等.
值得庆幸的是,Linux已经通过一些modProbe配置和最新的内核支持这些设备:
/etc/modprobe.d/scarlett.conf:
options snd_usb_audio vid=0x1235 pid=0x8214 device_setup=1
对于不同型号和可能不同的主要硬件版本,需要将上述值设置为不同的USB产品ID,以启用对这些设备的支持.
我一直在研究ALSA API,现在感觉已经weeks了,我学到了相当多:
- 有人用C语言编写了a GTK4 UI个用于管理Scarlett设备的代码,我基本上已经阅读了整个代码库,尽管有这么多困难,我仍然能够弄清楚它到底在做什么/正在使用哪些ALSA API.
- ALSA文档is abysmal at best,所以在这个项目之后,我将 compose 博客文章描述我的痛苦,解释其中的微妙之处,并试图回馈ALSA文档,以挽救其他人几天/几周/几个月的生命试图弄清楚这些事情.
- ALSA用户空间库通常是simply typedefs of syscalls to the kernel,这意味着对于像
snd_ctl_t
、snd_hctl_t
和snd_mixer_t
API这样的东西,用户空间中基本上没有代码.所有 struct 都是不透明的,函数(Syscall)与这些 struct 引用一起使用以获取详细信息.内核使用内存变魔术,并将其提供给用户空间. - 谢天谢地,一个勇敢而慷慨的灵魂移植了ALSA API to Rust的大部分.我还将为这个项目贡献文件,以帮助其他人在他们的道路上.
无论如何,我的困境是这样的:我可以列出ALSA设备并迭代它们,通过snd_ctl_card_info_t
我可以获得一些有用的属性,比如:
-
name
:转换器18i8 USB -
id
:USB -
longname
:Focusite Scarlett 18i8 USB,USB-0000:00:14.0-2.2,高速 -
mixername
:USB混音器 -
components
:USB1235:8214 -
driver
:USB音频
然而,这似乎是我可以从可用的API中获得的most个API.我可以通过从components
字段中的USB供应商/产品ID中提取型号类型,并且可以通过解析longname
找到实际的USB句柄,但是:
- 可能有多个连接相同USB供应商/产品ID的设备:这是将设备链接在一起以添加输入/输出的常见技术.
- 我关心的是提取
usb-*
插件的stability和USB供应商/产品ID,也许这可能会随着内核版本的不同而改变并变得无效. - 我需要identify个设备,希望有某种序列号,这样卡A(18i8)的配置就不会不经意地应用到卡B(18i8),我假设有某种类型的USB设备字段,其中包含每个设备的序列号.
因此,is there a Linux API which will allow me to get a USB device file from an ALSA handle of some kind?或者,我是否可能遗漏了什么,从而允许从ALSA API中获取序列号?
EDIT:我可以通过lsusb
找到序列号,字段名是iSerial
:
$ sudo lsusb -d 1235:8214 -vv | grep iSerial
iSerial 2 4K1A0P443EPEW7
我似乎确实需要达到root
才能获得实际的字段值,但我可能可以通过在udev
条规则中向我的用户授予对设备的权限来解决这个问题.如果我只能从ALSA API获得稳定的USB设备路径,那么我可以使用libusb
或其他API来提取iSerial
字段.