我有一个基于 CH348 芯片的多端口 USB-UART 设备,运行来自https://github.com/WCHSoftGroup/ch9344ser_linux的内核外驱动程序
驱动程序创建 8 个字符的设备节点 ( /dev/ttyCH9344USB0
.. /dev/ttyCH9344USB7
)。该设备未在 USB 设备描述符中提供序列号,但我想从设备中读取一个 EEPROM,从中提取序列号并使用它来创建类似的符号链接/dev/ttyUSB.CH348.<serial_number>.<instance>
。
我创建了一个简单的udev
规则并将其放入/etc/udev/rules.d/99-usb-serial.rules
:
ACTION=="add", KERNEL=="*ttyCH9344USB*", OPTIONS="log_level=debug", PROGRAM="/usr/local/bin/ch34x_serial %E{DEVNAME}", SYMLINK+="ttyUSB.CH348.$result"
该规则确实按预期工作,但只适用于 8 个节点中的一个随机节点。我实际上尝试了多种不同的匹配规则,无论我使用哪种方法(内核名称、USB 属性等),如果匹配,它只会匹配该系列中的一个随机实例。它可能会为实例 3、6、7 或任何其他实例创建一个符号链接,但只针对一个实例。
我检查了journalctl
和udevadm monitor -p
,发现加载驱动程序模块时恰好有 8 个不同的add
事件发生udev
。除了 KERNEL、DEVPATH、SEQNUM 和 MINOR 属性外,所有事件都相同,如下所示:
KERNEL[706136.962119] add /devices/pci0000:00/0000:00:1d.0/usb1/1-1/1-1.1/1-1.1.3/1-1.1.3.2/1-1.1.3.2.1/1-1.1.3.2.1:1.0/tty/ttyCH9344USB0 (tty)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb1/1-1/1-1.1/1-1.1.3/1-1.1.3.2/1-1.1.3.2.1/1-1.1.3.2.1:1.0/tty/ttyCH9344USB0
SUBSYSTEM=tty
DEVNAME=/dev/ttyCH9344USB0
SEQNUM=26571
MAJOR=168
MINOR=0
我不明白为什么只有其中一个实际事件会触发规则,而如果我udevadm test
针对 8 个设备节点中的任何一个运行,则该规则对所有节点都有效。
它看起来像是udev
以某种方式缓存动作并丢弃“重复”的,虽然我不明白它是如何得出这个结论的。
我正在运行 Ubuntu 24.04 Serverudev
版本255.4-1ubuntu8.4
。
任何帮助都将不胜感激。谢谢。
事实证明,正如@meuh 在其评论中指出的那样,
udev
我的程序并行运行了ch34x_serial
8 次。显然,驱动程序不能容忍 EEPROM 访问操作。为了解决这个问题,我添加了一个基于共享信号量的简单同步,以序列化与底层 EEPROM 的通信。我想我可以修补 ch9344_linux 驱动程序,但修改用户空间程序似乎更容易。
任何需要解决将多个 CH348 设备连接到一台机器的相同问题的人都可以尝试使用https://codeberg.org/AlexanderAmelkin/ch34x_serial提供的修改后的工具
修改后的版本加上简单的 udev 规则(也可以从上述存储库获得)对我来说工作正常,并产生了 8 个独立的设备别名。