From 3ec77bca9116478b2fef8ac9ba2518c5f7397c21 Mon Sep 17 00:00:00 2001 From: Henri Chataing <henrichataing@google.com> Date: Tue, 12 Apr 2022 11:52:58 +0000 Subject: [PATCH] Root-Canal: Add PDL definition of LL feature bits The LE local supported features mask was previously defined as an hexadecimal value, making it complex to read and edit. Define an enum with LL feature bit values, and initialize the le_supported_features_ field in DeviceProperties using an explicit feature list. Bug: 228326164 Test: VCS PTS tests against Eiffel Change-Id: I2bbc1b6ac4f6f825437ad889ba910192e6a2d7d8 --- system/gd/hci/hci_packets.pdl | 52 +++++++++++++++++++ .../model/controller/dual_mode_controller.cc | 19 +++++++ .../model/controller/dual_mode_controller.h | 3 ++ .../model/devices/device_properties.cc | 20 ++++++- .../model/devices/device_properties.h | 27 +++++++++- 5 files changed, 119 insertions(+), 2 deletions(-) diff --git a/system/gd/hci/hci_packets.pdl b/system/gd/hci/hci_packets.pdl index 351c6e67533..caae4744652 100644 --- a/system/gd/hci/hci_packets.pdl +++ b/system/gd/hci/hci_packets.pdl @@ -2994,6 +2994,58 @@ test LeReadBufferSizeV1Complete { "\x0e\x07\x01\x02\x20\x00\xfb\x00\x10", } +enum LLFeaturesBits : 64 { + // Byte 0 + LE_ENCRYPTION = 0x0000000000000001, + CONNECTION_PARAMETERS_REQUEST_PROCEDURE = 0x0000000000000002, + EXTENDED_REJECT_INDICATION = 0x0000000000000004, + PERIPHERAL_INITIATED_FEATURES_EXCHANGE = 0x0000000000000008, + LE_PING = 0x0000000000000010, + LE_DATA_PACKET_LENGTH_EXTENSION = 0x0000000000000020, + LL_PRIVACY = 0x0000000000000040, + EXTENDED_SCANNER_FILTER_POLICIES = 0x0000000000000080, + + // Byte 1 + LE_2M_PHY = 0x0000000000000100, + STABLE_MODULATION_INDEX_TRANSMITTER = 0x0000000000000200, + STABLE_MODULATION_INDEX_RECEIVER = 0x0000000000000400, + LE_CODED_PHY = 0x0000000000000800, + LE_EXTENDED_ADVERTISING = 0x0000000000001000, + LE_PERIODIC_ADVERTISING = 0x0000000000002000, + CHANNEL_SELECTION_ALGORITHM_2 = 0x0000000000004000, + LE_POWER_CLASS_1 = 0x0000000000008000, + + // Byte 2 + MINIMUM_NUMBER_OF_USED_CHANNELS_PROCEDURE = 0x0000000000010000, + CONNECTION_CTE_REQUEST = 0x0000000000020000, + CONNECTION_CTE_RESPONSE = 0x0000000000040000, + CONNECTIONLESS_CTE_TRANSMITTER = 0x0000000000080000, + CONNECTIONLESS_CTE_RECEIVER = 0x0000000000100000, + ANTENNA_SWITCHING_DURING_CTE_TRANSMISSION = 0x0000000000200000, + ANTENNA_SWITCHING_DURING_CTE_RECEPTION = 0x0000000000400000, + RECEIVING_CONSTANT_TONE_EXTENSIONS = 0x0000000000800000, + + // Byte 3 + PERIODIC_ADVERTISING_SYNC_TRANSFER_SENDER = 0x0000000001000000, + PERIODIC_ADVERTISING_SYNC_TRANSFER_RECIPIENT = 0x0000000002000000, + SLEEP_CLOCK_ACCURACY_UPDATES = 0x0000000004000000, + REMOTE_PUBLIC_KEY_VALIDATION = 0x0000000008000000, + CONNECTED_ISOCHRONOUS_STREAM_CENTRAL = 0x0000000010000000, + CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL = 0x0000000020000000, + ISOCHRONOUS_BROADCASTER = 0x0000000040000000, + SYNCHRONIZED_RECEIVER = 0x0000000080000000, + + // Byte 4 + CONNECTED_ISOCHRONOUS_STREAM_HOST_SUPPORT = 0x0000000100000000, + LE_POWER_CONTROL_REQUEST = 0x0000000200000000, + LE_POWER_CONTROL_REQUEST_BIS = 0x0000000400000000, + LE_PATH_LOSS_MONITORING = 0x0000000800000000, + PERIODIC_ADVERTISING_ADI_SUPPORT = 0x0000001000000000, + CONNECTION_SUBRATING = 0x0000002000000000, + CONNECTION_SUBRATING_HOST_SUPPORT = 0x0000004000000000, + CHANNEL_CLASSIFICATION = 0x0000008000000000, +} + packet LeReadLocalSupportedFeatures : Command (op_code = LE_READ_LOCAL_SUPPORTED_FEATURES) { } diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc index cae5a5546e1..b9ada7bbdfa 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.cc +++ b/tools/rootcanal/model/controller/dual_mode_controller.cc @@ -199,6 +199,7 @@ DualModeController::DualModeController(const std::string& properties_filename, SET_SUPPORTED(DELETE_STORED_LINK_KEY, DeleteStoredLinkKey); SET_SUPPORTED(REMOTE_NAME_REQUEST, RemoteNameRequest); SET_SUPPORTED(LE_SET_EVENT_MASK, LeSetEventMask); + SET_SUPPORTED(LE_SET_HOST_FEATURE, LeSetHostFeature); SET_SUPPORTED(LE_READ_BUFFER_SIZE_V1, LeReadBufferSize); SET_SUPPORTED(LE_READ_BUFFER_SIZE_V2, LeReadBufferSizeV2); SET_SUPPORTED(LE_READ_LOCAL_SUPPORTED_FEATURES, LeReadLocalSupportedFeatures); @@ -1598,6 +1599,19 @@ void DualModeController::LeSetEventMask(CommandView command) { kNumCommandPackets, ErrorCode::SUCCESS)); } +void DualModeController::LeSetHostFeature(CommandView command) { + auto command_view = gd_hci::LeSetHostFeatureView::Create(command); + ASSERT(command_view.IsValid()); + // TODO: if the controller has active connections, return COMMAND_DISALLOED + ErrorCode error_code = properties_.SetLeHostFeature( + static_cast<uint8_t>(command_view.GetBitNumber()), + static_cast<uint8_t>(command_view.GetBitValue())) + ? ErrorCode::SUCCESS + : ErrorCode::UNSUPORTED_FEATURE_OR_PARAMETER_VALUE; + send_event_(bluetooth::hci::LeSetHostFeatureCompleteBuilder::Create( + kNumCommandPackets, error_code)); +} + void DualModeController::LeReadBufferSize(CommandView command) { auto command_view = gd_hci::LeReadBufferSizeV1View::Create(command); ASSERT(command_view.IsValid()); @@ -1652,6 +1666,11 @@ void DualModeController::LeSetResovalablePrivateAddressTimeout( void DualModeController::LeReadLocalSupportedFeatures(CommandView command) { auto command_view = gd_hci::LeReadLocalSupportedFeaturesView::Create(command); ASSERT(command_view.IsValid()); + LOG_INFO( + "%s | LeReadLocalSupportedFeatures (%016llx)", + properties_.GetAddress().ToString().c_str(), + static_cast<unsigned long long>(properties_.GetLeSupportedFeatures())); + send_event_( bluetooth::hci::LeReadLocalSupportedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, diff --git a/tools/rootcanal/model/controller/dual_mode_controller.h b/tools/rootcanal/model/controller/dual_mode_controller.h index 8650393409a..59307bf405c 100644 --- a/tools/rootcanal/model/controller/dual_mode_controller.h +++ b/tools/rootcanal/model/controller/dual_mode_controller.h @@ -586,6 +586,9 @@ class DualModeController : public Device { void LeSetupIsoDataPath(CommandView packet_view); void LeRemoveIsoDataPath(CommandView packet_view); + // 7.8.115 + void LeSetHostFeature(CommandView packet_view); + // Vendor-specific Commands void LeVendorSleepMode(CommandView args); diff --git a/tools/rootcanal/model/devices/device_properties.cc b/tools/rootcanal/model/devices/device_properties.cc index 24acbb22c23..a2bade689f7 100644 --- a/tools/rootcanal/model/devices/device_properties.cc +++ b/tools/rootcanal/model/devices/device_properties.cc @@ -74,7 +74,6 @@ DeviceProperties::DeviceProperties(const std::string& file_name) // Use SetSupportedComands() to change what's supported. for (int i = 35; i < 64; i++) supported_commands_[i] = 0x00; - le_supported_features_ = 0x1f; le_supported_states_ = 0x3ffffffffff; le_vendor_cap_ = {}; @@ -122,4 +121,23 @@ DeviceProperties::DeviceProperties(const std::string& file_name) &le_resolving_list_ignore_reasons_); } +bool DeviceProperties::SetLeHostFeature(uint8_t bit_number, uint8_t bit_value) { + if (bit_number >= 64 || bit_value > 1) return false; + + uint64_t bit_mask = UINT64_C(1) << bit_number; + if (bit_mask != + static_cast<uint64_t>( + LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_HOST_SUPPORT) && + bit_mask != static_cast<uint64_t>( + LLFeaturesBits::CONNECTION_SUBRATING_HOST_SUPPORT)) + return false; + + if (bit_value == 0) + le_supported_features_ &= ~bit_mask; + else if (bit_value == 1) + le_supported_features_ |= bit_mask; + + return true; +} + } // namespace rootcanal diff --git a/tools/rootcanal/model/devices/device_properties.h b/tools/rootcanal/model/devices/device_properties.h index 279ce7241d7..3f61c3bc90a 100644 --- a/tools/rootcanal/model/devices/device_properties.h +++ b/tools/rootcanal/model/devices/device_properties.h @@ -30,6 +30,7 @@ namespace rootcanal { using ::bluetooth::hci::Address; using ::bluetooth::hci::ClassOfDevice; using ::bluetooth::hci::EventCode; +using ::bluetooth::hci::LLFeaturesBits; using ::bluetooth::hci::LMPFeaturesPage0Bits; using ::bluetooth::hci::LMPFeaturesPage1Bits; @@ -102,6 +103,28 @@ static constexpr uint64_t Page1LmpFeatures() { return value; } +static constexpr uint64_t LlFeatures() { + LLFeaturesBits features[] = { + LLFeaturesBits::LE_ENCRYPTION, + LLFeaturesBits::CONNECTION_PARAMETERS_REQUEST_PROCEDURE, + LLFeaturesBits::EXTENDED_REJECT_INDICATION, + LLFeaturesBits::PERIPHERAL_INITIATED_FEATURES_EXCHANGE, + LLFeaturesBits::LE_PING, + + LLFeaturesBits::EXTENDED_SCANNER_FILTER_POLICIES, + LLFeaturesBits::LE_EXTENDED_ADVERTISING, + + // TODO: breaks AVD boot tests with LE audio + // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_CENTRAL, + // LLFeaturesBits::CONNECTED_ISOCHRONOUS_STREAM_PERIPHERAL, + }; + + uint64_t value = 0; + for (unsigned i = 0; i < sizeof(features) / sizeof(*features); i++) + value |= static_cast<uint64_t>(features[i]); + return value; +} + class DeviceProperties { public: explicit DeviceProperties(const std::string& file_name = ""); @@ -278,6 +301,8 @@ class DeviceProperties { void SetEventMask(uint64_t mask) { event_mask_ = mask; } + bool SetLeHostFeature(uint8_t bit_number, uint8_t bit_value); + bool IsUnmasked(EventCode event) const { uint64_t bit = UINT64_C(1) << (static_cast<uint8_t>(event) - 1); return (event_mask_ & bit) != 0; @@ -445,7 +470,7 @@ class DeviceProperties { uint8_t num_le_data_packets_; uint8_t le_connect_list_size_; uint8_t le_resolving_list_size_; - uint64_t le_supported_features_{0x075b3fd8fe8ffeff}; + uint64_t le_supported_features_{LlFeatures()}; int8_t le_advertising_physical_channel_tx_power_{0x00}; uint64_t le_supported_states_; uint64_t le_event_mask_{0x01f}; -- GitLab