蓝牙
蓝牙是一种用于手机、电脑和其他电子设备短距离无线互连的标准。在 Linux 中,蓝牙协议栈的规范实现是 BlueZ。
安装
- 安装提供蓝牙协议栈的 bluez 软件包。
- 安装提供 bluetoothctl 工具的 bluez-utils 软件包。此外,安装 bluez-deprecated-tools 以获得已废弃的 BlueZ 工具。
- 通用的蓝牙驱动是
btusb内核模块。检查该模块是否已加载。如果未加载,则加载该模块。 - 启动/启用
bluetooth.service。
- 一些蓝牙适配器与 Wi-Fi 网卡捆绑(例如较旧的 Intel Centrino 网卡)。它们需要首先启用 Wi-Fi 网卡(通常是笔记本电脑上的键盘快捷键)才能使蓝牙适配器对内核可见。
- 一些蓝牙网卡(例如 Broadcom)与网络适配器冲突。因此,您需要确保您的蓝牙设备在网络服务启动之前连接。
- 一些工具,例如 hcitool 和 hciconfig 已在上游被废弃,并且不再包含在 bluez-utils 中。由于这些工具将不再更新,建议更新脚本以避免使用它们。如果您仍然希望使用它们,请额外安装 bluez-deprecated-tools。有关更多信息,请参阅 FS#53110 和 Bluez 邮件列表。
- 自 2024 年以来,bluez-obex 和 bluez-mesh 已从 bluez 中分离。因此,如果您计划通过蓝牙传输文件,需要安装 bluez-obex 并启用用户服务
obex.service。
前端
控制台
- bluetoothctl — 从 shell 配对设备是最简单可靠的选项之一。
- bluetui — 用于管理蓝牙设备的 TUI。
- bluetuith — 通过终端用户界面提供蓝牙管理器,以便更轻松地配对和管理设备/适配器,支持 OBEX 文件传输和鼠标。
- bluez-tools — 基础的非交互式工具,涵盖 bluetoothctl 中缺少的一些功能,例如发送文件或管理蓝牙网络。
echo -e "command1\ncommand2\n" | bluetoothctl 或 bluetoothctl -- command。图形界面
以下软件包提供图形界面以自定义蓝牙。
- GNOME Bluetooth — GNOME 的蓝牙工具。
- gnome-bluetooth-3.0 提供后端(gnome-bluetoothAUR 现已过时)
- gnome-shell 提供状态监视小程序
- gnome-control-center 提供配置前端 GUI,可以通过在 Activities 概览中键入 "Bluetooth" 或使用
gnome-control-center bluetooth命令来访问。 - 您也可以直接启动
bluetooth-sendto命令以向远程设备发送文件。 - nautilus-bluetoothAUR 将“通过蓝牙发送”条目添加到 Nautilus 的右键菜单中
- 要接收文件,请打开蓝牙设置面板;您只能在蓝牙面板打开时接收文件。
- 要在 Thunar 文件属性菜单的 发送到 菜单中添加蓝牙条目,请参阅此处的说明。(需要配置的命令是
bluetooth-sendto %F)。
- Bluedevil — KDE 的蓝牙工具。如果 Dolphin 和系统托盘中没有蓝牙图标可见,请在系统托盘选项中启用它或添加小部件。您可以单击图标配置 Bluedevil 并检测蓝牙设备。KDE 系统设置中也提供了界面。
- Blueberry — Linux Mint 的 GNOME Bluetooth 分支,适用于所有桌面环境。Blueberry 不支持通过 Obex Object Push 接收文件。
- Blueman — 功能齐全的蓝牙管理器。
- ObexFTP — 用于向/从任何启用 OBEX 的设备传输文件的工具。
- Overskride — 一个简单但功能强大的蓝牙客户端。
- btctl — fuzzel 和其他启动器的一个简单蓝牙连接管理器。
配对
本节介绍通过 bluetoothctl(1) 命令行工具直接配置 bluez,如果您使用替代的前端工具(例如 GNOME Bluetooth),则可能不需要。
确切的步骤取决于所涉及的设备及其输入功能。下面是使用 bluetoothctl 配对设备的通用概述。
启动 bluetoothctl 交互式命令。输入 help 获取可用命令列表。
- (可选) 使用
select MAC_address选择一个默认控制器。 - (可选) 输入
power on以打开控制器的电源(如果设备设置为关闭)。默认情况下它是打开的;请参阅#默认适配器电源状态。 - 输入
devices获取要配对设备的 MAC 地址。 - 如果设备尚未在列表中,请使用
scan on命令进入设备发现模式。 - 使用
agent on打开代理或选择特定代理:如果在agent后按两次 Tab 键,您应该会看到可用代理的列表。蓝牙代理是管理蓝牙“配对码”的。它可以响应传入的“配对码”,也可以发送一个出去。在大多数情况下,default-agent应该适用。[1] - 输入
pair MAC_address进行配对(Tab 补全可用)。 - 如果使用的设备没有 PIN 码,可能需要手动信任设备才能成功重新连接。输入
trust MAC_address来执行此操作。 - 输入
connect MAC_address建立连接。
一个会话示例可能如下所示
$ bluetoothctl
[NEW] Controller 00:10:20:30:40:50 hostname [default] [bluetooth]# agent KeyboardOnly Agent registered [bluetooth]# default-agent Default agent request successful [bluetooth]# power on Changing power on succeeded [CHG] Controller 00:10:20:30:40:50 Powered: yes [bluetooth]# scan on Discovery started [CHG] Controller 00:10:20:30:40:50 Discovering: yes [NEW] Device 00:12:34:56:78:90 device name [CHG] Device 00:12:34:56:78:90 LegacyPairing: yes [bluetooth]# pair 00:12:34:56:78:90 Attempting to pair with 00:12:34:56:78:90 [CHG] Device 00:12:34:56:78:90 Connected: yes [CHG] Device 00:12:34:56:78:90 Connected: no [CHG] Device 00:12:34:56:78:90 Connected: yes Request PIN code [agent] Enter PIN code: 1234 [CHG] Device 00:12:34:56:78:90 Paired: yes Pairing successful [CHG] Device 00:12:34:56:78:90 Connected: no [bluetooth]# connect 00:12:34:56:78:90 Attempting to connect to 00:12:34:56:78:90 [CHG] Device 00:12:34:56:78:90 Connected: yes Connection successful
双系统配对
对于双启动 Linux 系统,如#保存配置所示,只需确保 /var/lib/bluetooth/BT-Adapter-MAC-address 中的所有文件在每个安装上都相同,可以通过复制或创建符号链接来完成。
对于 Windows 或 macOS,要在双启动设置上配对设备,您需要更改 Linux 安装上的配对密钥以匹配。
本页仅描述手动操作方法。要自动化该过程,请参阅 bt-dualboot 项目(不支持 低功耗蓝牙)和 相关存储库。对于半自动化过程,请使用 bluetooth-dualboot 脚本,它不编辑任何文件,但可以帮助您运行正确的命令并剪切粘贴正确的值。
设置
要做到这一点,首先在您的 Arch Linux 安装上配对设备。然后重启到另一个操作系统并配对设备。现在您需要提取配对密钥,但首先关闭蓝牙设备以防止任何连接尝试。
针对 Windows
您可以在 Linux 或 Windows 上提取蓝牙密钥
在 Windows 上提取
首先,启动到 Windows。
包含链接密钥的注册表项只能由 SYSTEM 帐户访问,而该帐户无法登录。因此,您将需要微软官方 Windows Sysinternals 网站上的 PsExec 工具,以便以 SYSTEM 身份运行 regedit.exe。
下载 PsTools,并提取 PsExec64.exe。
在以管理员身份运行的命令 shell 中,从提取的 EXE 所在位置启动注册表编辑器
.\PsExec64.exe -s -i regedit.exe
在注册表编辑器中,导航到以下注册表项
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Keys
在此注册表项中,每个蓝牙适配器都有一个子项,以 MAC 地址命名。如果存在多个子项,并且您不确定使用哪个子项,请按照此指南查找所需蓝牙适配器的 MAC 地址。
在所需适配器的注册表项中,每个已配对设备都有一个名称-值对,其中名称是其 MAC 地址。此外,您可能会看到一些以 MAC 地址命名的子项,每个子项都包含名称-值对,名称如 LTK 或 IRK。这些子项(如果存在)用于蓝牙 5.1 设备。如果您尝试共享的设备具有子项,则它是蓝牙 5.1 设备。如果它没有子项,只有名称-值对,则它不是蓝牙 5.1 设备。
右键单击适配器的注册表项并将其导出为 .reg 文件。这是一个文本文件,您可以从中复制密钥。如前所述,它包含非蓝牙 5.1 设备的名称-值对中的配对密钥,以及蓝牙 5.1 设备的每个设备子项中的配对密钥(和一些其他信息)。将此文件提供给您的 Linux 安装并重新启动到其中。
如果您要共享的设备不是蓝牙 5.1 设备,请跳到#保存配置。如果它是蓝牙 5.1 设备,则在完成之前,您需要对配对密钥和相关信息进行一些修改。请参阅#准备蓝牙 5.1 密钥了解如何操作。
在 Linux 上提取
启动到 Arch。安装 chntpw。挂载您的 Windows 系统驱动器。切换到注册表 hive 目录并在 SYSTEM hive 上启动 chntpw
$ cd /path/to/windows/system/Windows/System32/config $ chntpw -e SYSTEM
在 chntpw 环境中,运行
> cd CurrentControlSet\Services\BTHPORT\Parameters\Keys
您可能会看到 ControlSet00X 而不是 CurrentControlSet(使用 ls 检查);请改用此项
> cd ControlSet00X\Services\BTHPORT\Parameters\Keys
可能只有一个子项,其名称是您的蓝牙适配器的 MAC 地址。使用 ls 显示它并 cd 进入它
> ls > cd your-adapter's-mac-address
该适配器下的子项名称是适配器配对的设备的 MAC 地址。使用 ls 显示它们,然后 cd 进入您想要双重配对的每个设备
> ls > cd your-device's-mac-address
如果这不是蓝牙 5.1 设备,您将只看到配对密钥
> ls
Node has 0 subkeys and 1 values size type value name [value if type DWORD] 16 REG_BINARY <ab12cd34ef56>
如果是这样,使用 hex 显示设备的密钥的 hexdump
> hex ab12cd34ef56
:00000 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX (some other chars)
"XX" 是配对密钥。记下哪些密钥对应哪些 MAC 地址。
如果这是蓝牙 5.1 设备,那么您将看到与一个设备对应的多个密钥
Node has 0 subkeys and 8 values
size type value name [value if type DWORD]
16 3 REG_BINARY <LTK>
4 4 REG_DWORD <KeyLength> 16 [0x10]
8 b REG_QWORD <ERand>
4 4 REG_DWORD <EDIV> 37520 [0x9290]
16 3 REG_BINARY <IRK>
8 b REG_QWORD <Address>
4 4 REG_DWORD <AddressType> 1 [0x1]
4 4 REG_DWORD <AuthReq> 45 [0x2d]
请参阅#准备蓝牙 5.1 密钥,了解如何使用这些密钥,使用 hex value_name 获取所需的值。
最后,要将密钥导入到您的 Linux 安装中,请继续进行#保存配置。
针对 macOS
启动到 macOS
- 对于 macOS Monterey 或更新版本
- 打开“钥匙串访问”(在 macOS Tahoe 及更高版本中重命名为“密码”)并搜索 Bluetooth。
- 按日期排序。
- 如果您最近移除了设备并重新连接,那么您可以简单地按修改日期对密钥进行排序并选择最新的。它可能被称为 MobileBluetooth(对于较旧的蓝牙设备)或者只是一个 UUID(对于蓝牙 5.1+)。
- 双击该条目。检查“账户”字段中的 MAC 地址是否与您设备的 MAC 地址匹配。
- 单击“显示密码”复选框。现在您需要输入两次密码。
- 复制密码字段中的文本,它实际上是一个 XML 文件(
⌘+a⌘+c) - 将文本粘贴到您主目录中的
bt_keys.txt中。
- 对于 High Sierra 或更新版本,在终端中运行以下命令
# defaults read /private/var/root/Library/Preferences/com.apple.bluetoothd.plist LinkKeys > ~/bt_keys.txt
- 对于 Sierra 或更旧版本,在终端中运行以下命令
# defaults read /private/var/root/Library/Preferences/blued.plist LinkKeys > ~/bt_keys.txt
现在 ~/bt_keys.txt 文件包含已建立的蓝牙密钥。对于旧版本的 macOS(High Sierra 和更旧版本),您必须在继续之前反转密钥。例如,98 54 2f aa bb cc dd ee ff gg hh ii jj kk ll mm 变为 MM LL KK JJ GG FF EE DD CC BB AA 2F 54 98。
>>> key = "98 54 2f aa bb cc dd ee ff gg hh ii jj kk ll mm" >>> " ".join(reversed(key.split()))
如果这是一个蓝牙 5.1 设备,那么将有不止一个密钥对应一个设备。请参阅#准备蓝牙 5.1 密钥,了解如何使用这些密钥。
最后,要将密钥导入到您的 Linux 安装中,请重新启动到 Linux 并继续#保存配置。
准备蓝牙 5.1 密钥
如果您在遵循 #针对 Windows 或 #针对 macOS 时观察到蓝牙 5.1 密钥的存在,则在将其导入 Linux 之前,必须对其值进行某些转换。创建所需的文件及其适当的内容,以便在#保存配置中进行安装。此过程将取决于设备,并且某些值必须进行操作;下面提供了用于执行此操作的代码实用程序。
| 设备 | 源密钥和转换(Windows) | 源密钥和转换(macOS) | 目标密钥文件 |
|---|---|---|---|
|
|
? | IdentityResolvingKey.Key
|
|
? | SlaveLongTermKey.Key 和 PeripheralLongTermKey.Key | |
ERand 和 EDIV 应为 0 |
随机数和加密多样化器应为 0。 |
– | |
|
|
? | IdentityResolvingKey.Key
|
|
? | LocalSignatureKey.Key
| |
|
? | LongTermKey.Key
| |
|
? | LongTermKey.EncSize
| |
|
? | LongTermKey.EDiv
| |
|
? | LongTermKey.Rand
| |
|
|
? | IdentityResolvingKey.Key
|
|
? | LongTermKey.Key
| |
|
? | LongTermKey.EncSize
| |
|
? | LongTermKey.EDiv
| |
|
? | LongTermKey.Rand
| |
|
|
? | RemoteSignatureKey.Key
|
|
|
|
IdentityResolvingKey.Key
|
|
|
LongTermKey.Key
| |
|
|
LongTermKey.Rand
| |
|
|
LongTermKey.EDiv
| |
| 其他设备 |
|
|
LongTermKey.Key
|
|
|
LongTermKey.Rand
| |
|
|
LongTermKey.EDiv
| |
| Xbox 无线控制器 |
|
? | SlaveLongTermKey.Key
|
>>> "key_value".replace(" ", "")
- 此 Python 代码仅执行八位字节反转
>>> ERand=" 63 02 84 B8 5D 40 44 DF " >>> ERand=list(reversed(ERand.strip().split()))
- 此 Python 代码执行某些所需的额外十进制转换
>>> int("".join(ERand), 16)
16088054540146049635
- 此 Python 代码执行 base64 到十六进制转换
binascii.hexlify(base64.decodebytes(b'...')).upper()
- 此 Python 代码执行完整的 macOS 加密多样化器转换
struct.unpack('<H', base64.decodebytes(b'...'))
- 此 Python 代码执行完整的 macOS 随机数转换
struct.unpack('<Q', base64.decodebytes(b'...'))
一般情况的示例
48 4D AF CD 0F 92 22 88 0A 52 9A F4 76 DA 8B 94的LTK变成了484DAFCD0F9222880A529AF476DA8B94的LongTermKey.Key。63 02 84 B8 5D 40 44 DF的ERand变成了16088054540146049635的Rand。37520的EDIV变成了37520的EDiv。
保存配置
现在您有了密钥,将用户切换到 root,然后继续
# cd /var/lib/bluetooth/BT-Adapter-MAC-address
在这里您会找到每个已配对蓝牙设备的文件夹。对于您要与 Arch 和双启动配对的每个设备,请执行以下操作
# cd device-MAC-address
如果您有配对密钥(即这不是蓝牙 5.1 设备),则编辑 info 文件并更改 [LinkKey] 下的密钥。例如:
info
[LinkKey] Key=XXXXXXXXXXXXXXX
如果您有多个密钥,例如蓝牙 5.1,请编辑 info 文件并用记录的值替换所有适用的密钥。例如,对于 Xbox One S 无线控制器
info
[IdentityResolvingKey] Key=<IdentityResolvingKey.Key> [PeripheralLongTermKey] Key=<PeripheralLongTermKey.Key> [SlaveLongTermKey] Key=<SlaveLongTermKey.Key>
然后重启 bluetooth.service 和 pulseaudio(使用 pulseaudio -k && pulseaudio --start)。
您现在应该能够连接到您的设备。
配置
默认传输 3.0 vs 5.x (低功耗)
要强制蓝牙控制器使用较旧的蓝牙传输协议(例如,因为为 3.0 设备设置双启动配对比为 5.x BLE 设备简单),请在 /etc/bluetooth/main.conf 的 [General] 部分设置 ControllerMode=bredr
/etc/bluetooth/main.conf
[General] ControllerMode=bredr
默认值为 ControllerMode=dual,即同时启用 BR/EDR 和 LE。
默认适配器电源状态
截至 bluez 5.65,BlueZ 的默认行为是在启动服务或从挂起恢复时打开所有蓝牙适配器的电源。[2]
如果您希望适配器不自动启用(例如在便携设备上,您希望节省电池),请在 /etc/bluetooth/main.conf 的 [Policy] 部分设置 AutoEnable=false
/etc/bluetooth/main.conf
[Policy] AutoEnable=false
适配器仍然可以通过运行 #配对 中描述的 power on 手动打开。
启动时可发现
如果设备应始终可见并可直接连接
/etc/bluetooth/main.conf
[General] DiscoverableTimeout = 0
从挂起唤醒
允许蓝牙键盘、鼠标等从休眠中唤醒系统。首先,检查 BIOS 设置并确保未禁用 USB 唤醒。在许多情况下,主板的蓝牙是 USB 设备。
为蓝牙适配器添加新的 udev 规则(USB 无线控制器基类,蓝牙编程接口协议)以启用从休眠中唤醒
/etc/udev/rules.d/91-bluetooth-wakeup.rules
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", \
ATTR{bDeviceClass}=="e0", \
ATTR{bDeviceProtocol}=="01", \
ATTR{bDeviceSubClass}=="01", \
ATTR{power/wakeup}="enabled"
要在唤醒后自动重新配置您的蓝牙键盘,例如具有不同的键盘映射或按键重复率(有关详细信息,请参阅 Xorg/Keyboard configuration#调整按键延迟和重复率 和 xmodmap),请创建一个可执行脚本
configure_keyboard.sh
#!/bin/sh export DISPLAY=:0 xset r rate 220 30 xmodmap /your/path/to/.Xmodmap
然后像上面一样创建附加的 udev 规则
/etc/udev/rules.d/92-keyboard-reconfiguration-wakeup.rules
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", \
ATTR{bDeviceClass}=="e0", \
ATTR{bDeviceProtocol}=="01", \
ATTR{bDeviceSubClass}=="01" \
RUN+="/your/path/to/configure_keyboard.sh"
启用实验性功能
Bluez 堆栈将新的、可能存在错误的特性放在 D-Bus experimental 和 kernel experimental 选项之后。这些选项包含的功能会随时间变化,因为实验性特性被确定为稳定后就不再需要该选项(例如:启用 D-Bus 实验性接口目前允许报告旧耳机的电池电量)。要启用这些特性,请取消注释配置文件中的相应行
/etc/bluetooth/main.conf
... # Enables D-Bus experimental interfaces # Possible values: true or false Experimental = true # Enables kernel experimental features, alternatively a list of UUIDs # can be given. # Possible values: true,false,<UUID List> # Possible UUIDS: ... # Defaults to false. KernelExperimental = true
或者,您可以编辑 bluetooth.service 以添加 --experimental 或 --kernel 标志,例如这个放置文件
/etc/systemd/system/bluetooth.service.d/override.conf
[Service] ExecStart= ExecStart=/usr/lib/bluetooth/bluetoothd --experimental
无论哪种方式,您都必须重启 bluetooth.service。
音频
通常需要额外一步将音频服务器与蓝牙集成。这将在以下部分详细说明。
有关蓝牙音频和蓝牙耳机的更多信息,请参阅蓝牙耳机页面。
PulseAudio
为了能够使用蓝牙耳机或扬声器等音频设备,您需要安装额外的 pulseaudio-bluetooth 软件包。请务必重新启动 PulseAudio 以使安装生效:pulseaudio -k。在默认的 PulseAudio 安装中(特别是使用带有打包的 default.pa 的用户实例),您应该能够立即从蓝牙设备将音频流式传输到扬声器。[3]
如果您有系统范围的 PulseAudio 设置,请确保运行守护进程的用户(通常是 pulse)属于 lp 组,并且您在 PulseAudio 配置中加载蓝牙模块
/etc/pulse/system.pa
... load-module module-bluetooth-policy load-module module-bluetooth-discover ...
(可选)添加 load-module module-switch-on-connect,如果您想自动将所有音频切换到蓝牙设备。
PipeWire
PipeWire 从 v0.3.19 开始默认启用其蓝牙支持。
ALSA
首先,确保您的蓝牙音频设备已正确配对并连接到系统。
然后,安装 bluez-alsa-gitAUR,启动(并启用) bluealsa 服务,并将您的用户添加到 audio 组。
运行以下命令检查一切是否按预期工作(替换下面的 XX:XX:XX:XX:XX:XX 和 FILE.wav)
$ aplay -D bluealsa:SRV=org.bluealsa,DEV=XX:XX:XX:XX:XX:XX,PROFILE=a2dp FILE.wav
最后,将以下行添加到您的 ~/.asoundrc 中
~/.asoundrc
defaults.bluealsa {
service "org.bluealsa"
device "XX:XX:XX:XX:XX:XX"
profile "a2dp"
}
您现在可以使用 bluealsa 设备连接您的蓝牙音频设备。音量管理通常通过 alsamixer 和选项 -D bluealsa 进行。
蓝牙串口
要在蓝牙到串口模块(HC-05, HC-06)上实现蓝牙串口通信,请执行以下步骤
使用 bluetoothctl 如上所述配对您的蓝牙设备。
安装 bluez-deprecated-tools,因为它提供了新工具中缺少的一些功能。
将配对设备的 MAC 地址绑定到 tty 终端
# rfcomm bind rfcomm0 MAC_address_of_Bluetooth_device
现在您可以打开 /dev/rfcomm0 进行串口通信
$ picocom /dev/rfcomm0 -b 115200
故障排除
常见问题排查
调试
为了调试,首先停止 bluetooth.service。
然后用 -d 参数启动它
# /usr/lib/bluetooth/bluetoothd -n -d
另一种选择是使用 btmon 工具。
已废弃的 BlueZ 工具
BlueZ 的八个工具已废弃并从 bluez-utils 中移除,尽管并非所有都被新工具取代。bluez-deprecated-tools 软件包现在提供这些已废弃的工具。
| 已废弃工具 | 最可能的替代品 |
|---|---|
| gatttool | btgatt-client, D-Bus Gatt API (GattCharacteristic, GattDescriptor, GattManager, GattProfile, 和 GattService) |
| hciattach | btattach |
| hciconfig | btmgmt (和 bluetoothctl?) |
| hcidump | btmon (和 btsnoop) |
| hcitool | 缺失,D-Bus Device API 可用 |
| rfcomm | 缺失,用 D-Bus Profile/ProfileManager API 实现? |
| ciptool | |
| sdptool | 缺失,功能似乎分散在不同的 D-Bus 对象中:Profile,Advertising (LEAdvertisement 和 LEAdvertisingManager),以及 device 和 adapter 中的 UUID 数组。 |
服务问题
systemd: 条件检查导致蓝牙服务被跳过
bluetooth.service 只要求目录 /sys/class/bluetooth 存在,该目录应由内核模块 bluetooth 创建,而 bluetooth 只有在实际找到一个正常工作的蓝牙硬件设备时才会被 systemd-udev 自动加载。
如果您的 /sys/class/bluetooth 不存在,请检查您的内核蓝牙模块是否已通过 lsmod 加载。如果没有,并且您认为您有蓝牙设备,您可以尝试通过手动加载蓝牙模块并重启 bluetooth.service 来手动启动它们。
您在加载 bluetooth 模块时,还应该加载相应的内核蓝牙驱动,最可能是 btusb,但也可能是 btrtl,btintel,btbcm,bnep,btusb 等。
检查 bluetooth.service 的单元状态以查看它是否已启动。
另请参阅 Debian Bug report logs - #853207。
如果 bluetooth.service 成功启动,您仍然可能无法正常使用蓝牙(例如,当您 scan on 时,bluetoothctl 会说 org.Bluez.Error.NotReady)。如果发生这种情况,请尝试重新启动计算机,并仔细检查:目录 /sys/class/bluetooth 是否存在;lsmod 是否包含正确的蓝牙模块;journal 中的日志消息;等等。systemd-udev 应该会自动检测您的蓝牙硬件,而无需再次手动更改。
蓝牙立即唤醒 suspend-to-idle 设备
在支持 suspend-to-idle/S2idle/S0ix/现代待机 的系统上,蓝牙控制器在睡眠期间将保持启用。这通常会导致系统在连接任何蓝牙设备的情况下进入睡眠后立即唤醒。
为了防止这种情况,您可以在进入睡眠之前完全禁用蓝牙——安装 bluez-utils 并创建此文件
/etc/systemd/system/bluetooth-disable-before-sleep.service
[Unit] Description=Disable Bluetooth before going to sleep Before=sleep.target Before=suspend.target Before=hybrid-sleep.target Before=suspend-then-hibernate.target StopWhenUnneeded=yes [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/bluetoothctl power off ExecStop=/usr/bin/bluetoothctl power on [Install] WantedBy=sleep.target WantedBy=suspend.target WantedBy=hybrid-sleep.target WantedBy=suspend-then-hibernate.target
启用此服务并检查蓝牙设备是否在进入睡眠时断开连接,以及在系统唤醒后蓝牙是否恢复正常。
如果使用此解决方法,使用蓝牙鼠标/键盘唤醒系统将不起作用。
在无头/服务器系统上注销后蓝牙关闭
这可能有多种原因
- PulseAudio 和 PipeWire 默认都以用户服务运行,一旦最后一个会话结束,它们就会终止。为用户启用持久会话以解决此问题。
- 此外,当使用 PipeWire 运行 WirePlumber 时(通常如此),WirePlumber 会运行一个“logind-monitor”,它在登录时启用蓝牙,在注销时禁用蓝牙。有关修复,请参阅 WirePlumber#注销后保持蓝牙运行 / 无头蓝牙。
适配器问题
hcitool scan: 未找到设备
- 在某些笔记本电脑(例如戴尔 Studio 15,联想 Thinkpad X1)上,您必须将蓝牙模式从 HID 切换到 HCI。安装 bluez-hid2hci 软件包,然后 udev 应该会自动完成此操作。或者,您可以运行此命令手动切换到 HCI
# /usr/lib/udev/hid2hci
- 如果设备仍然不显示,并且您的机器上安装了 Windows 操作系统,请尝试启动它并从 Windows 启用蓝牙适配器。
- 有时这个简单的命令也会有所帮助
# bluetoothctl power on
bluetoothctl: 没有可用的默认控制器
首先,确保设备未被 rfkill 阻止。如果使用 USBGuard,请确保它没有阻止设备(参见 USBGuard#允许蓝牙控制器)。
否则,请考虑以下可能的原因
- 一些主板蓝牙控制器存在导致此问题的错误。要查看是否是此问题,请运行
journalctl | grep hci并检查它是否包含command tx timeout或Reading Intel version command failed。如果包含,请关闭计算机并物理拔下电源线几秒钟。这会强制控制器重新加载固件,与标准重启不同(参见错误报告)。 - 一些 Intel 网卡(例如 8260)未被蓝牙服务正确识别。在这种情况下,使用已废弃的 bluez-deprecated-tools 而不是 bluez-utils 可能会解决此问题。
- 一些适配器,例如 CSR 克隆,在内核级别存在兼容性问题。
- 省电措施可能导致问题,在这种情况下,添加内核参数
btusb.enable_autosuspend=n是一种潜在的解决方案(参见错误报告)。
最后,不带选项地卸载和加载 btusb 有时有助于控制器恢复正常
# modprobe -r btusb # modprobe btusb
rfkill unblock: 不要解除阻塞
如果您的设备仍然被软阻塞并且您运行 ConnMan,请尝试以下方法
$ connmanctl enable bluetooth
蓝牙 USB 适配器
如果您使用 USB 适配器,应检查蓝牙适配器是否被识别。您可以在插入 USB 适配器时以 root 身份运行 journalctl -f(或检查 /var/log/messages.log)来执行此操作。它应该类似于以下内容(注意 hci)
Feb 20 15:00:24 hostname kernel: [ 2661.349823] usb 4-1: new full-speed USB device number 3 using uhci_hcd Feb 20 15:00:24 hostname bluetoothd[4568]: HCI dev 0 registered Feb 20 15:00:24 hostname bluetoothd[4568]: Listening for HCI events on hci0 Feb 20 15:00:25 hostname bluetoothd[4568]: HCI dev 0 up Feb 20 15:00:25 hostname bluetoothd[4568]: Adapter /org/bluez/4568/hci0 has been enabled
如果您只得到前两行,您可能会看到它找到了设备,但您需要将其启动。例如
# btmgmt
[mgmt]# info Index list with 1 item hci0: Primary controller addr 00:1A:7D:DA:71:10 version 6 manufacturer 10 class 0x000000 supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr hs le advertising secure-conn debug-keys privacy static-addr current settings: connectable discoverable bondable ssp br/edr le secure-conn name Mozart short name [mgmt]# select hci0 Selected index 0 [hci0]# power up hci0 Set Powered complete, settings: powered connectable discoverable bondable ssp br/edr le secure-conn [hci0]# info hci0: Primary controller addr 00:1A:7D:DA:71:10 version 6 manufacturer 10 class 0x1c0104 supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr hs le advertising secure-conn debug-keys privacy static-addr current settings: powered connectable discoverable bondable ssp br/edr le secure-conn
或者:
# bluetoothctl
[bluetooth]# show Controller 00:1A:7D:DA:71:10 (public) Name: Mozart Alias: Mozart Class: 0x0000095c Powered: no Discoverable: yes Pairable: yes [bluetooth]# power on [CHG] Controller 00:1A:7D:DA:71:10 Class: 0x001c0104 Changing power on succeeded [CHG] Controller 00:1A:7D:DA:71:10 Powered: yes [bluetooth]# show Controller 00:1A:7D:DA:71:10 (public) Name: Mozart Alias: Mozart Class: 0x001c0104 Powered: yes Discoverable: yes Pairable: yes
要验证设备是否被检测到,您可以使用 btmgmt,它是 bluez-utils 的一部分。您可以通过发出以下命令获取可用设备及其标识符和 MAC 地址的列表
$ btmgmt info
Index list with 1 item hci0: Primary controller addr 00:1A:7D:DA:71:10 version 6 manufacturer 10 class 0x1c0104 supported settings: powered connectable fast-connectable discoverable bondable link-security ssp br/edr hs le advertising secure-conn debug-keys privacy static-addr current settings: powered connectable discoverable bondable ssp br/edr le secure-conn
可以根据官方规范中的表格,将蓝牙版本映射到 HCI 版本。例如,在前面的输出中,HCI 版本 6 是蓝牙 4.0 版本。
可以使用已废弃的 hciconfig (bluez-deprecated-tools) 来检索设备的更详细信息。
$ hciconfig -a hci0
hci0: Type: USB
BD Address: 00:1B:DC:0F:DB:40 ACL MTU: 310:10 SCO MTU: 64:8
UP RUNNING PSCAN ISCAN
RX bytes:1226 acl:0 sco:0 events:27 errors:0
TX bytes:351 acl:0 sco:0 commands:26 errors:0
Features: 0xff 0xff 0x8f 0xfe 0x9b 0xf9 0x00 0x80
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: 'BlueZ (0)'
Class: 0x000100
Service Classes: Unspecified
Device Class: Computer, Uncategorized
HCI Ver: 2.0 (0x3) HCI Rev: 0xc5c LMP Ver: 2.0 (0x3) LMP Subver: 0xc5c
Manufacturer: Cambridge Silicon Radio (10)
音频设备在离适配器短距离处开始跳音
如果其他设备共享同一个 USB 主机,它们可能会干扰与音频设备的通信。确保它是其总线上唯一连接的设备。例如
$ lsusb
Bus 002 Device 002: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 004: ID 048d:1345 Integrated Technology Express, Inc. Multi Cardreader Bus 001 Device 003: ID 0424:a700 Standard Microsystems Corp. 2 Port Hub Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
CSR 适配器 0a12:0001
设备 ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) 有一个回归错误,目前仅在内核版本 5.17 和 < 6.0 中有效。有关更多信息,请参阅 内核 Bug 60824。
罗技蓝牙 USB 适配器
有一些罗技适配器(例如罗技 MX5000)可以工作在两种模式:嵌入式和 HCI。在嵌入式模式下,适配器模拟一个 USB 设备,因此您的电脑会认为您正在使用普通的 USB 鼠标/键盘。
如果您按住 USB 迷你接收器上的红色小按钮 3-5 秒,它将启用另一种模式。
或者,您可以安装 bluez-hid2hci 软件包。当您连接罗技适配器时,它将自动切换。
富士康 / 鸿海 / Lite-On 博通设备
其中一些设备需要在启动时将固件刷入设备。
在 AUR 上搜索 broadcom 时可以找到一些固件,一个值得注意的软件包是 broadcom-bt-firmwareAUR,它提供了多张网卡的文件。
或者,可以使用 hex2hcd(与 bluez-utils 一起安装)将 Microsoft Windows .hex 文件转换为 .hcd。
为了获得正确的 .hex 文件,请尝试搜索通过 lsusb 获得的设备供应商:产品代码,例如
Bus 002 Device 004: ID 04ca:2006 Lite-On Technology Corp. Broadcom BCM43142A0 Bluetooth Device
或者
Bus 004 Device 004: Id 0489:e031 Foxconn / Hon Hai
或者,启动到 Windows(虚拟机安装即可)并从设备管理器实用程序获取固件名称。如果您想知道设备的型号但无法在 lsusb 中看到它,您可能会在 lsusb -v 中看到它作为 iProduct。
.hex 文件可以从下载的 Windows 驱动程序中提取,而无需运行 Windows。下载正确的驱动程序,例如 Bluetooth Widcomm。根据格式,提取文件可能需要 unrar 或 cabextract。要找出众多 .hex 文件中哪个适合您,请查看文件 Win32/bcbtums-win7x86-brcm.inf 并搜索 [RAMUSBE031.CopyList],其中 E031 应替换为您的设备的产品代码(lsusb 中的第二个十六进制数字),大写。在下面您应该看到正确的 .hex 文件的文件名。
获得 .hcd 文件后,将其复制到 /lib/firmware/brcm/BCM.hcd - 此文件名由 dmesg 建议,并且在您的情况下可能会更改,因此请检查您的 dmesg 输出以进行验证。然后重新加载 btusb 模块
# rmmod btusb # modprobe btusb
设备现在应该可用。有关使这些更改持久化的信息,请参阅 BBS#162688。
英特尔 Wi-Fi 和蓝牙组合卡
请参阅 无线网络配置#蓝牙共存。
Mediatek MT7921 或 MT7961 在双系统与 Windows 并存时
在双系统系统中,如果 Windows 和 Linux 的蓝牙固件版本不同,则在重启到 Windows 后蓝牙适配器将无法工作。
防止这种情况的最佳方法是为每个操作系统更新蓝牙驱动程序(特别是固件)到最新版本。
如果找不到 Windows 的最新版本驱动程序(或固件),您可以从 Arch Linux 复制最新的固件文件 /usr/lib/firmware/mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin.xz 并将其解压到 Windows(例如 C:\WINDOWS\system32\DRIVERS\,您可以在 Windows 的设备管理器中找到固件文件路径)。
适配器在休眠/唤醒后消失
首先,找到适配器的供应商和产品 ID。例如
$ lsusb -tv
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/12p, 480M
ID 1d6b:0002 Linux Foundation 2.0 root hub
...
|__ Port 3: Dev 3, If 0, Class=Wireless, Driver=btusb, 12M
ID 8087:0025 Intel Corp.
|__ Port 3: Dev 3, If 1, Class=Wireless, Driver=btusb, 12M
ID 8087:0025 Intel Corp.
...
在这种情况下,供应商 ID 为 8087,产品 ID 为 0025。
然后,使用 usb_modeswitch 重置适配器
# usb_modeswitch -R -v vendor_ID -p product_ID
配对和连接问题
计算机不可见
如果您的计算机无法被手机发现,请启用可发现模式
# bluetoothctl discoverable on
验证可发现模式是否开启
# bluetoothctl show
Powered: yes Discoverable: yes Pairable: yes
/etc/bluetooth/main.conf 中的 DiscoverableTimeout 和 PairableTimeout。如果计算机仍未显示,请尝试更改 /etc/bluetooth/main.conf 中的设备类别,如下所示
# Default device class. Only the major and minor device class bits are # considered. #Class = 0x000100 # Computer Type (from default config) Class = 0x100100 # (Object-Transfer Service & Computer Type)
main.conf 中的 Class 在设备初始化后会被覆盖,因此请使用 hciconfig hci0 class 100100 直接设置类别。一位用户报告说这是他们手机能发现电脑的唯一解决方案。LG 电视(以及其他一些电视)可以通过其音频设备发现,因此使用 000414(条形音箱类别)将使此类设备出现。
请参阅 https://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html 生成蓝牙设备/服务类别。
设备连接后,几分钟后断开连接
BlueZ 5.83 中引入的一个错误(在 5.86 中仍然存在)导致在进行一次多余的身份验证尝试失败后断开连接。此错误似乎只影响支持多点连接的设备[4]。一个临时解决方案是重启 bluetooth.service。在 KDE Plasma 中,杀死或禁用 KDE Connect 可以停止此问题。
如果您在日志中看到以下消息,并且您的设备连接失败或连接后很快断开
bluetoothd: Unable to get connect data for Headset Voice gateway: getpeername: Transport endpoint is not connected (107) bluetoothd: connect error: Connection refused (111)
这可能是因为您已经使用相同的蓝牙适配器(例如,双启动)将设备与另一个操作系统配对。某些设备无法处理与同一 MAC 地址(即蓝牙适配器)关联的多个配对。请按照#双系统配对中的说明解决此问题。
设备未显示在扫描结果中
某些使用低功耗蓝牙的设备在用 bluetoothctl 扫描时不会显示,例如 罗技 MX Master。您可以使用 transport le 来扫描它。
# bluetoothctl
[bluetooth]# menu scan [bluetooth]# transport le [bluetooth]# back [bluetooth]# scan on [bluetooth]# devices ... Device XX:XX:XX:XX:XX:XX DA V2 X <---- low energy device here
另一种连接它们的方法是安装 bluez-deprecated-tools,然后启动 bluetooth.service 并执行
# bluetoothctl
[NEW] Controller (MAC) myhostname [default] [bluetooth]# power on [CHG] Controller (MAC) Class: 0x0c010c Changing power on succeeded [CHG] Controller (MAC) Powered: yes [bluetooth]# scan on Discovery started [CHG] Controller (MAC) Discovering: yes
在另一个终端中
# hcitool lescan
等待您的设备出现,然后 Ctrl+c hcitool。bluetoothctl 现在应该能看到您的设备并正常配对。
Intel Corp. AX200 蓝牙无法发现任何 BLE 设备
此设备的 BLE 被动扫描似乎已损坏。有关更多详细信息,请参阅上游错误报告。
睡眠后无法重新连接
您可能会注意到,设备进入睡眠状态后,或者计算机从休眠状态唤醒后,您无法自动重新连接到设备。
例如,您会在日志中注意到以下错误
bluetoothd[487]: Authentication attempt without agent bluetoothd[487]: Access denied: org.bluez.Error.Rejected
这可能是因为设备未标记为受信任。请参阅#配对。
特定设备问题
蓝牙鼠标卡顿 / 断开连接 / 无响应
请参阅 蓝牙鼠标#故障排除。
音频设备连接失败,提示 br-connection-profile-unavailable
如果正在使用 pipewire(而不是 pulseaudio-bluetooth),但 pipewire 实例未运行,蓝牙音频设备将无法连接。启动 pipewire.service 用户单元或播放一些音频以启动 pipewire 守护程序,然后再次尝试连接音频设备。
耳机和鼠标之间的干扰
如果您在使用蓝牙鼠标和键盘时遇到音频卡顿,您可以尝试以下方法,如 #23 https://bugs.launchpad.net/ubuntu/+source/bluez/+bug/424215 所述
# hciconfig hci0 lm ACCEPT,MASTER # hciconfig hci0 lp HOLD,SNIFF,PARK
TP-LINK UB400 和 Xbox 控制器持续连接/断开
使用以下设置
/etc/bluetooth/main.conf
... [General] JustWorksRepairing = always FastConnectable = true Class = 0x000100 ... [GATT] ReconnectIntervals=1,1,2,3,5,8,13,21,34,55 AutoEnable=true ...
然后重启 bluetooth.service。
您可以查看xpadneo 上的相关讨论,但不需要 xpadneo 驱动程序。
文件传输问题
gnome-bluetooth
如果您在 bluetooth-properties 中尝试启用接收文件时看到此内容
Bluetooth OBEX start failed: Invalid path Bluetooth FTP start failed: Invalid path
那么请确保 XDG 用户目录 存在。
因符号链接导致无法接收传输的文件
如果传入文件传输在其他功能正常的蓝牙连接上失败,则问题可能是由于文件传输路径中的符号链接。日志中会出现如下消息
Jun 18 11:18:13 ember obexd[3338969]: open(/home/me/.cache/obexd/MOC740): Operation not permitted (1)
如果错误消息中显示的路径包含符号链接,则 obexd 默认将不接受它。此行为可以在初始化时使用 obex.service 用户服务的放置文件来覆盖
~/.config/systemd/user/obex.service.d/10-symlink.conf
[Service] ExecStart= ExecStart=/usr/lib/bluetooth/obexd --symlinks
然后重新加载调用用户的 systemd 管理器配置,并重启 obex.service 用户单元。