pw_bluetooth_proxy#

Lightweight proxy for augmenting Bluetooth functionality

Unstable C++17

The pw_bluetooth_proxy module provides a lightweight proxy host that can be placed between a Bluetooth host and Bluetooth controller to add additional functionality or inspection. All without modifying the host or the controller.

An example use case could be offloading some functionality from a main host located on the application processor to instead be handled on the MCU (to reduce power usage).

The proxy acts as a proxy of all host controller interface (HCI) packets between the host and the controller. Policies can then be added to the proxy to view, insert, or modify HCI packets to provide additional functionality.

pw::bluetooth::proxy::HciProxy acts as the main coordinator for proxy functionality. To use it, instantiate it with pw::bluetooth::proxy::ProxyPolicy instances that provide the proxy behavior you want. Then pass all HCI packets through the proxy.

#include "pw_bluetooth_proxy/hci_proxy.h"
#include "pw_bluetooth_proxy/passthrough_policy.h"

  // Container creates proxy with simple passthrough policy.
  PassthroughPolicy passthrough_policy{};
  std::array<ProxyPolicy*, 1> policies{&passthrough_policy};
  HciProxy proxy = HciProxy(std::move(containerSendToHostFn),
                            std::move(containerSendToControllerFn),
                            policies);

  // Container passes H4 packets from host through proxy. Proxy will in turn
  // call the container-provided `containerSendToControllerFn` to pass them on
  // to the controller. Note depending on the policies, some packets may be
  // modified, added, or removed.
  proxy.ProcessH4HciFromHost(h4_span_from_host);

  // Container passes H4 packets from controller through proxy. Proxy will in
  // turn call the container-provided `containerSendToHostFn` to pass them
  // on to the controller. Note depending on the policies, some packets may be
  // modified, added, or removed.
  proxy.ProcessH4HciFromController(h4_span_from_controller);
Get Started

How to set up in your build system

API Reference

Reference information about the API

Roadmap

Upcoming plans

Code size analysis

Understand code footprint and savings potential

Get started#

Bazel isn’t supported yet.

First add emboss to your project as described in Emboss.

Then add $dir_pw_bluetooth_proxy to the deps list in your pw_executable() build target:

pw_executable("...") {
  # ...
  deps = [
    # ...
    "$dir_pw_bluetooth_proxy",
    # ...
  ]
}

CMake isn’t supported yet (but will be soon).

API reference#

pw::bluetooth::proxy::HciProxy#

class HciProxy#

HciProxy acts as the main coordinator for proxy functionality. A container should instantiate it with pw::bluetooth::proxy::ProxyPolicy instances that provide the proxy behavior the container wants. The container then passes packets through the proxy.

Public Functions

HciProxy(H4HciPacketSendFn &&send_to_host_fn, H4HciPacketSendFn &&send_to_controller_fn, pw::span<ProxyPolicy*> policies)#

Creates an HciProxy that will process HCI packets using the passed policies.

Parameters:
  • send_to_host_fn[in] Callback that will be called when proxy wants to send HCI packet towards the host.

  • send_to_controller_fn[in] - Callback that will be called when proxy wants to send HCI packet towards the controller.

  • policies[in] - Policies that will be applied to HCI packets. Policies are applied in forward order for packets from host to controller, and in the reverse order for packets from controller to host. Proxy does not take ownership of content, span and policies must outlive this object.

inline virtual void ProcessH4HciFromHost(H4HciPacket packet)#

Called by container to ask proxy to process an H4 HCI packet sent from the host side towards the controller side. Proxy will in turn call the send_to_controller_fn provided during construction to pass the packet on to the controller. Depending on the policies, some packets may be modified, added, or removed.

inline virtual void ProcessH4HciFromController(H4HciPacket packet)#

Called by container to ask proxy to process HCI packet sent from the controller side towards the host side. Proxy will in turn call the send_to_host_fn provided during construction to pass the packet on to the host. Depending on the policies, some packets may be modified, added, or removed.

pw::bluetooth::proxy::ProxyPolicy#

class ProxyPolicy#

ProxyPolicy subclasses provide proxy functionality within a pw::bluetooth::proxy::HciProxy. They should be instantiated and passed to the proxy when it is constructed.

Subclassed by pw::bluetooth::proxy::PassthroughPolicy

Public Functions

virtual void ProcessH4HciFromHost(H4HciPacket packet) = 0#

Process H4 HCI packet sent from the host side towards the controller side.

virtual void ProcessH4HciFromController(H4HciPacket packet) = 0#

Process HCI packet sent from the controller side towards the host side.

inline void setSendToHostFn(H4HciPacketSendFn &&send_to_host_fn)#

Sets the callback that will be called by the policy when it wants to send HCI bytes towards the host.

pw::bluetooth::proxy::PassthroughPolicy#

class PassthroughPolicy : public pw::bluetooth::proxy::ProxyPolicy#

Simple pw::bluetooth::proxy::ProxyPolicy that just passes packets onward. Intended for testing and as a simple example.

Public Functions

inline virtual void ProcessH4HciFromHost(H4HciPacket packet) override#

Process H4 HCI packet sent from the host side towards the controller side.

inline virtual void ProcessH4HciFromController(H4HciPacket packet) override#

Process HCI packet sent from the controller side towards the host side.

Code size analysis#

Delta when constructing a passthrough proxy and sending packets through.

Label

Segment

Delta

Create and use proxy with passthrough policy

FLASH

+20

[section .code]

+172

main

NEW

+216

pw::bluetooth::proxy::HciProxy::HciProxy()

NEW

+206

fit::internal::target<>::invoke()

NEW

+160

fit::internal::target<>::ops

NEW

+64

pw::bluetooth::proxy::HciProxy::~HciProxy()

NEW

+64

pw::bluetooth::proxy::PassthroughPolicy::ProcessH4HciFromHost()

NEW

+60

pw::bluetooth::proxy::PassthroughPolicy::ProcessH4HciFromController()

NEW

+48

pw::bluetooth::proxy::PassthroughPolicy::~PassthroughPolicy()

NEW

+34

fit::internal::function_base<>::invoke()

NEW

+34

pw::bluetooth::proxy::HciProxy::ProcessH4HciFromController()

NEW

+32

pw::bluetooth::proxy::HciProxy::ProcessH4HciFromHost()

NEW

+28

fit::internal::generic_function_base<>::move_target_from()

NEW

+24

fit::function_impl<>::operator=()

NEW

+24

pw::bluetooth::proxy::HciProxy

NEW

+24

pw::bluetooth::proxy::PassthroughPolicy

NEW

+24

pw::bluetooth::proxy::ProxyPolicy

NEW

+20

fit::internal::null_target<>::ops

NEW

+18

fit::internal::generic_function_base<>::operator bool()

NEW

+16

__wrap_free

NEW

+12

fit::internal::inline_trivial_target_move<>()

NEW

+8

fit::internal::generic_function_base<>::destroy_target()

NEW

+8

operator delete()

NEW

+6

fit::internal::null_target<>::invoke()

NEW

+4

fit::internal::null_target_get()

NEW

+4

fit::internal::unshared_target_type_id()

NEW

+2

fit::internal::inline_target_get()

NEW

+2

fit::internal::null_target_move()

NEW

+2

fit::internal::trivial_target_destroy()

+1,336

Roadmap#

  • ACL flow control

  • Sending GATT notifications

  • CMake support

  • Receiving GATT notifications

  • Taking ownership of a L2CAP channel

  • Bazel support

  • And more…