From 50a77aa8bbe1c8e88f461b43092cae5692d3d894 Mon Sep 17 00:00:00 2001 From: Josh Conner Date: Fri, 15 Dec 2023 17:26:08 +0000 Subject: [PATCH] pw_bluetooth_sapphire: Read ISO data buffer info on startup 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 Reviewed-by: Ben Lawson --- pw_bluetooth_sapphire/host/gap/adapter.cc | 81 +++++++++++++------ .../host/gap/adapter_test.cc | 34 +++++--- .../internal/host/gap/low_energy_state.h | 15 +++- 3 files changed, 94 insertions(+), 36 deletions(-) diff --git a/pw_bluetooth_sapphire/host/gap/adapter.cc b/pw_bluetooth_sapphire/host/gap/adapter.cc index 59b807de44..82ed5d3a2d 100644 --- a/pw_bluetooth_sapphire/host/gap/adapter.cc +++ b/pw_bluetooth_sapphire/host/gap/adapter.cc @@ -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(); - 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(); + 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(); + 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, @@ -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; @@ -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; @@ -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()); diff --git a/pw_bluetooth_sapphire/host/gap/adapter_test.cc b/pw_bluetooth_sapphire/host/gap/adapter_test.cc index c1d01468f6..c0d2bdd797 100644 --- a/pw_bluetooth_sapphire/host/gap/adapter_test.cc +++ b/pw_bluetooth_sapphire/host/gap/adapter_test.cc @@ -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()), @@ -1390,26 +1390,42 @@ TEST_F(AdapterTest, BufferSizesRecordedInState) { settings.AddLESupportedCommands(); settings.lmp_features_page0 |= static_cast(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) { diff --git a/pw_bluetooth_sapphire/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_state.h b/pw_bluetooth_sapphire/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_state.h index 40cc7e23ea..88a53dc6bd 100644 --- a/pw_bluetooth_sapphire/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_state.h +++ b/pw_bluetooth_sapphire/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_state.h @@ -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: @@ -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;