I need to control an HCI device directly without the Linux drivers/kernel interfering. For example, when creating an LE connection to a peripheral, the driver is independently sending an "LE Connection Update" command which I would like to avoid.
I though of two approaches to resolve this:
- Configure the bluetooth drivers to somehow disable interference with the HCI device (similar to the -r flag on hciattach), then control the HCI device using a regular AF_BLUEOOTH socket.
- Disable this particular HCI device, but keep the parent char device and connect to it directly.
So far I did not succeed in finding a way of how to implement any of these approaches.
I should also mention that I still need a different HCI device to be "normally" used by the system so disabling the bluetooth drivers completely is not an option.
I was able to achieve option #1.
Digging in the Linux kernel code for bluetooth drivers, I found an option for binding an HCI socket with hci_channel=1
. 1 is the enum for HCI_USER_CHANNEL
which causes the driver not to add its own commands to the HCI device.
To achieve this in 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));
To achieve this in Python:
Python's socket module does not support this option. A workaround for the missing support in Python was implemented in Scapy:
https://github.com/secdev/scapy/blob/d2f2b0c7b46b607fcdf79860f8f866446bb625fb/scapy/layers/bluetooth.py#L808
Example for C++:
https://github.com/sandeepmistry/node-bluetooth-hci-socket/blob/560a956c3e1421e31366115444ca9027d45b0e71/src/BluetoothHciSocket.cpp#L184
If you are interested in the relevant part of the Linux kernel: https://github.com/torvalds/linux/blob/86292b33d4b79ee03e2f43ea0381ef85f077c760/net/bluetooth/hci_sock.c#L1693