Loading system/gd/hci/controller.cc +126 −17 Original line number Diff line number Diff line Loading @@ -86,24 +86,28 @@ struct Controller::impl { BindOnce(&Controller::impl::le_read_supported_states_handler, common::Unretained(this)), module_.GetHandler()); if (is_support(OpCode::LE_READ_MAXIMUM_DATA_LENGTH)) { if (is_supported(OpCode::LE_READ_MAXIMUM_DATA_LENGTH)) { hci_->EnqueueCommand(LeReadMaximumDataLengthBuilder::Create(), BindOnce(&Controller::impl::le_read_maximum_data_length_handler, common::Unretained(this)), module_.GetHandler()); } if (is_support(OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH)) { if (is_supported(OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH)) { hci_->EnqueueCommand( LeReadMaximumAdvertisingDataLengthBuilder::Create(), BindOnce(&Controller::impl::le_read_maximum_advertising_data_length_handler, common::Unretained(this)), module_.GetHandler()); } if (is_support(OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS)) { if (is_supported(OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS)) { hci_->EnqueueCommand( LeReadNumberOfSupportedAdvertisingSetsBuilder::Create(), BindOnce(&Controller::impl::le_read_number_of_supported_advertising_sets_handler, common::Unretained(this)), module_.GetHandler()); } hci_->EnqueueCommand(LeGetVendorCapabilitiesBuilder::Create(), BindOnce(&Controller::impl::le_get_vendor_capabilities_handler, common::Unretained(this)), module_.GetHandler()); // We only need to synchronize the last read. Make BD_ADDR to be the last one. std::promise<void> promise; auto future = promise.get_future(); Loading Loading @@ -264,20 +268,98 @@ struct Controller::impl { le_number_supported_advertising_sets_ = complete_view.GetNumberSupportedAdvertisingSets(); } void le_get_vendor_capabilities_handler(CommandCompleteView view) { auto complete_view = LeGetVendorCapabilitiesCompleteView::Create(view); vendor_capabilities_.is_supported_ = 0x00; vendor_capabilities_.max_advt_instances_ = 0x00; vendor_capabilities_.offloaded_resolution_of_private_address_ = 0x00; vendor_capabilities_.total_scan_results_storage_ = 0x00; vendor_capabilities_.max_irk_list_sz_ = 0x00; vendor_capabilities_.filtering_support_ = 0x00; vendor_capabilities_.max_filter_ = 0x00; vendor_capabilities_.activity_energy_info_support_ = 0x00; vendor_capabilities_.version_supported_ = 0x00; vendor_capabilities_.version_supported_ = 0x00; vendor_capabilities_.total_num_of_advt_tracked_ = 0x00; vendor_capabilities_.extended_scan_support_ = 0x00; vendor_capabilities_.debug_logging_supported_ = 0x00; vendor_capabilities_.le_address_generation_offloading_support_ = 0x00; vendor_capabilities_.a2dp_source_offload_capability_mask_ = 0x00; vendor_capabilities_.bluetooth_quality_report_support_ = 0x00; if (complete_view.IsValid()) { vendor_capabilities_.is_supported_ = 0x01; // v0.55 BaseVendorCapabilities base_vendor_capabilities = complete_view.GetBaseVendorCapabilities(); vendor_capabilities_.max_advt_instances_ = base_vendor_capabilities.max_advt_instances_; vendor_capabilities_.offloaded_resolution_of_private_address_ = base_vendor_capabilities.offloaded_resolution_of_private_address_; vendor_capabilities_.total_scan_results_storage_ = base_vendor_capabilities.total_scan_results_storage_; vendor_capabilities_.max_irk_list_sz_ = base_vendor_capabilities.max_irk_list_sz_; vendor_capabilities_.filtering_support_ = base_vendor_capabilities.filtering_support_; vendor_capabilities_.max_filter_ = base_vendor_capabilities.max_filter_; vendor_capabilities_.activity_energy_info_support_ = base_vendor_capabilities.activity_energy_info_support_; if (complete_view.GetPayload().size() == 0) { vendor_capabilities_.version_supported_ = 55; return; } // v0.95 auto v95 = LeGetVendorCapabilitiesComplete095View::Create(complete_view); if (!v95.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.95"); return; } vendor_capabilities_.version_supported_ = v95.GetVersionSupported(); vendor_capabilities_.total_num_of_advt_tracked_ = v95.GetTotalNumOfAdvtTracked(); vendor_capabilities_.extended_scan_support_ = v95.GetExtendedScanSupport(); vendor_capabilities_.debug_logging_supported_ = v95.GetDebugLoggingSupported(); if (vendor_capabilities_.version_supported_ <= 95 || complete_view.GetPayload().size() == 0) { return; } // v0.96 auto v96 = LeGetVendorCapabilitiesComplete096View::Create(v95); if (!v96.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.96"); return; } vendor_capabilities_.le_address_generation_offloading_support_ = v96.GetLeAddressGenerationOffloadingSupport(); if (vendor_capabilities_.version_supported_ <= 96 || complete_view.GetPayload().size() == 0) { return; } // v0.98 auto v98 = LeGetVendorCapabilitiesComplete098View::Create(v96); if (!v98.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.98"); return; } vendor_capabilities_.a2dp_source_offload_capability_mask_ = v98.GetA2dpSourceOffloadCapabilityMask(); vendor_capabilities_.bluetooth_quality_report_support_ = v98.GetBluetoothQualityReportSupport(); } } void set_event_mask(uint64_t event_mask) { std::unique_ptr<SetEventMaskBuilder> packet = SetEventMaskBuilder::Create(event_mask); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand(std::move(packet), BindOnce(&Controller::impl::check_status<SetEventMaskCompleteView>, common::Unretained(this)), module_.GetHandler()); } void reset() { std::unique_ptr<ResetBuilder> packet = ResetBuilder::Create(); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand(std::move(packet), BindOnce(&Controller::impl::check_status<ResetCompleteView>, common::Unretained(this)), module_.GetHandler()); } void set_event_filter(std::unique_ptr<SetEventFilterBuilder> packet) { hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<SetEventFilterCompleteView>, common::Unretained(this)), module_.GetHandler()); } Loading @@ -289,7 +371,9 @@ struct Controller::impl { std::copy(std::begin(local_name), std::end(local_name), std::begin(local_name_array)); std::unique_ptr<WriteLocalNameBuilder> packet = WriteLocalNameBuilder::Create(local_name_array); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<WriteLocalNameCompleteView>, common::Unretained(this)), module_.GetHandler()); } Loading @@ -298,16 +382,28 @@ struct Controller::impl { std::unique_ptr<HostBufferSizeBuilder> packet = HostBufferSizeBuilder::Create(host_acl_data_packet_length, host_synchronous_data_packet_length, host_total_num_acl_data_packets, host_total_num_synchronous_data_packets); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<HostBufferSizeCompleteView>, common::Unretained(this)), module_.GetHandler()); } void le_set_event_mask(uint64_t le_event_mask) { std::unique_ptr<LeSetEventMaskBuilder> packet = LeSetEventMaskBuilder::Create(le_event_mask); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<LeSetEventMaskCompleteView>, common::Unretained(this)), module_.GetHandler()); } template <class T> void check_status(CommandCompleteView view) { ASSERT(view.IsValid()); auto status_view = T::Create(view); ASSERT(status_view.IsValid()); ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS); } #define OP_CODE_MAPPING(name) \ case OpCode::name: { \ uint16_t index = (uint16_t)OpCodeIndex::name; \ Loading @@ -320,7 +416,7 @@ struct Controller::impl { return supported; \ } bool is_support(OpCode op_code) { bool is_supported(OpCode op_code) { switch (op_code) { OP_CODE_MAPPING(INQUIRY) OP_CODE_MAPPING(INQUIRY_CANCEL) Loading Loading @@ -537,15 +633,23 @@ struct Controller::impl { OP_CODE_MAPPING(LE_SET_PRIVACY_MODE) // vendor specific case OpCode::LE_GET_VENDOR_CAPABILITIES: return vendor_capabilities_.is_supported_ == 0x01; case OpCode::LE_MULTI_ADVT: return vendor_capabilities_.max_advt_instances_ != 0x00; case OpCode::LE_BATCH_SCAN: return vendor_capabilities_.total_scan_results_storage_ != 0x00; case OpCode::LE_ADV_FILTER: return vendor_capabilities_.filtering_support_ == 0x01; case OpCode::LE_TRACK_ADV: return vendor_capabilities_.total_num_of_advt_tracked_ > 0; case OpCode::LE_ENERGY_INFO: return vendor_capabilities_.activity_energy_info_support_ == 0x01; case OpCode::LE_EXTENDED_SCAN_PARAMS: return vendor_capabilities_.extended_scan_support_ == 0x01; case OpCode::CONTROLLER_DEBUG_INFO: return vendor_capabilities_.debug_logging_supported_ == 0x01; case OpCode::CONTROLLER_A2DP_OPCODE: return true; return vendor_capabilities_.a2dp_source_offload_capability_mask_ != 0x00; // undefined in local_supported_commands_ case OpCode::CREATE_NEW_UNIT_KEY: case OpCode::READ_LOCAL_SUPPORTED_COMMANDS: Loading Loading @@ -580,6 +684,7 @@ struct Controller::impl { LeMaximumDataLength le_maximum_data_length_; uint16_t le_maximum_advertising_data_length_; uint16_t le_number_supported_advertising_sets_; VendorCapabilities vendor_capabilities_; }; // namespace hci Controller::Controller() : impl_(std::make_unique<impl>(*this)) {} Loading Loading @@ -732,8 +837,12 @@ uint16_t Controller::GetControllerLeNumberOfSupportedAdverisingSets() { return impl_->le_number_supported_advertising_sets_; } bool Controller::IsSupport(bluetooth::hci::OpCode op_code) { return impl_->is_support(op_code); VendorCapabilities Controller::GetControllerVendorCapabilities() { return impl_->vendor_capabilities_; } bool Controller::IsSupported(bluetooth::hci::OpCode op_code) { return impl_->is_supported(op_code); } const ModuleFactory Controller::Factory = ModuleFactory([]() { return new Controller(); }); Loading system/gd/hci/controller.h +3 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,9 @@ class Controller : public Module { uint16_t GetControllerLeNumberOfSupportedAdverisingSets(); bool IsSupport(OpCode op_code); VendorCapabilities GetControllerVendorCapabilities(); bool IsSupported(OpCode op_code); static const ModuleFactory Factory; Loading system/gd/hci/controller_test.cc +61 −6 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ constexpr uint16_t kHandle1 = 0x123; constexpr uint16_t kCredits1 = 0x78; constexpr uint16_t kHandle2 = 0x456; constexpr uint16_t kCredits2 = 0x9a; uint16_t feature_spec_version = 55; PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { auto bytes = std::make_shared<std::vector<uint8_t>>(); Loading Loading @@ -153,6 +154,25 @@ class TestHciLayer : public HciLayer { event_builder = LeReadNumberOfSupportedAdvertisingSetsCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, 0xF0); } break; case (OpCode::LE_GET_VENDOR_CAPABILITIES): { BaseVendorCapabilities base_vendor_capabilities; base_vendor_capabilities.max_advt_instances_ = 0x10; base_vendor_capabilities.offloaded_resolution_of_private_address_ = 0x01; base_vendor_capabilities.total_scan_results_storage_ = 0x2800; base_vendor_capabilities.max_irk_list_sz_ = 0x20; base_vendor_capabilities.filtering_support_ = 0x01; base_vendor_capabilities.max_filter_ = 0x10; base_vendor_capabilities.activity_energy_info_support_ = 0x01; auto payload = std::make_unique<RawBuilder>(); if (feature_spec_version > 55) { std::vector<uint8_t> payload_bytes = {0x20, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00}; payload->AddOctets2(feature_spec_version); payload->AddOctets(payload_bytes); } event_builder = LeGetVendorCapabilitiesCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, base_vendor_capabilities, std::move(payload)); } break; case (OpCode::SET_EVENT_MASK): case (OpCode::RESET): case (OpCode::SET_EVENT_FILTER): Loading Loading @@ -365,12 +385,47 @@ TEST_F(ControllerTest, send_le_set_event_mask_command) { } TEST_F(ControllerTest, is_supported_test) { ASSERT_TRUE(controller_->IsSupport(OpCode::INQUIRY)); ASSERT_TRUE(controller_->IsSupport(OpCode::REJECT_CONNECTION_REQUEST)); ASSERT_TRUE(controller_->IsSupport(OpCode::ACCEPT_CONNECTION_REQUEST)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_REMOVE_ADVERTISING_SET)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_CLEAR_ADVERTISING_SETS)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM)); ASSERT_TRUE(controller_->IsSupported(OpCode::INQUIRY)); ASSERT_TRUE(controller_->IsSupported(OpCode::REJECT_CONNECTION_REQUEST)); ASSERT_TRUE(controller_->IsSupported(OpCode::ACCEPT_CONNECTION_REQUEST)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_REMOVE_ADVERTISING_SET)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_CLEAR_ADVERTISING_SETS)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM)); } TEST_F(ControllerTest, feature_spec_version_055_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 55); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_FALSE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 95; } TEST_F(ControllerTest, feature_spec_version_095_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 95); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 96; } TEST_F(ControllerTest, feature_spec_version_096_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 96); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 98; } TEST_F(ControllerTest, feature_spec_version_098_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 98); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_TRUE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); } std::promise<void> credits1_set; Loading system/gd/hci/hci_packets.pdl +50 −1 Original line number Diff line number Diff line Loading @@ -2420,7 +2420,56 @@ packet LeSetPrivacyMode : LeSecurityCommand (op_code = LE_SET_PRIVACY_MODE) { // VENDOR_SPECIFIC packet LeGetVendorCapabilities : VendorCommand (op_code = LE_GET_VENDOR_CAPABILITIES) { _payload_, // placeholder (unimplemented) } struct VendorCapabilities { is_supported : 8, max_advt_instances: 8, offloaded_resolution_of_private_address : 8, total_scan_results_storage: 16, max_irk_list_sz: 8, filtering_support: 8, max_filter: 8, activity_energy_info_support: 8, version_supported: 16, total_num_of_advt_tracked: 16, extended_scan_support: 8, debug_logging_supported: 8, le_address_generation_offloading_support: 8, a2dp_source_offload_capability_mask: 32, bluetooth_quality_report_support: 8 } struct BaseVendorCapabilities { max_advt_instances: 8, offloaded_resolution_of_private_address : 8, total_scan_results_storage: 16, max_irk_list_sz: 8, filtering_support: 8, max_filter: 8, activity_energy_info_support: 8, } packet LeGetVendorCapabilitiesComplete : CommandComplete (command_op_code = LE_GET_VENDOR_CAPABILITIES) { status : ErrorCode, base_vendor_capabilities : BaseVendorCapabilities, _payload_, } packet LeGetVendorCapabilitiesComplete095 : LeGetVendorCapabilitiesComplete { version_supported: 16, total_num_of_advt_tracked: 16, extended_scan_support: 8, debug_logging_supported: 8, _payload_, } packet LeGetVendorCapabilitiesComplete096 : LeGetVendorCapabilitiesComplete095 { le_address_generation_offloading_support: 8, _payload_, } packet LeGetVendorCapabilitiesComplete098 : LeGetVendorCapabilitiesComplete096 { a2dp_source_offload_capability_mask: 32, bluetooth_quality_report_support: 8 } packet LeMultiAdvt : VendorCommand (op_code = LE_MULTI_ADVT) { Loading Loading
system/gd/hci/controller.cc +126 −17 Original line number Diff line number Diff line Loading @@ -86,24 +86,28 @@ struct Controller::impl { BindOnce(&Controller::impl::le_read_supported_states_handler, common::Unretained(this)), module_.GetHandler()); if (is_support(OpCode::LE_READ_MAXIMUM_DATA_LENGTH)) { if (is_supported(OpCode::LE_READ_MAXIMUM_DATA_LENGTH)) { hci_->EnqueueCommand(LeReadMaximumDataLengthBuilder::Create(), BindOnce(&Controller::impl::le_read_maximum_data_length_handler, common::Unretained(this)), module_.GetHandler()); } if (is_support(OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH)) { if (is_supported(OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH)) { hci_->EnqueueCommand( LeReadMaximumAdvertisingDataLengthBuilder::Create(), BindOnce(&Controller::impl::le_read_maximum_advertising_data_length_handler, common::Unretained(this)), module_.GetHandler()); } if (is_support(OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS)) { if (is_supported(OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS)) { hci_->EnqueueCommand( LeReadNumberOfSupportedAdvertisingSetsBuilder::Create(), BindOnce(&Controller::impl::le_read_number_of_supported_advertising_sets_handler, common::Unretained(this)), module_.GetHandler()); } hci_->EnqueueCommand(LeGetVendorCapabilitiesBuilder::Create(), BindOnce(&Controller::impl::le_get_vendor_capabilities_handler, common::Unretained(this)), module_.GetHandler()); // We only need to synchronize the last read. Make BD_ADDR to be the last one. std::promise<void> promise; auto future = promise.get_future(); Loading Loading @@ -264,20 +268,98 @@ struct Controller::impl { le_number_supported_advertising_sets_ = complete_view.GetNumberSupportedAdvertisingSets(); } void le_get_vendor_capabilities_handler(CommandCompleteView view) { auto complete_view = LeGetVendorCapabilitiesCompleteView::Create(view); vendor_capabilities_.is_supported_ = 0x00; vendor_capabilities_.max_advt_instances_ = 0x00; vendor_capabilities_.offloaded_resolution_of_private_address_ = 0x00; vendor_capabilities_.total_scan_results_storage_ = 0x00; vendor_capabilities_.max_irk_list_sz_ = 0x00; vendor_capabilities_.filtering_support_ = 0x00; vendor_capabilities_.max_filter_ = 0x00; vendor_capabilities_.activity_energy_info_support_ = 0x00; vendor_capabilities_.version_supported_ = 0x00; vendor_capabilities_.version_supported_ = 0x00; vendor_capabilities_.total_num_of_advt_tracked_ = 0x00; vendor_capabilities_.extended_scan_support_ = 0x00; vendor_capabilities_.debug_logging_supported_ = 0x00; vendor_capabilities_.le_address_generation_offloading_support_ = 0x00; vendor_capabilities_.a2dp_source_offload_capability_mask_ = 0x00; vendor_capabilities_.bluetooth_quality_report_support_ = 0x00; if (complete_view.IsValid()) { vendor_capabilities_.is_supported_ = 0x01; // v0.55 BaseVendorCapabilities base_vendor_capabilities = complete_view.GetBaseVendorCapabilities(); vendor_capabilities_.max_advt_instances_ = base_vendor_capabilities.max_advt_instances_; vendor_capabilities_.offloaded_resolution_of_private_address_ = base_vendor_capabilities.offloaded_resolution_of_private_address_; vendor_capabilities_.total_scan_results_storage_ = base_vendor_capabilities.total_scan_results_storage_; vendor_capabilities_.max_irk_list_sz_ = base_vendor_capabilities.max_irk_list_sz_; vendor_capabilities_.filtering_support_ = base_vendor_capabilities.filtering_support_; vendor_capabilities_.max_filter_ = base_vendor_capabilities.max_filter_; vendor_capabilities_.activity_energy_info_support_ = base_vendor_capabilities.activity_energy_info_support_; if (complete_view.GetPayload().size() == 0) { vendor_capabilities_.version_supported_ = 55; return; } // v0.95 auto v95 = LeGetVendorCapabilitiesComplete095View::Create(complete_view); if (!v95.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.95"); return; } vendor_capabilities_.version_supported_ = v95.GetVersionSupported(); vendor_capabilities_.total_num_of_advt_tracked_ = v95.GetTotalNumOfAdvtTracked(); vendor_capabilities_.extended_scan_support_ = v95.GetExtendedScanSupport(); vendor_capabilities_.debug_logging_supported_ = v95.GetDebugLoggingSupported(); if (vendor_capabilities_.version_supported_ <= 95 || complete_view.GetPayload().size() == 0) { return; } // v0.96 auto v96 = LeGetVendorCapabilitiesComplete096View::Create(v95); if (!v96.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.96"); return; } vendor_capabilities_.le_address_generation_offloading_support_ = v96.GetLeAddressGenerationOffloadingSupport(); if (vendor_capabilities_.version_supported_ <= 96 || complete_view.GetPayload().size() == 0) { return; } // v0.98 auto v98 = LeGetVendorCapabilitiesComplete098View::Create(v96); if (!v98.IsValid()) { LOG_ERROR("invalid data for hci requirements v0.98"); return; } vendor_capabilities_.a2dp_source_offload_capability_mask_ = v98.GetA2dpSourceOffloadCapabilityMask(); vendor_capabilities_.bluetooth_quality_report_support_ = v98.GetBluetoothQualityReportSupport(); } } void set_event_mask(uint64_t event_mask) { std::unique_ptr<SetEventMaskBuilder> packet = SetEventMaskBuilder::Create(event_mask); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand(std::move(packet), BindOnce(&Controller::impl::check_status<SetEventMaskCompleteView>, common::Unretained(this)), module_.GetHandler()); } void reset() { std::unique_ptr<ResetBuilder> packet = ResetBuilder::Create(); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand(std::move(packet), BindOnce(&Controller::impl::check_status<ResetCompleteView>, common::Unretained(this)), module_.GetHandler()); } void set_event_filter(std::unique_ptr<SetEventFilterBuilder> packet) { hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<SetEventFilterCompleteView>, common::Unretained(this)), module_.GetHandler()); } Loading @@ -289,7 +371,9 @@ struct Controller::impl { std::copy(std::begin(local_name), std::end(local_name), std::begin(local_name_array)); std::unique_ptr<WriteLocalNameBuilder> packet = WriteLocalNameBuilder::Create(local_name_array); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<WriteLocalNameCompleteView>, common::Unretained(this)), module_.GetHandler()); } Loading @@ -298,16 +382,28 @@ struct Controller::impl { std::unique_ptr<HostBufferSizeBuilder> packet = HostBufferSizeBuilder::Create(host_acl_data_packet_length, host_synchronous_data_packet_length, host_total_num_acl_data_packets, host_total_num_synchronous_data_packets); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<HostBufferSizeCompleteView>, common::Unretained(this)), module_.GetHandler()); } void le_set_event_mask(uint64_t le_event_mask) { std::unique_ptr<LeSetEventMaskBuilder> packet = LeSetEventMaskBuilder::Create(le_event_mask); hci_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandCompleteView complete) { /* TODO */ }), hci_->EnqueueCommand( std::move(packet), BindOnce(&Controller::impl::check_status<LeSetEventMaskCompleteView>, common::Unretained(this)), module_.GetHandler()); } template <class T> void check_status(CommandCompleteView view) { ASSERT(view.IsValid()); auto status_view = T::Create(view); ASSERT(status_view.IsValid()); ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS); } #define OP_CODE_MAPPING(name) \ case OpCode::name: { \ uint16_t index = (uint16_t)OpCodeIndex::name; \ Loading @@ -320,7 +416,7 @@ struct Controller::impl { return supported; \ } bool is_support(OpCode op_code) { bool is_supported(OpCode op_code) { switch (op_code) { OP_CODE_MAPPING(INQUIRY) OP_CODE_MAPPING(INQUIRY_CANCEL) Loading Loading @@ -537,15 +633,23 @@ struct Controller::impl { OP_CODE_MAPPING(LE_SET_PRIVACY_MODE) // vendor specific case OpCode::LE_GET_VENDOR_CAPABILITIES: return vendor_capabilities_.is_supported_ == 0x01; case OpCode::LE_MULTI_ADVT: return vendor_capabilities_.max_advt_instances_ != 0x00; case OpCode::LE_BATCH_SCAN: return vendor_capabilities_.total_scan_results_storage_ != 0x00; case OpCode::LE_ADV_FILTER: return vendor_capabilities_.filtering_support_ == 0x01; case OpCode::LE_TRACK_ADV: return vendor_capabilities_.total_num_of_advt_tracked_ > 0; case OpCode::LE_ENERGY_INFO: return vendor_capabilities_.activity_energy_info_support_ == 0x01; case OpCode::LE_EXTENDED_SCAN_PARAMS: return vendor_capabilities_.extended_scan_support_ == 0x01; case OpCode::CONTROLLER_DEBUG_INFO: return vendor_capabilities_.debug_logging_supported_ == 0x01; case OpCode::CONTROLLER_A2DP_OPCODE: return true; return vendor_capabilities_.a2dp_source_offload_capability_mask_ != 0x00; // undefined in local_supported_commands_ case OpCode::CREATE_NEW_UNIT_KEY: case OpCode::READ_LOCAL_SUPPORTED_COMMANDS: Loading Loading @@ -580,6 +684,7 @@ struct Controller::impl { LeMaximumDataLength le_maximum_data_length_; uint16_t le_maximum_advertising_data_length_; uint16_t le_number_supported_advertising_sets_; VendorCapabilities vendor_capabilities_; }; // namespace hci Controller::Controller() : impl_(std::make_unique<impl>(*this)) {} Loading Loading @@ -732,8 +837,12 @@ uint16_t Controller::GetControllerLeNumberOfSupportedAdverisingSets() { return impl_->le_number_supported_advertising_sets_; } bool Controller::IsSupport(bluetooth::hci::OpCode op_code) { return impl_->is_support(op_code); VendorCapabilities Controller::GetControllerVendorCapabilities() { return impl_->vendor_capabilities_; } bool Controller::IsSupported(bluetooth::hci::OpCode op_code) { return impl_->is_supported(op_code); } const ModuleFactory Controller::Factory = ModuleFactory([]() { return new Controller(); }); Loading
system/gd/hci/controller.h +3 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,9 @@ class Controller : public Module { uint16_t GetControllerLeNumberOfSupportedAdverisingSets(); bool IsSupport(OpCode op_code); VendorCapabilities GetControllerVendorCapabilities(); bool IsSupported(OpCode op_code); static const ModuleFactory Factory; Loading
system/gd/hci/controller_test.cc +61 −6 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ constexpr uint16_t kHandle1 = 0x123; constexpr uint16_t kCredits1 = 0x78; constexpr uint16_t kHandle2 = 0x456; constexpr uint16_t kCredits2 = 0x9a; uint16_t feature_spec_version = 55; PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { auto bytes = std::make_shared<std::vector<uint8_t>>(); Loading Loading @@ -153,6 +154,25 @@ class TestHciLayer : public HciLayer { event_builder = LeReadNumberOfSupportedAdvertisingSetsCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, 0xF0); } break; case (OpCode::LE_GET_VENDOR_CAPABILITIES): { BaseVendorCapabilities base_vendor_capabilities; base_vendor_capabilities.max_advt_instances_ = 0x10; base_vendor_capabilities.offloaded_resolution_of_private_address_ = 0x01; base_vendor_capabilities.total_scan_results_storage_ = 0x2800; base_vendor_capabilities.max_irk_list_sz_ = 0x20; base_vendor_capabilities.filtering_support_ = 0x01; base_vendor_capabilities.max_filter_ = 0x10; base_vendor_capabilities.activity_energy_info_support_ = 0x01; auto payload = std::make_unique<RawBuilder>(); if (feature_spec_version > 55) { std::vector<uint8_t> payload_bytes = {0x20, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00}; payload->AddOctets2(feature_spec_version); payload->AddOctets(payload_bytes); } event_builder = LeGetVendorCapabilitiesCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, base_vendor_capabilities, std::move(payload)); } break; case (OpCode::SET_EVENT_MASK): case (OpCode::RESET): case (OpCode::SET_EVENT_FILTER): Loading Loading @@ -365,12 +385,47 @@ TEST_F(ControllerTest, send_le_set_event_mask_command) { } TEST_F(ControllerTest, is_supported_test) { ASSERT_TRUE(controller_->IsSupport(OpCode::INQUIRY)); ASSERT_TRUE(controller_->IsSupport(OpCode::REJECT_CONNECTION_REQUEST)); ASSERT_TRUE(controller_->IsSupport(OpCode::ACCEPT_CONNECTION_REQUEST)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_REMOVE_ADVERTISING_SET)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_CLEAR_ADVERTISING_SETS)); ASSERT_FALSE(controller_->IsSupport(OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM)); ASSERT_TRUE(controller_->IsSupported(OpCode::INQUIRY)); ASSERT_TRUE(controller_->IsSupported(OpCode::REJECT_CONNECTION_REQUEST)); ASSERT_TRUE(controller_->IsSupported(OpCode::ACCEPT_CONNECTION_REQUEST)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_REMOVE_ADVERTISING_SET)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_CLEAR_ADVERTISING_SETS)); ASSERT_FALSE(controller_->IsSupported(OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM)); } TEST_F(ControllerTest, feature_spec_version_055_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 55); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_FALSE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 95; } TEST_F(ControllerTest, feature_spec_version_095_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 95); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 96; } TEST_F(ControllerTest, feature_spec_version_096_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 96); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); feature_spec_version = 98; } TEST_F(ControllerTest, feature_spec_version_098_test) { EXPECT_EQ(controller_->GetControllerVendorCapabilities().version_supported_, 98); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_MULTI_ADVT)); EXPECT_TRUE(controller_->IsSupported(OpCode::LE_TRACK_ADV)); EXPECT_FALSE(controller_->IsSupported(OpCode::CONTROLLER_DEBUG_INFO)); EXPECT_TRUE(controller_->IsSupported(OpCode::CONTROLLER_A2DP_OPCODE)); } std::promise<void> credits1_set; Loading
system/gd/hci/hci_packets.pdl +50 −1 Original line number Diff line number Diff line Loading @@ -2420,7 +2420,56 @@ packet LeSetPrivacyMode : LeSecurityCommand (op_code = LE_SET_PRIVACY_MODE) { // VENDOR_SPECIFIC packet LeGetVendorCapabilities : VendorCommand (op_code = LE_GET_VENDOR_CAPABILITIES) { _payload_, // placeholder (unimplemented) } struct VendorCapabilities { is_supported : 8, max_advt_instances: 8, offloaded_resolution_of_private_address : 8, total_scan_results_storage: 16, max_irk_list_sz: 8, filtering_support: 8, max_filter: 8, activity_energy_info_support: 8, version_supported: 16, total_num_of_advt_tracked: 16, extended_scan_support: 8, debug_logging_supported: 8, le_address_generation_offloading_support: 8, a2dp_source_offload_capability_mask: 32, bluetooth_quality_report_support: 8 } struct BaseVendorCapabilities { max_advt_instances: 8, offloaded_resolution_of_private_address : 8, total_scan_results_storage: 16, max_irk_list_sz: 8, filtering_support: 8, max_filter: 8, activity_energy_info_support: 8, } packet LeGetVendorCapabilitiesComplete : CommandComplete (command_op_code = LE_GET_VENDOR_CAPABILITIES) { status : ErrorCode, base_vendor_capabilities : BaseVendorCapabilities, _payload_, } packet LeGetVendorCapabilitiesComplete095 : LeGetVendorCapabilitiesComplete { version_supported: 16, total_num_of_advt_tracked: 16, extended_scan_support: 8, debug_logging_supported: 8, _payload_, } packet LeGetVendorCapabilitiesComplete096 : LeGetVendorCapabilitiesComplete095 { le_address_generation_offloading_support: 8, _payload_, } packet LeGetVendorCapabilitiesComplete098 : LeGetVendorCapabilitiesComplete096 { a2dp_source_offload_capability_mask: 32, bluetooth_quality_report_support: 8 } packet LeMultiAdvt : VendorCommand (op_code = LE_MULTI_ADVT) { Loading