HCI(7)

πŸ’– HCI β€” ok bestie, let's talk Bluetooth πŸ’–

So this is the manual page for hci (that's the Bluetooth HCI protocol, and yes it's a section 7 page, iykyk). Grab a snack, we're decoding how your computer literally talks to Bluetooth adapters. πŸ¦‹


✨ NAME ✨

hci β€” Bluetooth HCI protocol


πŸŽ€ SYNOPSIS πŸŽ€

#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>

hci_socket = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);

🌸 DESCRIPTION 🌸

Okay so. Bluetooth Host Controller Interface (HCI) is the standard protocol for talking to Bluetooth adapters. That's it, that's the vibe.

HCI gives the Host a uniform command method so it can peek at what the Controller can do, and control the connections to other Controllers. Uniform command method. One protocol to rule them all. Periodt. πŸ‘‘


πŸ’… SOCKET ADDRESS πŸ’…

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

So hci_channel can be any of these, and each one is a whole different personality:

  • HCI_CHANNEL_RAW β€” value 0x00 β€” Raw channel, used for raw HCI communication.
  • HCI_CHANNEL_USER β€” value 0x01 β€” User channel, used for userspace HCI communication (and it disables kernel processing, so be aware, bestie).
  • HCI_CHANNEL_MONITOR β€” value 0x02 β€” Monitor channel, used for monitoring HCI traffic (btmon(1)).
  • HCI_CHANNEL_CONTROL β€” value 0x03 β€” Control channel, used to manage local adapters (bluetoothd(7)).
  • HCI_CHANNEL_LOGGING β€” value 0x04 β€” Logging channel, used to inject logging messages (bluetoothd(7)).

And here's an example, so you can copy-paste and feel iconic:

struct sockaddr_hci addr;

memset(&addr, 0, sizeof(addr));
addr.hci_family = AF_BLUETOOTH;
addr.hci_dev = HCI_DEV_NONE;
addr.hci_channel = HCI_CHANNEL_CONTROL;

⭐ SOCKET OPTIONS ⭐

All the socket options down below get set with setsockopt(2) and read back with getsockopt(2), with the socket level set to SOL_BLUETOOTH or SOL_HCI (that second one is for HCI_FILTER, mwah πŸ’‹).

πŸ”₯ HCI_FILTER (since Linux 2.6) πŸ”₯

Filters by HCI events. It requires hci_channel to be set to HCI_CHANNEL_RAW. Possible values:

struct hci_filter {
    uint32_t type_mask;
    uint32_t event_mask[2];
    uint16_t opcode;
};

Example time:

struct hci_filter flt;

memset(&flt, 0, sizeof(flt));
flt.type_mask = 1 << BT_H4_EVT_PKT;
flt.event_mask[0] = 0xffffffff;
flt.event_mask[1] = 0xffffffff;

setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt));

πŸ¦‹ BT_SNDBUF (since Linux 5.16) πŸ¦‹

Sets the send buffer size. It requires hci_channel to be set to HCI_CHANNEL_MONITOR, HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.

Default value is 1028. Yes, really, 1028. Write it down. πŸ“

Example:

uint16_t mtu = UINT16_MAX;
int err;

err = setsockopt(fd, SOL_BLUETOOTH, BT_SNDMTU, &mtu, sizeof(mtu));

πŸ’œ BT_RCVBUF (since Linux 5.16) πŸ’œ

Sets the receive buffer size. Same deal β€” it requires hci_channel to be set to HCI_CHANNEL_MONITOR, HCI_CHANNEL_CONTROL or HCI_CHANNEL_LOGGING.

Default value is 1028 too. Twin behavior, honestly obsessed.

Example:

uint16_t mtu;
socklen_t len;
int err;

len = sizeof(mtu);
err = getsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU, mtu, &len);

🌈 RESOURCES 🌈


😭 REPORTING BUGS 😭

  • <linux-bluetooth@vger.kernel.org>

Found something cursed? Tell the mailing list, they're lovely. 🫢


πŸ‘‘ SEE ALSO πŸ‘‘


Free use of this software is granted under the terms of the GNU Lesser General Public Licenses (LGPL). Slay, and also legally binding. πŸ’…


Okay that's the whole page, bestie, you ate it up. πŸ“ This one's from BlueZ, dated October 2024, and it lives at HCI(7) in the Linux System Administration section β€” so go forth and socket responsibly. Mwah! πŸ’–βœ¨