如何为依赖 btattach 的最新 Intel 和 Broadcom 芯片组“启动时自动”启用蓝牙?

如何为依赖 btattach 的最新 Intel 和 Broadcom 芯片组“启动时自动”启用蓝牙?

Intel 和 Broadcom 的一些最新蓝牙芯片组需要btattach在用户空间中运行该命令才能正确启用蓝牙(它“附加”BT 芯片组并在需要时触发所需固件的加载)。

此类示例是 Lenovo ThinkPad 8 平板电脑上的 Broadcom BCM43241 rev B5 芯片组,它需要以下命令,# btattach --bredr /dev/ttyS1 -P bcm但这适用于连接到 UART 控制器的许多其他蓝牙芯片组。

btattach问:在启动过程中触发所需命令以自动启用蓝牙的最佳推荐方法是什么

PS 这个想法是为开始打包命令的 Linux 发行版btattach(如 Debian)提供这样的修改,因为现在许多最新的设备根本没有开箱即用的蓝牙功能。这对于没有或很少有全尺寸 USB 端口的平板电脑特别有用。

答案1

linux-bluetooth 邮件列表上的讨论建议创建一个相应的udev rule,参见。这条信息

对于问题中提到的特定芯片组,一个简单的 udev 规则如下所示:

$ cat /etc/udev/rules.d/98-bluetooth-attach-broadcom.rule KERNEL=="BCM2E55:00", RUN+="/usr/bin/btattach --bredr /dev/ttyS1 -P bcm"

BCM2E55:00是相应蓝牙芯片组的硬件 ACPI 标识符,显示为终端S1设备节点(通过 sysfs in 可见/sys/devices/platform/80860F0A:00/tty/ttyS1/device/BCM2E55:00$)。每个 ACPI 标识符都需要添加到规则文件中,并为每个芯片组变体调整相应的 /dev/ttyS*。

然而,这种简单方法的一个已知限制是它只能在很短的时间内起作用,如上所述这里。事实上,该btattach命令会在几秒/分钟后被终止。这是以下行为的记录udev

启动守护进程或其他长时间运行的进程不适合 udev;分叉的进程,无论是否分离,都将无条件地被被杀事件处理完成后。`

因此,其他选项需要间接触发以确保它不会被终止,而不是btattach直接从规则本身启动命令,例如可能通过 systemd 服务。udevbtattach

在进行一些初步测试时,这个简单的答案可能仍然有用,特别是在找到正确的 udev 规则条件时。

答案2

更精细的方法包括创建一条udev规则,仅在存在正确的硬件时触发,以btattachsystemd service.这是合并之前两个答案的概念。

对于问题中提到的特定芯片组,udev规则看起来很简单:

$ cat /etc/udev/rules.d/99-bluetooth-btattach.rules KERNEL=="BCM2E55:00", RUN+="/bin/systemctl --no-block start btattach-broadcom-ttyS1.service"

BCM2E55:00是相应蓝牙芯片组的硬件ACPI标识符。

systemd 服务,仅与作为子代出现的芯片组兼容终端S1设备节点(通过 sysfs in 可见/sys/devices/platform/80860F0A:00/tty/ttyS1/device/BCM2E55:00$),可以保持非常简单,如下所示:

$ cat /etc/systemd/system/btattach-broadcom-ttyS1.service [Unit] Description=Start btattach, needed to enable Bluetooth for some UART-based Bluetooth Broadcom chipsets [Service] Type=simple # A delay is needed, 1s seems enough ExecStartPre=/bin/sleep 1s ExecStart=/usr/bin/btattach --bredr /dev/ttyS1 -P bcm

对于作为子项出现的其他 Broadcom 芯片组(因此参数),这systemd service将按原样工作-P bcmttys1(因此/dev/ttyS1);只需udev完成规则即可包含其他芯片组变体的 ACPI 标识符。

对于连接到不同 ttyS* 节点的 Broadcom 芯片组,systemd service可以创建另一个类似的来覆盖这种情况(或者可以将正确的参数从 udev 规则共享到 systemd 服务)。

重新启动平板电脑表明该btattach命令在启动时正确执行:

$ ps auxw | grep btattach root 2059 0.0 0.0 6372 720 ? Ss 23:17 0:00 /usr/bin/btattach --bredr /dev/ttyS1 -P bcm

并且蓝牙实际上已启用并且正在工作! Gnome 蓝牙设置确实列出了已连接和扫描的设备,并且$ bluetoothctl从命令行运行可以正确显示控制器。

令人惊讶的是,当删除用于简单延迟实际命令的初始 1 秒睡眠命令时,蓝牙根本无法工作,并且无法正确启用,尽管btattach在后台进程列表中似乎仍然正确运行。

还不确定到底发生了什么:在启动 btattach 之前,存在一个时间问题,并且肯定需要等待所需的依赖项......

答案3

一种可行的方法是创建一个硬编码的 systemd 服务,如下所示:

$ cat /etc/systemd/system/btattach.service 
[Unit]
Description=Start btattach, needed to enable Bluetooth for some UART-based Bluetooth chipsets
[Service]
Type=simple
\# A delay is needed though, 1s seems enough on my system
ExecStartPre=/bin/sleep 1s
ExecStart=/usr/bin/btattach --bredr /dev/ttyS1 -P bcm
[Install]
WantedBy=multi-user.target`

要启用此新服务,请运行以下命令:

# systemctl --system enable btattach

重新启动平板电脑显示 btattach 命令现在已在启动时正确执行:

$ ps auxw | grep btattach
root      2059  0.0  0.0   6372   720 ?        Ss   23:17   0:00 /usr/bin/btattach --bredr /dev/ttyS1 -P bcm

并且蓝牙实际上已启用并且正在工作! Gnome 蓝牙设置确实列出了已连接和扫描的设备,并且$ bluetoothctl从命令行运行可以正确显示控制器。

令人惊讶的是,当删除用于简单延迟实际命令的初始1s sleep命令时,蓝牙根本无法工作,并且无法正确启用,尽管btattach在后台进程列表中似乎仍然正确运行。

还不确定到底发生了什么:在启动之前存在一个时间问题,并且肯定需要等待所需的依赖项btattach......

相关内容