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 服务。udev
btattach
在进行一些初步测试时,这个简单的答案可能仍然有用,特别是在找到正确的 udev 规则条件时。
答案2
更精细的方法包括创建一条udev
规则,仅在存在正确的硬件时触发,以btattach
从systemd 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 bcm
ttys1(因此/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
......