在 Linux 上直接控制 HCI 设备(绕过蓝牙驱动程序)

Posted

技术标签:

【中文标题】在 Linux 上直接控制 HCI 设备(绕过蓝牙驱动程序)【英文标题】:Direct Control of HCI Device (Bypass Bluetooth Drivers) on Linux 【发布时间】:2017-09-27 22:44:54 【问题描述】:

我需要在不受 Linux 驱动程序/内核干扰的情况下直接控制 HCI 设备。例如,在创建与外围设备的 LE 连接时,驱动程序会独立发送我希望避免的“LE 连接更新”命令。

我想了两种方法来解决这个问题:

    配置蓝牙驱动程序以某种方式禁用对 HCI 设备的干扰(类似于 hciattach 上的 -r 标志),然后使用常规 AF_BLUEOOTH 套接字控制 HCI 设备。 禁用此特定 HCI 设备,但保留父 char 设备并直接连接到它。

到目前为止,我还没有成功地找到实现这些方法的方法。

我还应该提到,我仍然需要一个不同的 HCI 设备才能被系统“正常”使用,因此完全禁用蓝牙驱动程序不是一种选择。

【问题讨论】:

【参考方案1】:

我能够实现选项#1。

深入研究蓝牙驱动程序的 Linux 内核代码,我发现了一个将 HCI 套接字与hci_channel=1 绑定的选项。 1 是 HCI_USER_CHANNEL 的枚举,这会导致驱动程序不会将自己的命令添加到 HCI 设备。

要在 C 中实现这一点:

struct sockaddr_hci 
    sa_family_t     hci_family;
    unsigned short  hci_dev;
    unsigned short  hci_channel;
;

struct sockaddr_hci a;

memset(&a, 0, sizeof(a));
a.hci_family = AF_BLUETOOTH;
a.hci_dev = 0; //0 for hci0
a.hci_channel = 1; //1 for HCI_CHANNEL_USER

bind(sock, (struct sockaddr *) &a, sizeof(a));

要在 Python 中实现这一点:

Python 的 socket 模块不支持这个选项。在 Scapy 中实现了 Python 中缺少支持的解决方法: https://github.com/secdev/scapy/blob/d2f2b0c7b46b607fcdf79860f8f866446bb625fb/scapy/layers/bluetooth.py#L808

C++ 示例: https://github.com/sandeepmistry/node-bluetooth-hci-socket/blob/560a956c3e1421e31366115444ca9027d45b0e71/src/BluetoothHciSocket.cpp#L184

如果您对Linux内核的相关部分感兴趣:https://github.com/torvalds/linux/blob/86292b33d4b79ee03e2f43ea0381ef85f077c760/net/bluetooth/hci_sock.c#L1693

【讨论】:

HCI_CHANNEL_USER 补丁介绍here,还包含一些文档

以上是关于在 Linux 上直接控制 HCI 设备(绕过蓝牙驱动程序)的主要内容,如果未能解决你的问题,请参考以下文章

Linux 上 C blueZ 中的蓝牙配对

怎样在Linux中使用蓝牙

蓝牙蓝牙,调试 hcitool与gatttool实例

蓝牙简介

linux 用蓝牙和手机通信

PyBluez over HCI 在 ESP32 的 Raspberry Pi 计算模块上工作异常