Skip to content

Commit

Permalink
pw_bluetooth_sapphire: Read ISO data buffer info on startup
Browse files Browse the repository at this point in the history
When initializing a controller, if supported read the
controller's ISO data buffer configuration (# of buffers and max
size of each buffer), which will dictacte the behavior of the
IsochronousDataChannel object.

Bug: b/311639040
Test: pw presubmit --step gn_chre_googletest_nanopb_sapphire_build
Change-Id: Idbf1c22798aa04d10786b672c3dd16638705a89b
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/184052
Commit-Queue: Josh Conner <joshconner@google.com>
Reviewed-by: Ben Lawson <benlawson@google.com>
  • Loading branch information
josh-conner authored and CQ Bot Account committed Dec 15, 2023
1 parent e45a2d6 commit 50a77aa
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 36 deletions.
81 changes: 57 additions & 24 deletions pw_bluetooth_sapphire/host/gap/adapter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -962,26 +962,59 @@ void AdapterImpl::InitializeStep2() {
state_.low_energy_state.supported_states_ = le64toh(params->le_states);
});

// HCI_LE_Read_Buffer_Size
init_seq_runner_->QueueCommand(
hci::EmbossCommandPacket::New<
pw::bluetooth::emboss::LEReadBufferSizeCommandV1View>(
hci_spec::kLEReadBufferSizeV1),
[this](const hci::EventPacket& cmd_complete) {
if (hci_is_error(
cmd_complete, WARN, "gap", "LE read buffer size failed")) {
return;
}
auto params =
cmd_complete
.return_params<hci_spec::LEReadBufferSizeV1ReturnParams>();
uint16_t mtu = le16toh(params->hc_le_acl_data_packet_length);
uint8_t max_count = params->hc_total_num_le_acl_data_packets;
if (mtu && max_count) {
state_.low_energy_state.data_buffer_info_ =
hci::DataBufferInfo(mtu, max_count);
}
});
if (state_.IsCommandSupported(
/*octet=*/41, hci_spec::SupportedCommand::kLEReadBufferSizeV2)) {
// HCI_LE_Read_Buffer_Size [v2]
init_seq_runner_->QueueCommand(
hci::EmbossCommandPacket::New<
pw::bluetooth::emboss::LEReadBufferSizeCommandV2View>(
hci_spec::kLEReadBufferSizeV2),
[this](const hci::EmbossEventPacket& cmd_complete) {
if (hci_is_error(cmd_complete,
WARN,
"gap",
"LE read buffer size [v2] failed")) {
return;
}
auto params =
cmd_complete
.view<pw::bluetooth::emboss::
LEReadBufferSizeV2CommandCompleteEventView>();
uint16_t acl_mtu = params.le_acl_data_packet_length().Read();
uint8_t acl_max_count = params.total_num_le_acl_data_packets().Read();
if (acl_mtu && acl_max_count) {
state_.low_energy_state.acl_data_buffer_info_ =
hci::DataBufferInfo(acl_mtu, acl_max_count);
}
uint16_t iso_mtu = params.iso_data_packet_length().Read();
uint8_t iso_max_count = params.total_num_iso_data_packets().Read();
if (iso_mtu && iso_max_count) {
state_.low_energy_state.iso_data_buffer_info_ =
hci::DataBufferInfo(iso_mtu, iso_max_count);
}
});
} else {
// HCI_LE_Read_Buffer_Size [v1]
init_seq_runner_->QueueCommand(
hci::EmbossCommandPacket::New<
pw::bluetooth::emboss::LEReadBufferSizeCommandV1View>(
hci_spec::kLEReadBufferSizeV1),
[this](const hci::EventPacket& cmd_complete) {
if (hci_is_error(
cmd_complete, WARN, "gap", "LE read buffer size failed")) {
return;
}
auto params =
cmd_complete
.return_params<hci_spec::LEReadBufferSizeV1ReturnParams>();
uint16_t mtu = le16toh(params->hc_le_acl_data_packet_length);
uint8_t max_count = params->hc_total_num_le_acl_data_packets;
if (mtu && max_count) {
state_.low_energy_state.acl_data_buffer_info_ =
hci::DataBufferInfo(mtu, max_count);
}
});
}

if (state_.features.HasBit(
/*page=*/0u,
Expand Down Expand Up @@ -1071,7 +1104,7 @@ void AdapterImpl::InitializeStep3() {
BT_ASSERT(!init_seq_runner_->HasQueuedCommands());

if (!state_.bredr_data_buffer_info.IsAvailable() &&
!state_.low_energy_state.data_buffer_info().IsAvailable()) {
!state_.low_energy_state.acl_data_buffer_info().IsAvailable()) {
bt_log(ERROR, "gap", "Both BR/EDR and LE buffers are unavailable");
CompleteInitialization(/*success=*/false);
return;
Expand All @@ -1081,7 +1114,7 @@ void AdapterImpl::InitializeStep3() {
// initialize the ACLDataChannel.
if (!hci_->InitializeACLDataChannel(
state_.bredr_data_buffer_info,
state_.low_energy_state.data_buffer_info())) {
state_.low_energy_state.acl_data_buffer_info())) {
bt_log(ERROR, "gap", "Failed to initialize ACLDataChannel (step 3)");
CompleteInitialization(/*success=*/false);
return;
Expand Down Expand Up @@ -1408,10 +1441,10 @@ void AdapterImpl::UpdateInspectProperties() {

inspect_properties_.le_max_num_packets = adapter_node_.CreateUint(
"le_max_num_packets",
state_.low_energy_state.data_buffer_info().max_num_packets());
state_.low_energy_state.acl_data_buffer_info().max_num_packets());
inspect_properties_.le_max_data_length = adapter_node_.CreateUint(
"le_max_data_length",
state_.low_energy_state.data_buffer_info().max_data_length());
state_.low_energy_state.acl_data_buffer_info().max_data_length());

inspect_properties_.sco_max_num_packets = adapter_node_.CreateUint(
"sco_max_num_packets", state_.sco_buffer_info.max_num_packets());
Expand Down
34 changes: 25 additions & 9 deletions pw_bluetooth_sapphire/host/gap/adapter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1173,12 +1173,12 @@ TEST_F(AdapterTest, InspectHierarchy) {
UintIs("le_max_num_packets",
adapter()
->state()
.low_energy_state.data_buffer_info()
.low_energy_state.acl_data_buffer_info()
.max_num_packets()),
UintIs("le_max_data_length",
adapter()
->state()
.low_energy_state.data_buffer_info()
.low_energy_state.acl_data_buffer_info()
.max_data_length()),
UintIs("sco_max_num_packets",
adapter()->state().sco_buffer_info.max_num_packets()),
Expand Down Expand Up @@ -1390,26 +1390,42 @@ TEST_F(AdapterTest, BufferSizesRecordedInState) {
settings.AddLESupportedCommands();
settings.lmp_features_page0 |=
static_cast<uint64_t>(hci_spec::LMPFeature::kLESupportedHost);
settings.le_acl_data_packet_length = 1;
settings.le_acl_data_packet_length = 0x1B; // minimum supported size
settings.le_total_num_acl_data_packets = 2;
settings.acl_data_packet_length = 3;
settings.total_num_acl_data_packets = 4;
settings.synchronous_data_packet_length = 5;
settings.total_num_synchronous_data_packets = 6;
settings.iso_data_packet_length = 7;
settings.total_num_iso_data_packets = 8;
test_device()->set_settings(settings);

InitializeAdapter(std::move(init_cb));
EXPECT_TRUE(success);
EXPECT_EQ(
adapter()->state().low_energy_state.data_buffer_info().max_data_length(),
1u);
EXPECT_EQ(
adapter()->state().low_energy_state.data_buffer_info().max_num_packets(),
2u);
EXPECT_EQ(adapter()
->state()
.low_energy_state.acl_data_buffer_info()
.max_data_length(),
(uint16_t)0x1B);
EXPECT_EQ(adapter()
->state()
.low_energy_state.acl_data_buffer_info()
.max_num_packets(),
2u);
EXPECT_EQ(adapter()->state().bredr_data_buffer_info.max_data_length(), 3u);
EXPECT_EQ(adapter()->state().bredr_data_buffer_info.max_num_packets(), 4u);
EXPECT_EQ(adapter()->state().sco_buffer_info.max_data_length(), 5u);
EXPECT_EQ(adapter()->state().sco_buffer_info.max_num_packets(), 6u);
EXPECT_EQ(adapter()
->state()
.low_energy_state.iso_data_buffer_info()
.max_data_length(),
7u);
EXPECT_EQ(adapter()
->state()
.low_energy_state.iso_data_buffer_info()
.max_num_packets(),
8u);
}

TEST_F(AdapterTest, ScoDataChannelInitializedSuccessfully) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ class LowEnergyState final {
uint64_t supported_features() const { return supported_features_; }

// Returns the LE ACL data buffer capacity.
const hci::DataBufferInfo& data_buffer_info() const {
return data_buffer_info_;
const hci::DataBufferInfo& acl_data_buffer_info() const {
return acl_data_buffer_info_;
}

// Returns the ISO data buffer capacity.
const hci::DataBufferInfo& iso_data_buffer_info() const {
return iso_data_buffer_info_;
}

private:
Expand All @@ -42,7 +47,11 @@ class LowEnergyState final {

// Storage capacity information about the controller's internal ACL data
// buffers.
hci::DataBufferInfo data_buffer_info_;
hci::DataBufferInfo acl_data_buffer_info_;

// Storage capacity information about the controller's internal ISO data
// buffers.
hci::DataBufferInfo iso_data_buffer_info_;

// Local supported LE Features reported by the controller.
uint64_t supported_features_ = 0;
Expand Down

0 comments on commit 50a77aa

Please sign in to comment.