Adding Linux BlueZ DBus peripheral role support

Broadly speaking the Qt’s Bluetooth Low Energy (“BT LE") support consists of two complementing use cases: the central/client and the peripheral/server roles. For more details about the two roles please consult the Qt Bluetooth documentation.

Qt 6.5 introduces a new Linux backend for the peripheral (server) role which is based on the BlueZ DBus API. This backend now complements the already existing Qt BlueZ DBus client backend. 

The existing BlueZ Bluetooth management socket peripheral backend support is kept available for reasons laid out later in this post.

The Brief History

The current Qt Linux peripheral backend was introduced in 2014. It operates on a somewhat lower abstraction level by using Bluetooth management sockets. These sockets allow a very detailed control over the operation of the Bluetooth subsystem, and the resulting backend implementation is very detailed and, in my view, an ambitious and admirable implementation. Back in 2014 it was more or less the only viable option for implementing BT LE on Linux.

Fast forward a few years to 2016, the BlueZ project marked the D-Bus API as non-experimental. Following that Qt Bluetooth released support for the BlueZ DBus client role backend, while the peripheral role implementation remained on the management sockets.

Fast forward again, and the BlueZ D-Bus peripheral role support starts to mature, and for instance the Advertising API required for the peripheral role is marked as non-experimental

This brings us to the current day: adding the BlueZ DBus peripheral role support. The high level Figure below illustrates how it fits in with the existing backends:



There are several reasons why to make this change, for instance:

  • The BlueZ DBus and Qt management sockets implementation both operate on a lower abstraction level themselves, resulting in some sense a duplicate implementation.
  • The BlueZ DBus API is probably the eventual successor of the management sockets, and some day in the future it is plausible that the support for management sockets might cease. Therefore Qt 6.5, as an LTS release, is safe should such phasing out happen.
  • Also there are reports from users that the DBus API is in fact more stable for the typical use, see for example the commentary here
  • For some use cases such as encryption and general data protection the bluetooth daemon provides most of the support out-of-the-box already. The BlueZ Bluetooth management socket API required Qt to implement many aspects. Relying on the BlueZ projects expertise allows QtBluetooth to leverage this expertise.
  • There are some use cases where a low level access via the socket API can clash with other Bluetooth applications who try to manage peripheral services via the BlueZ’s DBus API.

While developing the BlueZ DBus backend I’ve learned to appreciate its overall stability and operation. I’ve run tests literally hundreds of times, against several Bluetooth stacks and with different Bluetooth hardware, and it appears to be a solid foundation to build on. 

As a detail I also find it pleasing that using BlueZ DBus API does not require the CAP_NET_ADMIN capability for the application process. This requirement probably meant for many people in practice running the peripheral application as a root during the development phase.

Requirements and opting in

The new backend is an opt-in backend for the applications. This means that unless the user opts in, the current management socket API will be used.  The opting in happens by setting the QT_BLUETOOTH_USE_DBUS_PERIPHERAL environment variable.

The primary reason for this is that the BlueZ DBus API is not feature-wise on par with the lower level socket implementation; some, arguably less-used, features are not supported.  These are indicated in the respective feature documentation throughout the Qt Bluetooth documentation. To provide some intuition on these features, they include things such as connection request whitelists and advertising intervals, and updating connection parameters.

The minimum required BlueZ version is 5.56. There were some issues with versions prior to that, which would have made the backend implementation trickier. For clarity it should be noted that a typical application wouldn’t likely hit those issues, but the story is a bit different for Qt Bluetooth which, as a library, needs to be prepared for various Qt Bluetooth API use cases.

Please see the documentation on the requirements.

That’s it

Thank you for reading this far. As always feedback is welcome, and in particular please be sure to file any bugs you encounter here. Bluetooth stacks, use cases, devices, and Bluetooth environments differ vastly and such reports are invaluable.

Blog Topics: