Skip to content

LINUX PLATFORM

Using Bumble With Physical Bluetooth Controllers

A Bumble application can interface with a local Bluetooth controller on a Linux host. The 3 main types of physical Bluetooth controllers are:

  • Bluetooth USB Dongle
  • HCI over UART (via a serial port)
  • Kernel-managed Bluetooth HCI (HCI Sockets)

Conflicts with the kernel and BlueZ

If your use a USB dongle that is recognized by your kernel as a supported Bluetooth device, it is likely that the kernel driver will claim that USB device and attach it to the BlueZ stack. If you want to claim ownership of it to use with Bumble, you will need to set the state of the corresponding HCI interface as DOWN. HCI interfaces are numbered, starting from 0 (i.e hci0, hci1, ...).

For example, to bring hci0 down:

$ sudo hciconfig hci0 down

You can use the hciconfig command with no arguments to get a list of HCI interfaces seen by the kernel.

Also, if bluetoothd is running on your system, it will likely re-claim the interface after you close it, so you may need to bring the interface back UP before using it again, or to disable bluetoothd altogether (see the section further below about BlueZ and bluetoothd).

Using a USB Dongle

See the USB Transport page for general information on how to use HCI USB controllers.

USB Permissions

By default, when running as a regular user, you won't have the permission to use arbitrary USB devices. You can change the permissions for a specific USB device based on its bus number and device number (you can use lsusb to find the Bus and Device numbers for your Bluetooth dongle).

Example:

$ sudo chmod o+w /dev/bus/usb/001/004
This will change the permissions for Device 4 on Bus 1.

Note that the USB Bus number and Device number may change depending on where you plug the USB dongle and what other USB devices and hubs are also plugged in.

If you need to make the permission changes permanent across reboots, you can create a udev rule for your specific Bluetooth dongle. Visit this Arch Linux Wiki page for a good overview of how you may do that.

Using HCI over UART

See the Serial Transport page for general information on how to use HCI over a UART (serial port).

Using HCI Sockets

HCI sockets provide a way to send/receive HCI packets to/from a Bluetooth controller managed by the kernel. See the HCI Socket Transport page for details on the hci-socket tansport syntax.

The HCI device referenced by an hci-socket transport (hci<X>, where <X> is an integer, with hci0 being the first controller device, and so on) must be in the DOWN state before it can be opened as a transport. You can bring a HCI controller UP or DOWN with hciconfig hci<X> up and hciconfig hci<X> up.

HCI Socket Permissions

By default, when running as a regular user, you won't have the permission to use an HCI socket to a Bluetooth controller (you may see an exception like PermissionError: [Errno 1] Operation not permitted).

If you want to run without using sudo, you need to manage the capabilities by adding the appropriate entries in /etc/security/capability.conf to grant a user or group the cap_net_admin capability. See this manpage for details.

Alternatively, if you are just experimenting temporarily, the capsh command may be useful in order to execute a single command with enhanced permissions, as in this example:

$ sudo capsh --caps="cap_net_admin+eip cap_setpcap,cap_setuid,cap_setgid+ep" --keep=1 --user=$USER --addamb=cap_net_admin  -- -c "<path/to/executable> <executable-args>"
Where <path/to/executable> is the path to your python3 executable or to one of the Bumble bundled command-line applications.

List all available controllers

The command

$ hciconfig
lists all available HCI controllers and their state.

Example:

pi@raspberrypi:~ $ hciconfig
hci1:   Type: Primary  Bus: USB
    BD Address: 00:16:A4:5A:40:F2  ACL MTU: 1021:8  SCO MTU: 64:1
    DOWN
    RX bytes:84056 acl:0 sco:0 events:51 errors:0
    TX bytes:1980 acl:0 sco:0 commands:90 errors:0

hci0:   Type: Primary  Bus: UART
    BD Address: DC:A6:32:75:2C:97  ACL MTU: 1021:8  SCO MTU: 64:1
    DOWN
    RX bytes:68038 acl:0 sco:0 events:692 errors:0
    TX bytes:20105 acl:0 sco:0 commands:843 errors:0

Disabling bluetoothd

When the Bluetooth daemon, bluetoothd, is running, it will try to use any HCI controller attached to the BlueZ stack, automatically. This means that whenever an HCI socket transport is released, it is likely that bluetoothd will take it over, so you will get a "device busy" condition (ex: OSError: [Errno 16] Device or resource busy). If that happens, you can always use

$ hciconfig hci0 down
(or hci<X> with <X> being the index of the controller device you want to use), but a simpler solution is to just stop the bluetoothd daemon, with a command like:
$ sudo systemctl stop bluetooth.service
You can always re-start the daemon with ``` $ sudo systemctl start bluetooth.service

Bumble on the Raspberry Pi

Raspberry Pi 4

You can use the Bluetooth controller either via the kernel, or directly to the device.

Via The Kernel

Use an HCI Socket transport (see section above)

Directly

In order to use the Bluetooth controller directly on a Raspberry Pi 4 board, you need to ensure that it isn't being used by the BlueZ stack (which it probably is by default).

$ sudo systemctl stop hciuart
should detach the controller from the stack, after which you can use the HCI UART with Bumble.

Check the device name for the UART and at what speed it should be opened

$ sudo systemctl status hciuart
should show the speed at which the UART should be opened. For example:
$ sudo systemctl status hciuart
 hciuart.service - Configure Bluetooth Modems connected by UART
  Loaded: loaded (/lib/systemd/system/hciuart.service; enabled; vendor preset: enabled)
  Active: active (running) since Fri 2021-06-18 02:17:28 BST; 1min 10s ago
 Process: 357 ExecStart=/usr/bin/btuart (code=exited, status=0/SUCCESS)
Main PID: 586 (hciattach)
   Tasks: 1 (limit: 4915)
  CGroup: /system.slice/hciuart.service
          └─586 /usr/bin/hciattach /dev/serial1 bcm43xx 3000000 flow -
When run before stopping the hciuart service, shows that on this board, the UART device is /dev/serial and the speed is 3000000

Example: scanning

python3 run_scanner.py serial:/dev/serial1,3000000

Using Bumble With BlueZ

In addition to all the standard functionality available from the project by running the python tools and/or writing your own apps by leveraging the API, it is also possible on Linux hosts to interface the Bumble stack with the native BlueZ stack, and with Bluetooth controllers.

A Bumble virtual controller can be attached to the BlueZ stack. Attaching a controller to BlueZ can be done by either simulating a UART HCI interface, or by using the VHCI driver interface if available. In both cases, the controller can run locally on the Linux host, or remotely on a different host, with a bridge between the remote controller and the local BlueZ host, which may be useful when the BlueZ stack is running on an embedded system, or a host on which running the Bumble controller is not convenient.

Using VHCI

With the VHCI transport you can attach a Bumble virtual controller to the BlueZ stack. Once attached, the controller will appear just like any other controller, and thus can be used with the standard BlueZ tools.

Attaching a virtual controller

With the example app run_controller.py:

python3 examples/run_controller.py F6:F7:F8:F9:FA:FB examples/device1.json vhci

You should see a 'Virtual Bus' controller. For example:

$ hciconfig
hci0:   Type: Primary  Bus: Virtual
    BD Address: F6:F7:F8:F9:FA:FB  ACL MTU: 27:64  SCO MTU: 0:0
    UP RUNNING
    RX bytes:0 acl:0 sco:0 events:43 errors:0
    TX bytes:274 acl:0 sco:0 commands:43 errors:0

And scanning for devices should show the virtual 'Bumble' device that's running as part of the run_controller.py example app:

pi@raspberrypi:~ $ sudo hcitool -i hci2 lescan
LE Scan ...
F0:F1:F2:F3:F4:F5 Bumble

```

Using a Simulated UART HCI

Bridge to a Remote Controller