pw_bluetooth_sapphire#

Battle-tested Bluetooth with rock-solid reliability

Unstable C++17 Code Size Impact: 500 to 700 kB

Attention

This module is still under construction. There is no public API yet. Please contact the Pigweed team if you are interested in using this module.

The pw_bluetooth_sapphire module provides a dual-mode Bluetooth Host stack that will implement the pw_bluetooth APIs. Sapphire originated as the Fuchsia operating system’s Bluetooth stack and is used in production. The Sapphire Host stack has been migrated into the Pigweed project for use in embedded projects. However, as it was not written in an embedded context, there is a lot of work to be done to optimize memory usage.

Why use Sapphire?

  • Open source, unlike vendor Bluetooth stacks. This makes debugging and fixing issues much easier!

  • Integrated with Pigweed. Logs, asserts, randomness, time, async, strings, and more are all using Pigweed modules.

  • Excellent test coverage, unlike most Bluetooth stacks. This means fewer bugs and greater maintainability.

  • Certified. Sapphire was certified by the Bluetooth SIG after passing all conformance tests.

  • A great API. Coming 2025. See pw_bluetooth.

Architecture#

Sapphire is composed of multiple libraries that implement different protocols in the Core specification. These libraries include:

HCI: Host-Controller Interface

Processes data (ACL), command, and event packets exchanged between the host and the controller. Note that HCI is currently split into hci, transport, and hci-spec libraries.

L2CAP: Logical Link Control and Adaptation Layer Protocol

Multiplexes a single ACL connection into multiple channels and manages channel configuration and flow control.

SDP: Service Discovery Protocol

Serves the BR/EDR service database and searches peers for BR/EDR services.

SM: Security Manager

Implements LE security, including pairing.

ATT: Attribute Protocol

Implements the ATT protocol PDUs, flow control, and database.

GATT: Generic Attribute Profile

Implements the GATT server and client.

GAP: Generic Access Profile

Responsible for device discovery and connection functionality.

SCO: Synchronous Connection Oriented link

Used for audio data by the Hands-Free Profile.

ISO: Isochronous Channels

Used for audio data in LE Audio.

These libraries build on top of each other as shown in the following diagram. HCI is the foundation, L2CAP builds on top of HCI, ATT builds on top of L2CAP, etc.

flowchart TB subgraph HCI["HCI"] TRA["Transport"] HCI2["HCI"] SPEC["HCI-Spec"] CONT["Controllers"] end subgraph Host["Host"] COM["Common"] GATT["GATT"] ISO["ISO"] SCO["SCO"] SM["SM"] L2CAP["L2CAP"] SDP["SDP"] GAP["GAP"] ATT["ATT"] HCI end GAP --> GATT & ISO & SCO & SM & L2CAP & SDP & HCI2 GATT --> ATT ATT --> L2CAP L2CAP --> TRA SCO --> HCI2 & TRA SM --> L2CAP SDP --> L2CAP ISO --> TRA HCI2 --> TRA TRA --> CONT CONT -- UART/USB --> Controller["Controller"]

Certification#

The Sapphire Host stack was certified as implementing the Bluetooth Core Specification 5.0 by the Bluetooth SIG in 2020 as “Google Sapphire 1.0 Bluetooth Core Host Solution”. You can find its public listing and add it to your product certification at the Qualification Workspace.

Products running Sapphire#

Sapphire is running on millions of the following devices:

  • Google Nest Hub (1st Gen)

  • Google Nest Hub (2nd Gen)

  • Google Nest Hub Max

Supported features#

GAP#

Feature

Supported?

Notes

BR/EDR/LE Device Configuration

BR/EDR Device Configuration

Tracking bug

LE Device Configuration

Tracking bug

Secure Simple Pairing

Legacy Pairing

LE Central Role

LE Peripheral Role

LE Advertising

LE Active Scanning

LE Passive Scanning

LE General Connection Establishment

LE Auto Connection Establishment

BR/EDR Inquiry

BR/EDR Connection Establishment

L2CAP#

Feature

Supported?

Notes

Fragmentation/Recombination

Segmentation/Reassembly

Tracking bug Clients must respect the peer’s MTU size, and Sapphire supports receiving the max SDU size.

BR/EDR Dynamic Channels

LE Connection-Oriented Channels (CoC)

Basic Mode (ERTM)

Enhanced Retransmission Mode (ERTM)

LE Credit-Based Flow Control Mode

Retransmission Mode

Tracking bug

Flow Control Mode

Tracking bug

Streaming Mode

Tracking bug

ATT#

Feature

Supported?

Notes

ATT over LE

ATT over BR/EDR

Tracking bug

Enhanced Attribute Protocol (EATT)

🚧

Tracking bug Most of the requirements are implemented. A few new PDUs are missing and there is no API yet.

Contributing#

Building#

The following commands will build test binaries for the host platform. The tests use GoogleTest so they are not supported by the default build configuration.

bazelisk build //pw_bluetooth_sapphire/host/... \
  --platforms=//pw_unit_test:googletest_platform \
  --@pigweed//pw_unit_test:backend=@pigweed//pw_unit_test:googletest

First, install the boringssl, emboss, and googletest packages with pw package.

pw package install boringssl
pw package install emboss
pw package install googletest

Next, configure the GN args for all of the packages and backends that Sapphire uses. For example:

gn args out
dir_pw_third_party_boringssl = "/path/to/pigweed/.environment/packages/boringssl"
dir_pw_third_party_emboss = "/path/to/pigweed/.environment/packages/emboss"
dir_pw_third_party_googletest = "/path/to/pigweed/.environment/packages/googletest"
pw_bluetooth_sapphire_ENABLED = true
pw_unit_test_MAIN = "//third_party/googletest:gmock_main"
pw_unit_test_BACKEND = "//pw_unit_test:googletest"
pw_function_CONFIG = "//pw_function:enable_dynamic_allocation"
pw_chrono_SYSTEM_CLOCK_BACKEND = "//pw_chrono_stl:system_clock"
pw_chrono_SYSTEM_TIMER_BACKEND = "//pw_chrono_stl:system_timer"
pw_async_TASK_BACKEND = "//pw_async_basic:task"
pw_async_FAKE_DISPATCHER_BACKEND = "//pw_async_basic:fake_dispatcher"

Finally, build with pw watch.

Running tests#

Run all tests:

bazelisk test //pw_bluetooth_sapphire/host/... \
  --platforms=//pw_unit_test:googletest_platform \
  --@pigweed//pw_unit_test:backend=@pigweed//pw_unit_test:googletest

Run l2cap tests with a test filter, logs, and log level filter:

bazelisk test //pw_bluetooth_sapphire/host/l2cap:l2cap_test \
  --platforms=//pw_unit_test:googletest_platform \
  --@pigweed//pw_unit_test:backend=@pigweed//pw_unit_test:googletest \
  --test_arg=--gtest_filter="*InboundChannelFailure" \
  --test_output=all \
  --copt=-DPW_LOG_LEVEL_DEFAULT=PW_LOG_LEVEL_ERROR

The easiest way to run GN tests is with pw presubmit, which will install dependencies and set GN args correctly.

$ pw presubmit --step gn_chre_googletest_nanopb_sapphire_build

You can also use pw watch if you install required packages and set your GN args as described in the Building section.

Clangd support#

In order to use pw_ide to generate a compilation database for Clangd, you must first configure your GN args as described in the Building GN tab.

Roadmap#

  • Support CMake

  • Implement pw_bluetooth APIs

  • Optimize memory footprint

  • Add snoop log capture support

  • Add metrics

  • Add configuration options (LE only, Classic only, etc.)

  • Add CLI for controlling stack over RPC