Loading tools/rootcanal/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -241,6 +241,9 @@ cc_test_host { "test/controller/le/le_set_extended_scan_enable_test.cc", "test/controller/le/le_set_extended_scan_enable_test.cc", "test/controller/le/le_set_extended_scan_parameters_test.cc", "test/controller/le/le_set_extended_scan_parameters_test.cc", "test/controller/le/le_set_extended_scan_response_data_test.cc", "test/controller/le/le_set_extended_scan_response_data_test.cc", "test/controller/le/le_set_periodic_advertising_data_test.cc", "test/controller/le/le_set_periodic_advertising_enable_test.cc", "test/controller/le/le_set_periodic_advertising_parameters_test.cc", "test/controller/le/le_set_random_address_test.cc", "test/controller/le/le_set_random_address_test.cc", "test/controller/le/le_set_scan_enable_test.cc", "test/controller/le/le_set_scan_enable_test.cc", "test/controller/le/le_set_scan_parameters_test.cc", "test/controller/le/le_set_scan_parameters_test.cc", Loading tools/rootcanal/model/controller/dual_mode_controller.cc +48 −6 Original line number Original line Diff line number Diff line Loading @@ -2308,6 +2308,48 @@ void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) { kNumCommandPackets, status)); kNumCommandPackets, status)); } } void DualModeController::LeSetPeriodicAdvertisingParameters( CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingParametersView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingParameters( command_view.GetAdvertisingHandle(), command_view.GetPeriodicAdvertisingIntervalMin(), command_view.GetPeriodicAdvertisingIntervalMax(), command_view.GetIncludeTxPower()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingParametersCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetPeriodicAdvertisingData(CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingDataRawView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingData( command_view.GetAdvertisingHandle(), command_view.GetOperation(), command_view.GetAdvertisingData()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetPeriodicAdvertisingEnable(CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingEnableView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingEnable( command_view.GetEnable(), command_view.GetIncludeAdi(), command_view.GetAdvertisingHandle()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanParameters(CommandView command) { void DualModeController::LeSetExtendedScanParameters(CommandView command) { auto command_view = bluetooth::hci::LeSetExtendedScanParametersView::Create( auto command_view = bluetooth::hci::LeSetExtendedScanParametersView::Create( bluetooth::hci::LeScanningCommandView::Create(command)); bluetooth::hci::LeScanningCommandView::Create(command)); Loading Loading @@ -3960,12 +4002,12 @@ const std::unordered_map<OpCode, DualModeController::CommandHandler> &DualModeController::LeRemoveAdvertisingSet}, &DualModeController::LeRemoveAdvertisingSet}, {OpCode::LE_CLEAR_ADVERTISING_SETS, {OpCode::LE_CLEAR_ADVERTISING_SETS, &DualModeController::LeClearAdvertisingSets}, &DualModeController::LeClearAdvertisingSets}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS, {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS, //&DualModeController::LeSetPeriodicAdvertisingParameters}, &DualModeController::LeSetPeriodicAdvertisingParameters}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, //&DualModeController::LeSetPeriodicAdvertisingData}, &DualModeController::LeSetPeriodicAdvertisingData}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, //&DualModeController::LeSetPeriodicAdvertisingEnable}, &DualModeController::LeSetPeriodicAdvertisingEnable}, {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, &DualModeController::LeSetExtendedScanParameters}, &DualModeController::LeSetExtendedScanParameters}, {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, Loading tools/rootcanal/model/controller/dual_mode_controller.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -558,6 +558,11 @@ class DualModeController : public Device { // 7.8.60 // 7.8.60 void LeClearAdvertisingSets(CommandView command); void LeClearAdvertisingSets(CommandView command); // 7.8.61 - 7.8.63 void LeSetPeriodicAdvertisingParameters(CommandView command); void LeSetPeriodicAdvertisingData(CommandView command); void LeSetPeriodicAdvertisingEnable(CommandView command); // 7.8.64 // 7.8.64 void LeSetExtendedScanParameters(CommandView command); void LeSetExtendedScanParameters(CommandView command); Loading tools/rootcanal/model/controller/le_advertiser.cc +329 −7 Original line number Original line Diff line number Diff line Loading @@ -174,7 +174,7 @@ ErrorCode LinkLayerController::LeSetAdvertisingEnable(bool advertising_enable) { } } if (!advertising_enable) { if (!advertising_enable) { legacy_advertiser_.advertising_enable = false; legacy_advertiser_.Disable(); return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading Loading @@ -976,8 +976,8 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( // If Enable and Num_Sets are both set to // If Enable and Num_Sets are both set to // 0x00, then all advertising sets are disabled. // 0x00, then all advertising sets are disabled. if (!enable && sets.empty()) { if (!enable && sets.empty()) { for (auto& advertiser : extended_advertisers_) { for (auto& [_, advertiser] : extended_advertisers_) { advertiser.second.advertising_enable = false; advertiser.Disable(); } } return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading @@ -993,7 +993,7 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( if (!enable) { if (!enable) { for (auto& set : sets) { for (auto& set : sets) { auto& advertiser = extended_advertisers_[set.advertising_handle_]; auto& advertiser = extended_advertisers_[set.advertising_handle_]; advertiser.advertising_enable = false; advertiser.Disable(); } } return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading Loading @@ -1145,9 +1145,7 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( advertiser.max_extended_advertising_events = advertiser.max_extended_advertising_events = set.max_extended_advertising_events_; set.max_extended_advertising_events_; advertiser.num_completed_extended_advertising_events = 0; advertiser.num_completed_extended_advertising_events = 0; advertiser.advertising_enable = true; advertiser.Enable(); advertiser.next_event = std::chrono::steady_clock::now() + advertiser.primary_advertising_interval; if (set.duration_ > 0) { if (set.duration_ > 0) { std::chrono::milliseconds duration = std::chrono::milliseconds duration = std::chrono::milliseconds(set.duration_ * 10); std::chrono::milliseconds(set.duration_ * 10); Loading Loading @@ -1297,6 +1295,310 @@ uint16_t ExtendedAdvertiser::GetRawAdvertisingEventProperties( return mask; return mask; } } // ============================================================================= // Periodic Advertising Commands // ============================================================================= // HCI LE Set Periodic Advertising Parameters command (Vol 4, Part E § 7.8.61). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingParameters( uint8_t advertising_handle, uint16_t periodic_advertising_interval_min, uint16_t periodic_advertising_interval_max, bool /*include_tx_power*/) { // The Advertising_Handle parameter identifies the advertising set whose // periodic advertising parameters are being configured. If the corresponding // advertising set does not already exist, then the Controller shall return // the error code Unknown Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; // The Periodic_Advertising_Interval_Min parameter shall be less than or // equal to the Periodic_Advertising_Interval_Max parameter. if (periodic_advertising_interval_min < 0x6 || periodic_advertising_interval_max < 0x6 || periodic_advertising_interval_max < periodic_advertising_interval_min) { LOG_INFO("invalid periodic advertising interval range %04x - %04x", periodic_advertising_interval_min, periodic_advertising_interval_max); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the advertising set identified by the Advertising_Handle specified // scannable, connectable, legacy, or anonymous advertising, the Controller // shall return the error code Invalid HCI Command Parameters (0x12). if (advertiser.advertising_event_properties.connectable_ || advertiser.advertising_event_properties.scannable_ || advertiser.advertising_event_properties.legacy_ || advertiser.advertising_event_properties.anonymous_) { LOG_INFO( "the periodic advertising set %02x specifies scannable," " connectable, legacy or anonymous advertising", static_cast<int>(advertising_handle)); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the Host issues this command when periodic advertising is enabled for // the specified advertising set, the Controller shall return the error code // Command Disallowed (0x0C). if (advertiser.periodic_advertising_enable) { LOG_INFO("periodic advertising is enabled for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If the Advertising_Handle does not identify an advertising set that is // already configured for periodic advertising and the Controller is unable // to support more periodic advertising at present, the Controller shall // return the error code Memory Capacity Exceeded (0x07) // TODO: add controller configuration for maximum number of periodic // advertising sets. // If the advertising set already contains periodic advertising data and the // length of the data is greater than the maximum that the Controller can // transmit within a periodic advertising interval of // Periodic_Advertising_Interval_Max, the Controller shall return the error // code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( slots(periodic_advertising_interval_max))) { LOG_INFO( "the length of the periodic advertising data exceeds the maximum" " that the controller can transmit within the maximum periodic" " advertising interval"); return ErrorCode::PACKET_TOO_LONG; } advertiser.periodic_advertising_interval = slots(periodic_advertising_interval_max); return ErrorCode::SUCCESS; } // HCI LE Set Periodic Advertising Data command (Vol 4, Part E § 7.8.62). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingData( uint8_t advertising_handle, bluetooth::hci::Operation operation, const std::vector<uint8_t>& advertising_data) { // If the advertising set corresponding to the Advertising_Handle parameter // does not exist, then the Controller shall return the error code // Unknown Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; // If the advertising set has not been configured for periodic advertising, // then the Controller shall return the error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_interval.count() == 0) { LOG_INFO("periodic advertising is not configured for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If periodic advertising is currently enabled for the specified advertising // set and Operation does not have the value 0x03 or 0x04, then the Controller // shall return the error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_enable && operation != Operation::COMPLETE_ADVERTISEMENT && operation != Operation::UNCHANGED_DATA) { LOG_INFO( "periodic advertising is enabled and the operation is not" " Complete_Advertisement or Unchanged_Data"); return ErrorCode::COMMAND_DISALLOWED; } // If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero, // then the Controller shall return the error code // Invalid HCI Command Parameters (0x12). if (advertising_data.empty() && operation != Operation::COMPLETE_ADVERTISEMENT && operation != Operation::UNCHANGED_DATA) { LOG_INFO( "periodic advertising data is empty is enabled and the operation" " is not Complete_Advertisement or Unchanged_Data"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If Operation is 0x04 and: // • periodic advertising is currently disabled for the advertising set; // • the periodic advertising set contains no data; or // • Advertising_Data_Length is not zero; // then the Controller shall return the error code // Invalid HCI Command Parameters (0x12). if (operation == Operation::UNCHANGED_DATA && (!advertiser.periodic_advertising_enable || advertiser.periodic_advertising_data.empty() || !advertising_data.empty())) { LOG_INFO( "Unchanged_Data operation is used but periodic advertising is disabled;" " or the periodic advertising set contains no data;" " or the advertising data is not empty"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } switch (operation) { case Operation::INTERMEDIATE_FRAGMENT: advertiser.periodic_advertising_data.insert( advertiser.periodic_advertising_data.end(), advertising_data.begin(), advertising_data.end()); advertiser.partial_periodic_advertising_data = true; break; case Operation::FIRST_FRAGMENT: advertiser.periodic_advertising_data = advertising_data; advertiser.partial_periodic_advertising_data = true; break; case Operation::LAST_FRAGMENT: advertiser.periodic_advertising_data.insert( advertiser.periodic_advertising_data.end(), advertising_data.begin(), advertising_data.end()); advertiser.partial_periodic_advertising_data = false; break; case Operation::COMPLETE_ADVERTISEMENT: advertiser.periodic_advertising_data = advertising_data; advertiser.partial_periodic_advertising_data = false; break; case Operation::UNCHANGED_DATA: break; default: LOG_INFO("unknown operation (%x)", static_cast<int>(operation)); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the combined length of the data exceeds the capacity of the advertising // set identified by the Advertising_Handle parameter or the amount of memory // currently available, all the data shall be discarded and the Controller // shall return the error code Memory Capacity Exceeded (0x07). if (advertiser.periodic_advertising_data.size() > properties_.le_max_advertising_data_length) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum advertising data length"); advertiser.periodic_advertising_data.clear(); advertiser.partial_periodic_advertising_data = false; return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } // If the combined length of the data is greater than the maximum that the // Controller can transmit within the current periodic advertising interval // for the advertising set, all the data shall be discarded and the // Controller shall return the error code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( advertiser.periodic_advertising_interval)) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum that the controller can transmit within the current" " periodic advertising interval"); advertiser.periodic_advertising_data.clear(); advertiser.partial_periodic_advertising_data = false; return ErrorCode::PACKET_TOO_LONG; } return ErrorCode::SUCCESS; } // HCI LE Set Periodic Advertising Enable command (Vol 4, Part E § 7.8.63). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingEnable( bool enable, bool include_adi, uint8_t advertising_handle) { // If the advertising set corresponding to the Advertising_Handle parameter // does not exist, the Controller shall return the error code Unknown // Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; if (!enable) { advertiser.DisablePeriodic(); return ErrorCode::SUCCESS; } // If bit 0 of Enable is set to 1 (periodic advertising is enabled) and the // advertising set contains partial periodic advertising data, the Controller // shall return the error code Command Disallowed (0x0C). if (advertiser.partial_periodic_advertising_data) { LOG_INFO("the advertising set contains partial periodic advertising data"); return ErrorCode::COMMAND_DISALLOWED; } // If bit 0 of Enable is set to 1 and the Host has not issued the // HCI_LE_Set_Periodic_Advertising_Parameters command for the advertising set, // the Controller shall either use vendor-specified parameters or return the // error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_interval.count() == 0) { LOG_INFO("periodic advertising is not configured for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If bit 0 of Enable is set to 1 and the length of the periodic advertising // data is greater than the maximum that the Controller can transmit within // the chosen periodic advertising interval, the Controller shall return the // error code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( advertiser.periodic_advertising_interval)) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum that the controller can transmit within the current" " periodic advertising interval"); return ErrorCode::PACKET_TOO_LONG; } // If bit 0 of Enable is set to 1 and the advertising set identified by the // Advertising_Handle specified scannable, connectable, legacy, or anonymous // advertising, the Controller shall return the error code // Command Disallowed (0x0C). if (advertiser.advertising_event_properties.connectable_ || advertiser.advertising_event_properties.scannable_ || advertiser.advertising_event_properties.legacy_ || advertiser.advertising_event_properties.anonymous_) { LOG_INFO( "the periodic advertising set %02x specifies scannable," " connectable, legacy or anonymous advertising", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If bit 1 of Enable is set to 1 and the Controller does not support the // Periodic Advertising ADI Support feature, the Controller shall return an // error which should use the error code Unsupported Feature or // Parameter Value (0x11). if (include_adi && !properties_.SupportsLLFeature( LLFeaturesBits::PERIODIC_ADVERTISING_ADI_SUPPORT)) { LOG_INFO( "include ADI is true but the controller does not support the" " Periodic Advertising ADI Supported feature", static_cast<int>(advertising_handle)); return ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; } advertiser.EnablePeriodic(); return ErrorCode::SUCCESS; } uint16_t ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( slots periodic_advertising_interval) { // TODO: evaluate the maximum length of the advertising PDU that can // be physically sent in the advertising interval. return max_extended_advertising_pdu_size; } // ============================================================================= // ============================================================================= // Advertising Routines // Advertising Routines // ============================================================================= // ============================================================================= Loading Loading @@ -1514,10 +1816,30 @@ void LinkLayerController::LeAdvertising() { advertiser.primary_advertising_phy), advertiser.primary_advertising_phy), static_cast<model::packets::SecondaryPhyType>( static_cast<model::packets::SecondaryPhyType>( advertiser.secondary_advertising_phy), advertiser.secondary_advertising_phy), advertiser.periodic_advertising_interval.count(), advertiser.advertising_data), advertiser.advertising_data), advertiser.advertising_tx_power); advertiser.advertising_tx_power); } } } } // Periodic Advertising Event // Generate Link Layer Advertising events when advertising is enabled // and a full interval has passed since the last event. if (advertiser.IsPeriodicEnabled() && now >= advertiser.next_periodic_event) { advertiser.next_periodic_event += advertiser.periodic_advertising_interval; SendLeLinkLayerPacket( model::packets::LePeriodicAdvertisingPduBuilder::Create( advertiser.advertising_address.GetAddress(), Address(), static_cast<model::packets::AddressType>( advertiser.advertising_address.GetAddressType()), advertiser.advertising_sid, advertiser.advertising_tx_power, advertiser.periodic_advertising_interval.count(), advertiser.periodic_advertising_data), advertiser.advertising_tx_power); } } } } } Loading tools/rootcanal/model/controller/le_advertiser.h +47 −1 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,24 @@ class ExtendedAdvertiser : public Advertiser { : advertising_handle(advertising_handle) {} : advertising_handle(advertising_handle) {} ~ExtendedAdvertiser() = default; ~ExtendedAdvertiser() = default; void Enable() { advertising_enable = true; periodic_advertising_enable_latch = periodic_advertising_enable; next_event = std::chrono::steady_clock::now(); } void EnablePeriodic() { periodic_advertising_enable = true; periodic_advertising_enable_latch = advertising_enable; next_periodic_event = std::chrono::steady_clock::now(); } void DisablePeriodic() { periodic_advertising_enable = false; periodic_advertising_enable_latch = false; } bool IsPeriodicEnabled() const { return periodic_advertising_enable_latch; } bool IsScannable() const { return advertising_event_properties.scannable_; } bool IsScannable() const { return advertising_event_properties.scannable_; } bool IsConnectable() const { bool IsConnectable() const { Loading @@ -121,7 +139,6 @@ class ExtendedAdvertiser : public Advertiser { // Host configuration parameters. Gather the configuration from the // Host configuration parameters. Gather the configuration from the // extended advertising HCI commands. // extended advertising HCI commands. uint8_t advertising_handle; uint8_t advertising_handle; bool periodic_advertising_enable{false}; AdvertisingEventProperties advertising_event_properties{}; AdvertisingEventProperties advertising_event_properties{}; slots primary_advertising_interval{}; slots primary_advertising_interval{}; uint8_t primary_advertising_channel_map{}; uint8_t primary_advertising_channel_map{}; Loading @@ -141,6 +158,30 @@ class ExtendedAdvertiser : public Advertiser { bool partial_advertising_data{false}; bool partial_advertising_data{false}; bool partial_scan_response_data{false}; bool partial_scan_response_data{false}; // Periodic advertising configuration. // Note: the enable flag has a latch because of the semantic describe in the // specification: // // If the advertising set is not currently enabled, the periodic advertising // is not started until the advertising set is enabled. Once the advertising // set has been enabled, the Controller shall continue periodic advertising // until the Host issues an HCI_LE_Set_Periodic_Advertising_Enable command // with bit 0 of Enable set to 0 (periodic advertising is disabled). // Disabling the advertising set has no effect on the periodic advertising // once the advertising set has been enabled. // // Thus the enable latch is set when the advertising set is enabled and // periodic advertising is enabled, and cleared when periodic advertising // gets disabled. bool periodic_advertising_enable{false}; bool periodic_advertising_enable_latch{false}; slots periodic_advertising_interval{}; std::vector<uint8_t> periodic_advertising_data{}; bool partial_periodic_advertising_data{false}; // Time keeping for periodic advertising. std::chrono::steady_clock::time_point next_periodic_event{}; // Enabled state. // Enabled state. uint8_t max_extended_advertising_events{0}; uint8_t max_extended_advertising_events{0}; uint8_t num_completed_extended_advertising_events{0}; uint8_t num_completed_extended_advertising_events{0}; Loading @@ -163,6 +204,11 @@ class ExtendedAdvertiser : public Advertiser { // Reconstitute the raw Advertising_Event_Properties bitmask. // Reconstitute the raw Advertising_Event_Properties bitmask. static uint16_t GetRawAdvertisingEventProperties( static uint16_t GetRawAdvertisingEventProperties( const AdvertisingEventProperties& properties); const AdvertisingEventProperties& properties); // Compute the maximum periodic advertising data payload size for the // selected periodic advertising interval. static uint16_t GetMaxPeriodicAdvertisingDataLength( slots periodic_advertising_interval); }; }; } // namespace rootcanal } // namespace rootcanal Loading
tools/rootcanal/Android.bp +3 −0 Original line number Original line Diff line number Diff line Loading @@ -241,6 +241,9 @@ cc_test_host { "test/controller/le/le_set_extended_scan_enable_test.cc", "test/controller/le/le_set_extended_scan_enable_test.cc", "test/controller/le/le_set_extended_scan_parameters_test.cc", "test/controller/le/le_set_extended_scan_parameters_test.cc", "test/controller/le/le_set_extended_scan_response_data_test.cc", "test/controller/le/le_set_extended_scan_response_data_test.cc", "test/controller/le/le_set_periodic_advertising_data_test.cc", "test/controller/le/le_set_periodic_advertising_enable_test.cc", "test/controller/le/le_set_periodic_advertising_parameters_test.cc", "test/controller/le/le_set_random_address_test.cc", "test/controller/le/le_set_random_address_test.cc", "test/controller/le/le_set_scan_enable_test.cc", "test/controller/le/le_set_scan_enable_test.cc", "test/controller/le/le_set_scan_parameters_test.cc", "test/controller/le/le_set_scan_parameters_test.cc", Loading
tools/rootcanal/model/controller/dual_mode_controller.cc +48 −6 Original line number Original line Diff line number Diff line Loading @@ -2308,6 +2308,48 @@ void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) { kNumCommandPackets, status)); kNumCommandPackets, status)); } } void DualModeController::LeSetPeriodicAdvertisingParameters( CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingParametersView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingParameters( command_view.GetAdvertisingHandle(), command_view.GetPeriodicAdvertisingIntervalMin(), command_view.GetPeriodicAdvertisingIntervalMax(), command_view.GetIncludeTxPower()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingParametersCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetPeriodicAdvertisingData(CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingDataRawView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingData( command_view.GetAdvertisingHandle(), command_view.GetOperation(), command_view.GetAdvertisingData()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetPeriodicAdvertisingEnable(CommandView command) { auto command_view = bluetooth::hci::LeSetPeriodicAdvertisingEnableView::Create( bluetooth::hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPeriodicAdvertisingEnable( command_view.GetEnable(), command_view.GetIncludeAdi(), command_view.GetAdvertisingHandle()); send_event_( bluetooth::hci::LeSetPeriodicAdvertisingEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanParameters(CommandView command) { void DualModeController::LeSetExtendedScanParameters(CommandView command) { auto command_view = bluetooth::hci::LeSetExtendedScanParametersView::Create( auto command_view = bluetooth::hci::LeSetExtendedScanParametersView::Create( bluetooth::hci::LeScanningCommandView::Create(command)); bluetooth::hci::LeScanningCommandView::Create(command)); Loading Loading @@ -3960,12 +4002,12 @@ const std::unordered_map<OpCode, DualModeController::CommandHandler> &DualModeController::LeRemoveAdvertisingSet}, &DualModeController::LeRemoveAdvertisingSet}, {OpCode::LE_CLEAR_ADVERTISING_SETS, {OpCode::LE_CLEAR_ADVERTISING_SETS, &DualModeController::LeClearAdvertisingSets}, &DualModeController::LeClearAdvertisingSets}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS, {OpCode::LE_SET_PERIODIC_ADVERTISING_PARAMETERS, //&DualModeController::LeSetPeriodicAdvertisingParameters}, &DualModeController::LeSetPeriodicAdvertisingParameters}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, {OpCode::LE_SET_PERIODIC_ADVERTISING_DATA, //&DualModeController::LeSetPeriodicAdvertisingData}, &DualModeController::LeSetPeriodicAdvertisingData}, //{OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, {OpCode::LE_SET_PERIODIC_ADVERTISING_ENABLE, //&DualModeController::LeSetPeriodicAdvertisingEnable}, &DualModeController::LeSetPeriodicAdvertisingEnable}, {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, {OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS, &DualModeController::LeSetExtendedScanParameters}, &DualModeController::LeSetExtendedScanParameters}, {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, {OpCode::LE_SET_EXTENDED_SCAN_ENABLE, Loading
tools/rootcanal/model/controller/dual_mode_controller.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -558,6 +558,11 @@ class DualModeController : public Device { // 7.8.60 // 7.8.60 void LeClearAdvertisingSets(CommandView command); void LeClearAdvertisingSets(CommandView command); // 7.8.61 - 7.8.63 void LeSetPeriodicAdvertisingParameters(CommandView command); void LeSetPeriodicAdvertisingData(CommandView command); void LeSetPeriodicAdvertisingEnable(CommandView command); // 7.8.64 // 7.8.64 void LeSetExtendedScanParameters(CommandView command); void LeSetExtendedScanParameters(CommandView command); Loading
tools/rootcanal/model/controller/le_advertiser.cc +329 −7 Original line number Original line Diff line number Diff line Loading @@ -174,7 +174,7 @@ ErrorCode LinkLayerController::LeSetAdvertisingEnable(bool advertising_enable) { } } if (!advertising_enable) { if (!advertising_enable) { legacy_advertiser_.advertising_enable = false; legacy_advertiser_.Disable(); return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading Loading @@ -976,8 +976,8 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( // If Enable and Num_Sets are both set to // If Enable and Num_Sets are both set to // 0x00, then all advertising sets are disabled. // 0x00, then all advertising sets are disabled. if (!enable && sets.empty()) { if (!enable && sets.empty()) { for (auto& advertiser : extended_advertisers_) { for (auto& [_, advertiser] : extended_advertisers_) { advertiser.second.advertising_enable = false; advertiser.Disable(); } } return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading @@ -993,7 +993,7 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( if (!enable) { if (!enable) { for (auto& set : sets) { for (auto& set : sets) { auto& advertiser = extended_advertisers_[set.advertising_handle_]; auto& advertiser = extended_advertisers_[set.advertising_handle_]; advertiser.advertising_enable = false; advertiser.Disable(); } } return ErrorCode::SUCCESS; return ErrorCode::SUCCESS; } } Loading Loading @@ -1145,9 +1145,7 @@ ErrorCode LinkLayerController::LeSetExtendedAdvertisingEnable( advertiser.max_extended_advertising_events = advertiser.max_extended_advertising_events = set.max_extended_advertising_events_; set.max_extended_advertising_events_; advertiser.num_completed_extended_advertising_events = 0; advertiser.num_completed_extended_advertising_events = 0; advertiser.advertising_enable = true; advertiser.Enable(); advertiser.next_event = std::chrono::steady_clock::now() + advertiser.primary_advertising_interval; if (set.duration_ > 0) { if (set.duration_ > 0) { std::chrono::milliseconds duration = std::chrono::milliseconds duration = std::chrono::milliseconds(set.duration_ * 10); std::chrono::milliseconds(set.duration_ * 10); Loading Loading @@ -1297,6 +1295,310 @@ uint16_t ExtendedAdvertiser::GetRawAdvertisingEventProperties( return mask; return mask; } } // ============================================================================= // Periodic Advertising Commands // ============================================================================= // HCI LE Set Periodic Advertising Parameters command (Vol 4, Part E § 7.8.61). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingParameters( uint8_t advertising_handle, uint16_t periodic_advertising_interval_min, uint16_t periodic_advertising_interval_max, bool /*include_tx_power*/) { // The Advertising_Handle parameter identifies the advertising set whose // periodic advertising parameters are being configured. If the corresponding // advertising set does not already exist, then the Controller shall return // the error code Unknown Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; // The Periodic_Advertising_Interval_Min parameter shall be less than or // equal to the Periodic_Advertising_Interval_Max parameter. if (periodic_advertising_interval_min < 0x6 || periodic_advertising_interval_max < 0x6 || periodic_advertising_interval_max < periodic_advertising_interval_min) { LOG_INFO("invalid periodic advertising interval range %04x - %04x", periodic_advertising_interval_min, periodic_advertising_interval_max); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the advertising set identified by the Advertising_Handle specified // scannable, connectable, legacy, or anonymous advertising, the Controller // shall return the error code Invalid HCI Command Parameters (0x12). if (advertiser.advertising_event_properties.connectable_ || advertiser.advertising_event_properties.scannable_ || advertiser.advertising_event_properties.legacy_ || advertiser.advertising_event_properties.anonymous_) { LOG_INFO( "the periodic advertising set %02x specifies scannable," " connectable, legacy or anonymous advertising", static_cast<int>(advertising_handle)); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the Host issues this command when periodic advertising is enabled for // the specified advertising set, the Controller shall return the error code // Command Disallowed (0x0C). if (advertiser.periodic_advertising_enable) { LOG_INFO("periodic advertising is enabled for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If the Advertising_Handle does not identify an advertising set that is // already configured for periodic advertising and the Controller is unable // to support more periodic advertising at present, the Controller shall // return the error code Memory Capacity Exceeded (0x07) // TODO: add controller configuration for maximum number of periodic // advertising sets. // If the advertising set already contains periodic advertising data and the // length of the data is greater than the maximum that the Controller can // transmit within a periodic advertising interval of // Periodic_Advertising_Interval_Max, the Controller shall return the error // code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( slots(periodic_advertising_interval_max))) { LOG_INFO( "the length of the periodic advertising data exceeds the maximum" " that the controller can transmit within the maximum periodic" " advertising interval"); return ErrorCode::PACKET_TOO_LONG; } advertiser.periodic_advertising_interval = slots(periodic_advertising_interval_max); return ErrorCode::SUCCESS; } // HCI LE Set Periodic Advertising Data command (Vol 4, Part E § 7.8.62). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingData( uint8_t advertising_handle, bluetooth::hci::Operation operation, const std::vector<uint8_t>& advertising_data) { // If the advertising set corresponding to the Advertising_Handle parameter // does not exist, then the Controller shall return the error code // Unknown Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; // If the advertising set has not been configured for periodic advertising, // then the Controller shall return the error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_interval.count() == 0) { LOG_INFO("periodic advertising is not configured for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If periodic advertising is currently enabled for the specified advertising // set and Operation does not have the value 0x03 or 0x04, then the Controller // shall return the error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_enable && operation != Operation::COMPLETE_ADVERTISEMENT && operation != Operation::UNCHANGED_DATA) { LOG_INFO( "periodic advertising is enabled and the operation is not" " Complete_Advertisement or Unchanged_Data"); return ErrorCode::COMMAND_DISALLOWED; } // If Operation is not 0x03 or 0x04 and Advertising_Data_Length is zero, // then the Controller shall return the error code // Invalid HCI Command Parameters (0x12). if (advertising_data.empty() && operation != Operation::COMPLETE_ADVERTISEMENT && operation != Operation::UNCHANGED_DATA) { LOG_INFO( "periodic advertising data is empty is enabled and the operation" " is not Complete_Advertisement or Unchanged_Data"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If Operation is 0x04 and: // • periodic advertising is currently disabled for the advertising set; // • the periodic advertising set contains no data; or // • Advertising_Data_Length is not zero; // then the Controller shall return the error code // Invalid HCI Command Parameters (0x12). if (operation == Operation::UNCHANGED_DATA && (!advertiser.periodic_advertising_enable || advertiser.periodic_advertising_data.empty() || !advertising_data.empty())) { LOG_INFO( "Unchanged_Data operation is used but periodic advertising is disabled;" " or the periodic advertising set contains no data;" " or the advertising data is not empty"); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } switch (operation) { case Operation::INTERMEDIATE_FRAGMENT: advertiser.periodic_advertising_data.insert( advertiser.periodic_advertising_data.end(), advertising_data.begin(), advertising_data.end()); advertiser.partial_periodic_advertising_data = true; break; case Operation::FIRST_FRAGMENT: advertiser.periodic_advertising_data = advertising_data; advertiser.partial_periodic_advertising_data = true; break; case Operation::LAST_FRAGMENT: advertiser.periodic_advertising_data.insert( advertiser.periodic_advertising_data.end(), advertising_data.begin(), advertising_data.end()); advertiser.partial_periodic_advertising_data = false; break; case Operation::COMPLETE_ADVERTISEMENT: advertiser.periodic_advertising_data = advertising_data; advertiser.partial_periodic_advertising_data = false; break; case Operation::UNCHANGED_DATA: break; default: LOG_INFO("unknown operation (%x)", static_cast<int>(operation)); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // If the combined length of the data exceeds the capacity of the advertising // set identified by the Advertising_Handle parameter or the amount of memory // currently available, all the data shall be discarded and the Controller // shall return the error code Memory Capacity Exceeded (0x07). if (advertiser.periodic_advertising_data.size() > properties_.le_max_advertising_data_length) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum advertising data length"); advertiser.periodic_advertising_data.clear(); advertiser.partial_periodic_advertising_data = false; return ErrorCode::MEMORY_CAPACITY_EXCEEDED; } // If the combined length of the data is greater than the maximum that the // Controller can transmit within the current periodic advertising interval // for the advertising set, all the data shall be discarded and the // Controller shall return the error code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( advertiser.periodic_advertising_interval)) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum that the controller can transmit within the current" " periodic advertising interval"); advertiser.periodic_advertising_data.clear(); advertiser.partial_periodic_advertising_data = false; return ErrorCode::PACKET_TOO_LONG; } return ErrorCode::SUCCESS; } // HCI LE Set Periodic Advertising Enable command (Vol 4, Part E § 7.8.63). ErrorCode LinkLayerController::LeSetPeriodicAdvertisingEnable( bool enable, bool include_adi, uint8_t advertising_handle) { // If the advertising set corresponding to the Advertising_Handle parameter // does not exist, the Controller shall return the error code Unknown // Advertising Identifier (0x42). // TODO(c++20) unordered_map<>::contains if (extended_advertisers_.count(advertising_handle) == 0) { LOG_INFO("no advertising set defined with handle %02x", static_cast<int>(advertising_handle)); return ErrorCode::UNKNOWN_ADVERTISING_IDENTIFIER; } ExtendedAdvertiser& advertiser = extended_advertisers_[advertising_handle]; if (!enable) { advertiser.DisablePeriodic(); return ErrorCode::SUCCESS; } // If bit 0 of Enable is set to 1 (periodic advertising is enabled) and the // advertising set contains partial periodic advertising data, the Controller // shall return the error code Command Disallowed (0x0C). if (advertiser.partial_periodic_advertising_data) { LOG_INFO("the advertising set contains partial periodic advertising data"); return ErrorCode::COMMAND_DISALLOWED; } // If bit 0 of Enable is set to 1 and the Host has not issued the // HCI_LE_Set_Periodic_Advertising_Parameters command for the advertising set, // the Controller shall either use vendor-specified parameters or return the // error code Command Disallowed (0x0C). if (advertiser.periodic_advertising_interval.count() == 0) { LOG_INFO("periodic advertising is not configured for the set %02x", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If bit 0 of Enable is set to 1 and the length of the periodic advertising // data is greater than the maximum that the Controller can transmit within // the chosen periodic advertising interval, the Controller shall return the // error code Packet Too Long (0x45). if (advertiser.periodic_advertising_data.size() > ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( advertiser.periodic_advertising_interval)) { LOG_INFO( "the length of the combined periodic advertising data exceeds" " the maximum that the controller can transmit within the current" " periodic advertising interval"); return ErrorCode::PACKET_TOO_LONG; } // If bit 0 of Enable is set to 1 and the advertising set identified by the // Advertising_Handle specified scannable, connectable, legacy, or anonymous // advertising, the Controller shall return the error code // Command Disallowed (0x0C). if (advertiser.advertising_event_properties.connectable_ || advertiser.advertising_event_properties.scannable_ || advertiser.advertising_event_properties.legacy_ || advertiser.advertising_event_properties.anonymous_) { LOG_INFO( "the periodic advertising set %02x specifies scannable," " connectable, legacy or anonymous advertising", static_cast<int>(advertising_handle)); return ErrorCode::COMMAND_DISALLOWED; } // If bit 1 of Enable is set to 1 and the Controller does not support the // Periodic Advertising ADI Support feature, the Controller shall return an // error which should use the error code Unsupported Feature or // Parameter Value (0x11). if (include_adi && !properties_.SupportsLLFeature( LLFeaturesBits::PERIODIC_ADVERTISING_ADI_SUPPORT)) { LOG_INFO( "include ADI is true but the controller does not support the" " Periodic Advertising ADI Supported feature", static_cast<int>(advertising_handle)); return ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; } advertiser.EnablePeriodic(); return ErrorCode::SUCCESS; } uint16_t ExtendedAdvertiser::GetMaxPeriodicAdvertisingDataLength( slots periodic_advertising_interval) { // TODO: evaluate the maximum length of the advertising PDU that can // be physically sent in the advertising interval. return max_extended_advertising_pdu_size; } // ============================================================================= // ============================================================================= // Advertising Routines // Advertising Routines // ============================================================================= // ============================================================================= Loading Loading @@ -1514,10 +1816,30 @@ void LinkLayerController::LeAdvertising() { advertiser.primary_advertising_phy), advertiser.primary_advertising_phy), static_cast<model::packets::SecondaryPhyType>( static_cast<model::packets::SecondaryPhyType>( advertiser.secondary_advertising_phy), advertiser.secondary_advertising_phy), advertiser.periodic_advertising_interval.count(), advertiser.advertising_data), advertiser.advertising_data), advertiser.advertising_tx_power); advertiser.advertising_tx_power); } } } } // Periodic Advertising Event // Generate Link Layer Advertising events when advertising is enabled // and a full interval has passed since the last event. if (advertiser.IsPeriodicEnabled() && now >= advertiser.next_periodic_event) { advertiser.next_periodic_event += advertiser.periodic_advertising_interval; SendLeLinkLayerPacket( model::packets::LePeriodicAdvertisingPduBuilder::Create( advertiser.advertising_address.GetAddress(), Address(), static_cast<model::packets::AddressType>( advertiser.advertising_address.GetAddressType()), advertiser.advertising_sid, advertiser.advertising_tx_power, advertiser.periodic_advertising_interval.count(), advertiser.periodic_advertising_data), advertiser.advertising_tx_power); } } } } } Loading
tools/rootcanal/model/controller/le_advertiser.h +47 −1 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,24 @@ class ExtendedAdvertiser : public Advertiser { : advertising_handle(advertising_handle) {} : advertising_handle(advertising_handle) {} ~ExtendedAdvertiser() = default; ~ExtendedAdvertiser() = default; void Enable() { advertising_enable = true; periodic_advertising_enable_latch = periodic_advertising_enable; next_event = std::chrono::steady_clock::now(); } void EnablePeriodic() { periodic_advertising_enable = true; periodic_advertising_enable_latch = advertising_enable; next_periodic_event = std::chrono::steady_clock::now(); } void DisablePeriodic() { periodic_advertising_enable = false; periodic_advertising_enable_latch = false; } bool IsPeriodicEnabled() const { return periodic_advertising_enable_latch; } bool IsScannable() const { return advertising_event_properties.scannable_; } bool IsScannable() const { return advertising_event_properties.scannable_; } bool IsConnectable() const { bool IsConnectable() const { Loading @@ -121,7 +139,6 @@ class ExtendedAdvertiser : public Advertiser { // Host configuration parameters. Gather the configuration from the // Host configuration parameters. Gather the configuration from the // extended advertising HCI commands. // extended advertising HCI commands. uint8_t advertising_handle; uint8_t advertising_handle; bool periodic_advertising_enable{false}; AdvertisingEventProperties advertising_event_properties{}; AdvertisingEventProperties advertising_event_properties{}; slots primary_advertising_interval{}; slots primary_advertising_interval{}; uint8_t primary_advertising_channel_map{}; uint8_t primary_advertising_channel_map{}; Loading @@ -141,6 +158,30 @@ class ExtendedAdvertiser : public Advertiser { bool partial_advertising_data{false}; bool partial_advertising_data{false}; bool partial_scan_response_data{false}; bool partial_scan_response_data{false}; // Periodic advertising configuration. // Note: the enable flag has a latch because of the semantic describe in the // specification: // // If the advertising set is not currently enabled, the periodic advertising // is not started until the advertising set is enabled. Once the advertising // set has been enabled, the Controller shall continue periodic advertising // until the Host issues an HCI_LE_Set_Periodic_Advertising_Enable command // with bit 0 of Enable set to 0 (periodic advertising is disabled). // Disabling the advertising set has no effect on the periodic advertising // once the advertising set has been enabled. // // Thus the enable latch is set when the advertising set is enabled and // periodic advertising is enabled, and cleared when periodic advertising // gets disabled. bool periodic_advertising_enable{false}; bool periodic_advertising_enable_latch{false}; slots periodic_advertising_interval{}; std::vector<uint8_t> periodic_advertising_data{}; bool partial_periodic_advertising_data{false}; // Time keeping for periodic advertising. std::chrono::steady_clock::time_point next_periodic_event{}; // Enabled state. // Enabled state. uint8_t max_extended_advertising_events{0}; uint8_t max_extended_advertising_events{0}; uint8_t num_completed_extended_advertising_events{0}; uint8_t num_completed_extended_advertising_events{0}; Loading @@ -163,6 +204,11 @@ class ExtendedAdvertiser : public Advertiser { // Reconstitute the raw Advertising_Event_Properties bitmask. // Reconstitute the raw Advertising_Event_Properties bitmask. static uint16_t GetRawAdvertisingEventProperties( static uint16_t GetRawAdvertisingEventProperties( const AdvertisingEventProperties& properties); const AdvertisingEventProperties& properties); // Compute the maximum periodic advertising data payload size for the // selected periodic advertising interval. static uint16_t GetMaxPeriodicAdvertisingDataLength( slots periodic_advertising_interval); }; }; } // namespace rootcanal } // namespace rootcanal