Skip to content

Commit

Permalink
pw_bluetooth_sapphire: Implement PrivilegedPeripheral API
Browse files Browse the repository at this point in the history
Support the public address type when a privileged client requests it.
Otherwise default back to the random address type. Add unit tests.

Bug: 362316463
Test: bazel run --config=fuchsia //pw_bluetooth_sapphire/fuchsia:tests_qemu
Change-Id: I8d2c96be4745545e4ed87ed7cb3e506cf42bd5da
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/241712
Docs-Not-Needed: Lulu Wang <luluwang@google.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Reviewed-by: Ben Lawson <benlawson@google.com>
Pigweed-Auto-Submit: Lulu Wang <luluwang@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
Lulu Wang authored and CQ Bot Account committed Oct 29, 2024
1 parent b901805 commit 0dff116
Show file tree
Hide file tree
Showing 26 changed files with 887 additions and 124 deletions.
8 changes: 8 additions & 0 deletions pw_bluetooth_sapphire/fuchsia/host/fidl/helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2902,6 +2902,14 @@ fuchsia::bluetooth::le::CisEstablishedParameters CisEstablishedParametersToFidl(
return params_out;
}

bt::DeviceAddress::Type FidlToDeviceAddressType(fbt::AddressType addr_type) {
switch (addr_type) {
case fbt::AddressType::PUBLIC:
return bt::DeviceAddress::Type::kLEPublic;
case fbt::AddressType::RANDOM:
return bt::DeviceAddress::Type::kLERandom;
}
}
} // namespace bthost::fidl_helpers

// static
Expand Down
6 changes: 6 additions & 0 deletions pw_bluetooth_sapphire/fuchsia/host/fidl/host_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ void HostServer::RequestProtocol(fhost::ProtocolRequest request) {
BindServer<ProfileServer>(adapter()->AsWeakPtr(),
std::move(request.profile()));
break;
case fhost::ProtocolRequest::Tag::kPrivilegedPeripheral:
BindServer<LowEnergyPrivilegedPeripheralServer>(
adapter()->AsWeakPtr(),
gatt_,
std::move(request.privileged_peripheral()));
break;
default:
bt_log(WARN, "fidl", "received unknown protocol request");
// The unknown protocol will be closed when `request` is destroyed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,11 @@ LowEnergyPeripheralServer::AdvertisementInstanceDeprecated::Register(
LowEnergyPeripheralServer::LowEnergyPeripheralServer(
bt::gap::Adapter::WeakPtr adapter,
bt::gatt::GATT::WeakPtr gatt,
fidl::InterfaceRequest<Peripheral> request)
fidl::InterfaceRequest<Peripheral> request,
bool privileged)
: AdapterServerBase(std::move(adapter), this, std::move(request)),
gatt_(std::move(gatt)),
privileged_(privileged),
weak_self_(this) {}

LowEnergyPeripheralServer::~LowEnergyPeripheralServer() {
Expand All @@ -254,19 +256,32 @@ void LowEnergyPeripheralServer::Advertise(
return;
}

// TODO(fxbug.dev/42156474): As a temporary hack until multiple advertisements
// is supported, don't allow more than one advertisement. The current behavior
// of hci::LegacyLowEnergyAdvertiser is to replace the current advertisement,
// which is not the intended behavior of `Advertise`. NOTE: This is
// insufficient when there are multiple Peripheral clients advertising, but
// that is the status quo with `StartAdvertising` anyway (the last advertiser
// wins).
// TODO: https://fxbug.dev/42156474 - As a temporary hack until multiple
// advertisements is supported, don't allow more than one advertisement. The
// current behavior of hci::LegacyLowEnergyAdvertiser is to replace the
// current advertisement, which is not the intended behavior of `Advertise`.
// NOTE: This is insufficient when there are multiple Peripheral clients
// advertising, but that is the status quo with `StartAdvertising` anyway (the
// last advertiser wins).
if (!advertisements_.empty()) {
callback(fpromise::error(fble::PeripheralError::FAILED));
return;
}

AdvertisementInstanceId instance_id = next_advertisement_instance_id_++;

// Non-privileged clients should not be able to advertise with a public
// address, so we default to a random address type.
if (!privileged_ && parameters.has_address_type() &&
parameters.address_type() == fuchsia::bluetooth::AddressType::PUBLIC) {
bt_log(WARN,
LOG_TAG,
"Cannot advertise public address (instance id: %zu)",
instance_id);
callback(fpromise::error(fble::PeripheralError::INVALID_PARAMETERS));
return;
}

auto [iter, inserted] =
advertisements_.try_emplace(instance_id,
this,
Expand Down Expand Up @@ -494,8 +509,8 @@ void LowEnergyPeripheralServer::StartAdvertisingInternal(
// `connection_options` is present or the deprecated `connectable` parameter
// is true, advertisements will be connectable. `connectable_parameter` was
// the predecessor of `connection_options` and
// TODO(fxbug.dev/42121197): will be removed once all consumers of it have
// migrated to `connection_options`.
// TODO: https://fxbug.dev/42121197 - will be removed once all consumers of it
// have migrated to `connection_options`.
bool connectable = parameters.has_connection_options() ||
(parameters.has_connectable() && parameters.connectable());
if (connectable) {
Expand Down Expand Up @@ -550,6 +565,12 @@ void LowEnergyPeripheralServer::StartAdvertisingInternal(
extended_pdu = parameters.advertising_procedure().is_extended();
}

std::optional<bt::DeviceAddress::Type> address_type = std::nullopt;
if (parameters.has_address_type()) {
address_type =
fidl_helpers::FidlToDeviceAddressType(parameters.address_type());
}

PW_CHECK(adapter()->le());
adapter()->le()->StartAdvertising(std::move(adv_data),
std::move(scan_rsp),
Expand All @@ -558,7 +579,43 @@ void LowEnergyPeripheralServer::StartAdvertisingInternal(
/*anonymous=*/false,
include_tx_power_level,
std::move(connectable_params),
address_type,
std::move(status_cb));
}

LowEnergyPrivilegedPeripheralServer::LowEnergyPrivilegedPeripheralServer(
const bt::gap::Adapter::WeakPtr& adapter,
bt::gatt::GATT::WeakPtr gatt,
fidl::InterfaceRequest<fuchsia::bluetooth::le::PrivilegedPeripheral>
request)
: AdapterServerBase(adapter, this, std::move(request)), weak_self_(this) {
fidl::InterfaceHandle<fuchsia::bluetooth::le::Peripheral> handle;
le_peripheral_server_ = std::make_unique<LowEnergyPeripheralServer>(
adapter, std::move(gatt), handle.NewRequest(), /*privileged=*/true);
}

void LowEnergyPrivilegedPeripheralServer::Advertise(
fuchsia::bluetooth::le::AdvertisingParameters parameters,
fidl::InterfaceHandle<fuchsia::bluetooth::le::AdvertisedPeripheral>
advertised_peripheral,
AdvertiseCallback callback) {
le_peripheral_server_->Advertise(std::move(parameters),
std::move(advertised_peripheral),
std::move(callback));
}

void LowEnergyPrivilegedPeripheralServer::StartAdvertising(
fble::AdvertisingParameters parameters,
::fidl::InterfaceRequest<fble::AdvertisingHandle> token,
StartAdvertisingCallback callback) {
le_peripheral_server_->StartAdvertising(
std::move(parameters), std::move(token), std::move(callback));
}

void LowEnergyPrivilegedPeripheralServer::ListenL2cap(
fble::ChannelListenerRegistryListenL2capRequest request,
ListenL2capCallback callback) {
le_peripheral_server_->ListenL2cap(std::move(request), std::move(callback));
}

} // namespace bthost
Loading

0 comments on commit 0dff116

Please sign in to comment.