Loading tools/rootcanal/model/controller/dual_mode_controller.cc +17 −12 Original line number Diff line number Diff line Loading @@ -1717,19 +1717,24 @@ void DualModeController::SetEventFilter(CommandView command) { void DualModeController::Inquiry(CommandView command) { auto command_view = bluetooth::hci::InquiryView::Create(command); ASSERT(command_view.IsValid()); auto lap = command_view.GetLap().lap_; auto inquiry_length = command_view.GetInquiryLength(); auto num_responses = command_view.GetNumResponses(); auto max_responses = command_view.GetNumResponses(); auto length = command_view.GetInquiryLength(); DEBUG(id_, "<< Inquiry"); DEBUG(id_, " lap={}", lap); DEBUG(id_, " inquiry_length={}", inquiry_length); DEBUG(id_, " num_responses={}", num_responses); DEBUG(id_, " num_responses={}", max_responses); DEBUG(id_, " inquiry_length={}", length); auto status = link_layer_controller_.Inquiry(lap, inquiry_length, num_responses); send_event_( bluetooth::hci::InquiryStatusBuilder::Create(status, kNumCommandPackets)); if (max_responses > 0xff || length < 1 || length > 0x30) { send_event_(bluetooth::hci::InquiryStatusBuilder::Create( ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, kNumCommandPackets)); return; } link_layer_controller_.SetInquiryLAP(command_view.GetLap().lap_); link_layer_controller_.SetInquiryMaxResponses(max_responses); link_layer_controller_.StartInquiry(std::chrono::milliseconds(length * 1280)); send_event_(bluetooth::hci::InquiryStatusBuilder::Create(ErrorCode::SUCCESS, kNumCommandPackets)); } void DualModeController::InquiryCancel(CommandView command) { Loading @@ -1738,9 +1743,9 @@ void DualModeController::InquiryCancel(CommandView command) { DEBUG(id_, "<< Inquiry Cancel"); auto status = link_layer_controller_.InquiryCancel(); link_layer_controller_.InquiryCancel(); send_event_(bluetooth::hci::InquiryCancelCompleteBuilder::Create( kNumCommandPackets, status)); kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::AcceptConnectionRequest(CommandView command) { Loading tools/rootcanal/model/controller/link_layer_controller.cc +48 −59 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ namespace rootcanal { constexpr milliseconds kScanRequestTimeout(200); constexpr milliseconds kNoDelayMs(0); constexpr milliseconds kPageInterval(1000); constexpr milliseconds kInquiryInterval(500); const Address& LinkLayerController::GetAddress() const { return address_; } Loading Loading @@ -292,43 +291,6 @@ LinkLayerController::GenerateResolvablePrivateAddress(AddressWithType address, // BR/EDR Commands // ============================================================================= // HCI Inquiry command (Vol 4, Part E § 7.1.1). ErrorCode LinkLayerController::Inquiry(uint8_t lap, uint8_t inquiry_length, uint8_t num_responses) { if (inquiry_.has_value()) { INFO(id_, "inquiry is already started"); return ErrorCode::COMMAND_DISALLOWED; } if (inquiry_length < 0x1 || inquiry_length > 0x30) { INFO(id_, "invalid inquiry length ({})", inquiry_length); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Inquiry_Length parameter, added to Extended_Inquiry_Length // (see Section 6.42), specifies the total duration of the Inquiry Mode and, // when this time expires, Inquiry will be halted. std::chrono::microseconds inquiry_timeout = 1280ms * inquiry_length + std::chrono::duration_cast<milliseconds>(extended_inquiry_length_); auto now = std::chrono::steady_clock::now(); inquiry_ = InquiryState{ .lap = lap, .num_responses = num_responses, .next_inquiry_event = now + kInquiryInterval, .inquiry_timeout = now + inquiry_timeout, }; return ErrorCode::SUCCESS; } // HCI Inquiry Cancel command (Vol 4, Part E § 7.1.2). ErrorCode LinkLayerController::InquiryCancel() { inquiry_ = {}; return ErrorCode::SUCCESS; } // HCI Read Rssi command (Vol 4, Part E § 7.5.4). ErrorCode LinkLayerController::ReadRssi(uint16_t connection_handle, int8_t* rssi) { Loading Loading @@ -5199,7 +5161,10 @@ void LinkLayerController::IncomingPageResponsePacket( void LinkLayerController::Tick() { RunPendingTasks(); Paging(); Inquiring(); if (inquiry_timer_task_id_ != kInvalidTaskId) { Inquiry(); } LeAdvertising(); LeScanning(); link_manager_tick(lm_.get()); Loading Loading @@ -5427,7 +5392,7 @@ ErrorCode LinkLayerController::CreateConnection(const Address& bd_addr, } auto now = std::chrono::steady_clock::now(); page_ = PageState{ page_ = Page{ .bd_addr = bd_addr, .allow_role_switch = allow_role_switch, .next_page_event = now + kPageInterval, Loading Loading @@ -6084,7 +6049,10 @@ void LinkLayerController::Reset() { initiator_ = Initiator{}; synchronizing_ = {}; synchronized_ = {}; last_inquiry_ = steady_clock::now(); inquiry_mode_ = InquiryType::STANDARD; inquiry_lap_ = 0; inquiry_max_responses_ = 0; default_tx_phys_ = properties_.LeSupportedPhys(); default_rx_phys_ = properties_.LeSupportedPhys(); Loading @@ -6094,7 +6062,11 @@ void LinkLayerController::Reset() { current_iac_lap_list_.emplace_back(general_iac); page_ = {}; inquiry_ = {}; if (inquiry_timer_task_id_ != kInvalidTaskId) { CancelScheduledTask(inquiry_timer_task_id_); inquiry_timer_task_id_ = kInvalidTaskId; } lm_.reset(link_manager_create(controller_ops_)); ll_.reset(link_layer_create(controller_ops_)); Loading @@ -6105,7 +6077,7 @@ void LinkLayerController::Paging() { auto now = std::chrono::steady_clock::now(); if (page_.has_value() && now >= page_->page_timeout) { INFO(id_, "page timeout triggered for connection with {}", INFO("page timeout triggered for connection with {}", page_->bd_addr.ToString()); send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create( Loading @@ -6128,25 +6100,25 @@ void LinkLayerController::Paging() { } } /// Drive the logic for the Inquiry controller substate. void LinkLayerController::Inquiring() { auto now = std::chrono::steady_clock::now(); void LinkLayerController::StartInquiry(milliseconds timeout) { inquiry_timer_task_id_ = ScheduleTask(milliseconds(timeout), [this]() { LinkLayerController::InquiryTimeout(); }); } if (inquiry_.has_value() && now >= inquiry_->inquiry_timeout) { INFO(id_, "inquiry timeout triggered"); void LinkLayerController::InquiryCancel() { ASSERT(inquiry_timer_task_id_ != kInvalidTaskId); CancelScheduledTask(inquiry_timer_task_id_); inquiry_timer_task_id_ = kInvalidTaskId; } void LinkLayerController::InquiryTimeout() { if (inquiry_timer_task_id_ != kInvalidTaskId) { inquiry_timer_task_id_ = kInvalidTaskId; if (IsEventUnmasked(EventCode::INQUIRY_COMPLETE)) { send_event_( bluetooth::hci::InquiryCompleteBuilder::Create(ErrorCode::SUCCESS)); inquiry_ = {}; return; } // Send a Inquiry packet when the inquiry interval has passed. if (inquiry_.has_value() && now >= inquiry_->next_inquiry_event) { SendLinkLayerPacket(model::packets::InquiryBuilder::Create( GetAddress(), Address::kEmpty, inquiry_mode_, inquiry_->lap)); inquiry_->next_inquiry_event = now + kInquiryInterval; } } Loading @@ -6154,6 +6126,23 @@ void LinkLayerController::SetInquiryMode(uint8_t mode) { inquiry_mode_ = static_cast<model::packets::InquiryType>(mode); } void LinkLayerController::SetInquiryLAP(uint64_t lap) { inquiry_lap_ = lap; } void LinkLayerController::SetInquiryMaxResponses(uint8_t max) { inquiry_max_responses_ = max; } void LinkLayerController::Inquiry() { steady_clock::time_point now = steady_clock::now(); if (duration_cast<milliseconds>(now - last_inquiry_) < milliseconds(2000)) { return; } SendLinkLayerPacket(model::packets::InquiryBuilder::Create( GetAddress(), Address::kEmpty, inquiry_mode_, inquiry_lap_)); last_inquiry_ = now; } void LinkLayerController::SetInquiryScanEnable(bool enable) { inquiry_scan_enable_ = enable; } Loading tools/rootcanal/model/controller/link_layer_controller.h +13 −21 Original line number Diff line number Diff line Loading @@ -185,7 +185,6 @@ class LinkLayerController { void Reset(); void Paging(); void Inquiring(); void LeAdvertising(); void LeScanning(); void LeSynchronization(); Loading Loading @@ -277,7 +276,13 @@ class LinkLayerController { uint8_t LeReadNumberOfSupportedAdvertisingSets(); // Classic void StartInquiry(std::chrono::milliseconds timeout); void InquiryCancel(); void InquiryTimeout(); void SetInquiryMode(uint8_t mode); void SetInquiryLAP(uint64_t lap); void SetInquiryMaxResponses(uint8_t max); void Inquiry(); bool GetInquiryScanEnable() const { return inquiry_scan_enable_; } void SetInquiryScanEnable(bool enable); Loading Loading @@ -338,12 +343,6 @@ class LinkLayerController { // BR/EDR Commands // HCI Inquiry command (Vol 4, Part E § 7.1.1). ErrorCode Inquiry(uint8_t lap, uint8_t inquiry_length, uint8_t num_responses); // HCI Inquiry Cancel command (Vol 4, Part E § 7.1.2). ErrorCode InquiryCancel(); // HCI Read Rssi command (Vol 4, Part E § 7.5.4). ErrorCode ReadRssi(uint16_t connection_handle, int8_t* rssi); Loading Loading @@ -949,9 +948,6 @@ class LinkLayerController { // Class of Device (Vol 4, Part E § 6.26). uint32_t class_of_device_{0}; // Extended Inquiry Length (Vol 4, Part E § 6.42). slots extended_inquiry_length_{0}; // Other configuration parameters. // Current IAC LAP (Vol 4, Part E § 7.3.44). Loading Loading @@ -1176,27 +1172,23 @@ class LinkLayerController { struct ControllerOps controller_ops_; // Classic state. struct PageState { struct Page { Address bd_addr; uint8_t allow_role_switch; std::chrono::steady_clock::time_point next_page_event{}; std::chrono::steady_clock::time_point page_timeout{}; }; struct InquiryState { uint64_t lap; uint8_t num_responses; std::chrono::steady_clock::time_point next_inquiry_event{}; std::chrono::steady_clock::time_point inquiry_timeout{}; }; // Page and inquiry substates. // Page substate. // RootCanal will allow only one page request running at the same time. std::optional<PageState> page_; std::optional<InquiryState> inquiry_; std::optional<Page> page_; std::chrono::steady_clock::time_point last_inquiry_; model::packets::InquiryType inquiry_mode_{ model::packets::InquiryType::STANDARD}; TaskId inquiry_timer_task_id_ = kInvalidTaskId; uint64_t inquiry_lap_{}; uint8_t inquiry_max_responses_{}; public: // Type of scheduled tasks. Loading Loading
tools/rootcanal/model/controller/dual_mode_controller.cc +17 −12 Original line number Diff line number Diff line Loading @@ -1717,19 +1717,24 @@ void DualModeController::SetEventFilter(CommandView command) { void DualModeController::Inquiry(CommandView command) { auto command_view = bluetooth::hci::InquiryView::Create(command); ASSERT(command_view.IsValid()); auto lap = command_view.GetLap().lap_; auto inquiry_length = command_view.GetInquiryLength(); auto num_responses = command_view.GetNumResponses(); auto max_responses = command_view.GetNumResponses(); auto length = command_view.GetInquiryLength(); DEBUG(id_, "<< Inquiry"); DEBUG(id_, " lap={}", lap); DEBUG(id_, " inquiry_length={}", inquiry_length); DEBUG(id_, " num_responses={}", num_responses); DEBUG(id_, " num_responses={}", max_responses); DEBUG(id_, " inquiry_length={}", length); auto status = link_layer_controller_.Inquiry(lap, inquiry_length, num_responses); send_event_( bluetooth::hci::InquiryStatusBuilder::Create(status, kNumCommandPackets)); if (max_responses > 0xff || length < 1 || length > 0x30) { send_event_(bluetooth::hci::InquiryStatusBuilder::Create( ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, kNumCommandPackets)); return; } link_layer_controller_.SetInquiryLAP(command_view.GetLap().lap_); link_layer_controller_.SetInquiryMaxResponses(max_responses); link_layer_controller_.StartInquiry(std::chrono::milliseconds(length * 1280)); send_event_(bluetooth::hci::InquiryStatusBuilder::Create(ErrorCode::SUCCESS, kNumCommandPackets)); } void DualModeController::InquiryCancel(CommandView command) { Loading @@ -1738,9 +1743,9 @@ void DualModeController::InquiryCancel(CommandView command) { DEBUG(id_, "<< Inquiry Cancel"); auto status = link_layer_controller_.InquiryCancel(); link_layer_controller_.InquiryCancel(); send_event_(bluetooth::hci::InquiryCancelCompleteBuilder::Create( kNumCommandPackets, status)); kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::AcceptConnectionRequest(CommandView command) { Loading
tools/rootcanal/model/controller/link_layer_controller.cc +48 −59 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ namespace rootcanal { constexpr milliseconds kScanRequestTimeout(200); constexpr milliseconds kNoDelayMs(0); constexpr milliseconds kPageInterval(1000); constexpr milliseconds kInquiryInterval(500); const Address& LinkLayerController::GetAddress() const { return address_; } Loading Loading @@ -292,43 +291,6 @@ LinkLayerController::GenerateResolvablePrivateAddress(AddressWithType address, // BR/EDR Commands // ============================================================================= // HCI Inquiry command (Vol 4, Part E § 7.1.1). ErrorCode LinkLayerController::Inquiry(uint8_t lap, uint8_t inquiry_length, uint8_t num_responses) { if (inquiry_.has_value()) { INFO(id_, "inquiry is already started"); return ErrorCode::COMMAND_DISALLOWED; } if (inquiry_length < 0x1 || inquiry_length > 0x30) { INFO(id_, "invalid inquiry length ({})", inquiry_length); return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Inquiry_Length parameter, added to Extended_Inquiry_Length // (see Section 6.42), specifies the total duration of the Inquiry Mode and, // when this time expires, Inquiry will be halted. std::chrono::microseconds inquiry_timeout = 1280ms * inquiry_length + std::chrono::duration_cast<milliseconds>(extended_inquiry_length_); auto now = std::chrono::steady_clock::now(); inquiry_ = InquiryState{ .lap = lap, .num_responses = num_responses, .next_inquiry_event = now + kInquiryInterval, .inquiry_timeout = now + inquiry_timeout, }; return ErrorCode::SUCCESS; } // HCI Inquiry Cancel command (Vol 4, Part E § 7.1.2). ErrorCode LinkLayerController::InquiryCancel() { inquiry_ = {}; return ErrorCode::SUCCESS; } // HCI Read Rssi command (Vol 4, Part E § 7.5.4). ErrorCode LinkLayerController::ReadRssi(uint16_t connection_handle, int8_t* rssi) { Loading Loading @@ -5199,7 +5161,10 @@ void LinkLayerController::IncomingPageResponsePacket( void LinkLayerController::Tick() { RunPendingTasks(); Paging(); Inquiring(); if (inquiry_timer_task_id_ != kInvalidTaskId) { Inquiry(); } LeAdvertising(); LeScanning(); link_manager_tick(lm_.get()); Loading Loading @@ -5427,7 +5392,7 @@ ErrorCode LinkLayerController::CreateConnection(const Address& bd_addr, } auto now = std::chrono::steady_clock::now(); page_ = PageState{ page_ = Page{ .bd_addr = bd_addr, .allow_role_switch = allow_role_switch, .next_page_event = now + kPageInterval, Loading Loading @@ -6084,7 +6049,10 @@ void LinkLayerController::Reset() { initiator_ = Initiator{}; synchronizing_ = {}; synchronized_ = {}; last_inquiry_ = steady_clock::now(); inquiry_mode_ = InquiryType::STANDARD; inquiry_lap_ = 0; inquiry_max_responses_ = 0; default_tx_phys_ = properties_.LeSupportedPhys(); default_rx_phys_ = properties_.LeSupportedPhys(); Loading @@ -6094,7 +6062,11 @@ void LinkLayerController::Reset() { current_iac_lap_list_.emplace_back(general_iac); page_ = {}; inquiry_ = {}; if (inquiry_timer_task_id_ != kInvalidTaskId) { CancelScheduledTask(inquiry_timer_task_id_); inquiry_timer_task_id_ = kInvalidTaskId; } lm_.reset(link_manager_create(controller_ops_)); ll_.reset(link_layer_create(controller_ops_)); Loading @@ -6105,7 +6077,7 @@ void LinkLayerController::Paging() { auto now = std::chrono::steady_clock::now(); if (page_.has_value() && now >= page_->page_timeout) { INFO(id_, "page timeout triggered for connection with {}", INFO("page timeout triggered for connection with {}", page_->bd_addr.ToString()); send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create( Loading @@ -6128,25 +6100,25 @@ void LinkLayerController::Paging() { } } /// Drive the logic for the Inquiry controller substate. void LinkLayerController::Inquiring() { auto now = std::chrono::steady_clock::now(); void LinkLayerController::StartInquiry(milliseconds timeout) { inquiry_timer_task_id_ = ScheduleTask(milliseconds(timeout), [this]() { LinkLayerController::InquiryTimeout(); }); } if (inquiry_.has_value() && now >= inquiry_->inquiry_timeout) { INFO(id_, "inquiry timeout triggered"); void LinkLayerController::InquiryCancel() { ASSERT(inquiry_timer_task_id_ != kInvalidTaskId); CancelScheduledTask(inquiry_timer_task_id_); inquiry_timer_task_id_ = kInvalidTaskId; } void LinkLayerController::InquiryTimeout() { if (inquiry_timer_task_id_ != kInvalidTaskId) { inquiry_timer_task_id_ = kInvalidTaskId; if (IsEventUnmasked(EventCode::INQUIRY_COMPLETE)) { send_event_( bluetooth::hci::InquiryCompleteBuilder::Create(ErrorCode::SUCCESS)); inquiry_ = {}; return; } // Send a Inquiry packet when the inquiry interval has passed. if (inquiry_.has_value() && now >= inquiry_->next_inquiry_event) { SendLinkLayerPacket(model::packets::InquiryBuilder::Create( GetAddress(), Address::kEmpty, inquiry_mode_, inquiry_->lap)); inquiry_->next_inquiry_event = now + kInquiryInterval; } } Loading @@ -6154,6 +6126,23 @@ void LinkLayerController::SetInquiryMode(uint8_t mode) { inquiry_mode_ = static_cast<model::packets::InquiryType>(mode); } void LinkLayerController::SetInquiryLAP(uint64_t lap) { inquiry_lap_ = lap; } void LinkLayerController::SetInquiryMaxResponses(uint8_t max) { inquiry_max_responses_ = max; } void LinkLayerController::Inquiry() { steady_clock::time_point now = steady_clock::now(); if (duration_cast<milliseconds>(now - last_inquiry_) < milliseconds(2000)) { return; } SendLinkLayerPacket(model::packets::InquiryBuilder::Create( GetAddress(), Address::kEmpty, inquiry_mode_, inquiry_lap_)); last_inquiry_ = now; } void LinkLayerController::SetInquiryScanEnable(bool enable) { inquiry_scan_enable_ = enable; } Loading
tools/rootcanal/model/controller/link_layer_controller.h +13 −21 Original line number Diff line number Diff line Loading @@ -185,7 +185,6 @@ class LinkLayerController { void Reset(); void Paging(); void Inquiring(); void LeAdvertising(); void LeScanning(); void LeSynchronization(); Loading Loading @@ -277,7 +276,13 @@ class LinkLayerController { uint8_t LeReadNumberOfSupportedAdvertisingSets(); // Classic void StartInquiry(std::chrono::milliseconds timeout); void InquiryCancel(); void InquiryTimeout(); void SetInquiryMode(uint8_t mode); void SetInquiryLAP(uint64_t lap); void SetInquiryMaxResponses(uint8_t max); void Inquiry(); bool GetInquiryScanEnable() const { return inquiry_scan_enable_; } void SetInquiryScanEnable(bool enable); Loading Loading @@ -338,12 +343,6 @@ class LinkLayerController { // BR/EDR Commands // HCI Inquiry command (Vol 4, Part E § 7.1.1). ErrorCode Inquiry(uint8_t lap, uint8_t inquiry_length, uint8_t num_responses); // HCI Inquiry Cancel command (Vol 4, Part E § 7.1.2). ErrorCode InquiryCancel(); // HCI Read Rssi command (Vol 4, Part E § 7.5.4). ErrorCode ReadRssi(uint16_t connection_handle, int8_t* rssi); Loading Loading @@ -949,9 +948,6 @@ class LinkLayerController { // Class of Device (Vol 4, Part E § 6.26). uint32_t class_of_device_{0}; // Extended Inquiry Length (Vol 4, Part E § 6.42). slots extended_inquiry_length_{0}; // Other configuration parameters. // Current IAC LAP (Vol 4, Part E § 7.3.44). Loading Loading @@ -1176,27 +1172,23 @@ class LinkLayerController { struct ControllerOps controller_ops_; // Classic state. struct PageState { struct Page { Address bd_addr; uint8_t allow_role_switch; std::chrono::steady_clock::time_point next_page_event{}; std::chrono::steady_clock::time_point page_timeout{}; }; struct InquiryState { uint64_t lap; uint8_t num_responses; std::chrono::steady_clock::time_point next_inquiry_event{}; std::chrono::steady_clock::time_point inquiry_timeout{}; }; // Page and inquiry substates. // Page substate. // RootCanal will allow only one page request running at the same time. std::optional<PageState> page_; std::optional<InquiryState> inquiry_; std::optional<Page> page_; std::chrono::steady_clock::time_point last_inquiry_; model::packets::InquiryType inquiry_mode_{ model::packets::InquiryType::STANDARD}; TaskId inquiry_timer_task_id_ = kInvalidTaskId; uint64_t inquiry_lap_{}; uint8_t inquiry_max_responses_{}; public: // Type of scheduled tasks. Loading