【问题标题】:Excessive Bluetooth LE timeouts on Linux?Linux 上的蓝牙 LE 超时过多?
【发布时间】:2026-01-01 20:05:01
【问题描述】:

我编写了一个应用程序,它在 Linux 上以非阻塞模式使用蓝牙 LE L2CAP 连接来读取/写入 ATT 数据包(使用 socket(PF_BLUETOOTH, SOCK_SEQPACKET|SOCK_CLOEXEC, BTPROTO_L2CAP))。通常,当设备关闭或超出范围时,read() 会给出 errno=ETIMEDOUT。

但是,read() 给出的 errno=ETIMEDOUT 频率超出了应有的频率,此时蓝牙 LE 设备似乎仍在工作。超时的原因是什么?超时时间是否可配置?

我的 Linux 配置是 3.13.0-24-generic;蓝牙核心版本 2.17。

【问题讨论】:

    标签: linux bluetooth-lowenergy l2cap


    【解决方案1】:

    已建立的 LE L2CAP 套接字上的 ETIMEDOUT 错误实际上来自蓝牙适配器在几个连续丢失的数据包之后。多少取决于连接参数。一旦 master 发起与 slave 的连接,master 每 Connection Interval (7.5ms–4s) 对 slave 执行一次 ping 操作,slave 如果听到 ping 就会做出响应。如果任一设备在 监督超时 (100ms–32s) 后未能收到另一台设备的回复,它将关闭连接。第三个参数 Slave Latency (0-499) 允许从机通过不响应某些 ping 来节省电池电量。另见What are connection parameters?

    操作系统在启动连接时设置默认连接参数。从设备可能会推荐一组更合适的连接参数来平衡电池寿命、延迟和对障碍物/干扰的恢复能力,并且操作系统有机会批准这些参数(请参阅Apple’s Bluetooth Design Guidelines 了解 Apple 操作系统将使用的连接参数范围接受)。但是如果从站不建议一组新的参数,那么它就会受到操作系统默认值的摆布,操作系统的默认值会因操作系统而异!

    在查看 Wireshark 中的 hcidump btsnoop 文件时,我的特定设备(蓝牙笔)似乎从未建议不同的间隔和超时。因此,其可靠性将取决于操作系统的默认设置。

    这里是通过实验确定的默认间隔和超时。

    带有内置蓝牙适配器的 Linux 3.13 (currently defined in hci_core.c):
    操作系统允许的时间间隔:50–70ms
    蓝牙适配器选择的连接间隔:67.5ms
    监督超时:420ms(6在断开前丢失数据包)

    装有 iOS 7 的 iPhone 4S:
    操作系统允许的时间间隔:未知
    蓝牙适配器选择的连接间隔:30ms
    从属延迟:0 个数据包
    监督超时:720ms(23在断开前丢失数据包)

    Nexus 4 上的 Android 5.0.1 Lollipop
    操作系统允许的时间间隔:30–50ms
    蓝牙适配器选择的连接间隔:48.75ms
    从属延迟:0 个数据包
    监督超时:2000 毫秒(41 在断开之前丢失数据包)

    带有外部适配器的 OSX 10.10.1(Apple 蓝牙软件版本:4.3.1f2 15015):
    操作系统允许的时间间隔:未知
    蓝牙适配器选择的连接间隔:15ms
    从属延迟:0 个数据包
    监督超时:2000ms(133在断开之前丢失数据包)

    这解释了为什么我与 Livescribe 笔的连接在 Linux 上显得不太可靠。内核默认是只丢了6个包就断开连接,pen从来不推荐更好的参数。

    在 Linux 3.17 及更高版本上,可以通过写入 /sys/kernel/debug/bluetooth/hci0/supervision_timeout 来调整监督超时。

    测试方法:Linux 上的跟踪是使用 hcidump(在 Android 的开发人员选项中)获得的,并在 Wireshark 中针对 HCI LE Create Connection 命令进行了分析。 OSX 和 iPhone 的跟踪是使用 TI CC2540 和 TI 的数据包嗅探器软件获得的。

    【讨论】: