• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "l2cap/classic/internal/signalling_manager.h"
18 
19 #include <chrono>
20 
21 #include "common/bind.h"
22 #include "l2cap/classic/internal/channel_configuration_state.h"
23 #include "l2cap/classic/internal/link.h"
24 #include "l2cap/internal/data_pipeline_manager.h"
25 #include "l2cap/l2cap_packets.h"
26 #include "os/log.h"
27 #include "packet/raw_builder.h"
28 
29 namespace bluetooth {
30 namespace l2cap {
31 namespace classic {
32 namespace internal {
33 static constexpr auto kTimeout = std::chrono::seconds(3);
34 
GetCommandsFromPacketView(PacketView<kLittleEndian> packet)35 static std::vector<ControlView> GetCommandsFromPacketView(PacketView<kLittleEndian> packet) {
36   size_t curr = 0;
37   size_t end = packet.size();
38   std::vector<ControlView> result;
39   while (curr < end) {
40     auto sub_view = packet.GetLittleEndianSubview(curr, end);
41     auto control = ControlView::Create(sub_view);
42     if (!control.IsValid()) {
43       return {};
44     }
45     result.push_back(control);
46     curr += 1 + 1 + 2 + control.GetPayload().size();
47   }
48   return result;
49 }
50 
ClassicSignallingManager(os::Handler * handler,Link * link,l2cap::internal::DataPipelineManager * data_pipeline_manager,DynamicChannelServiceManagerImpl * dynamic_service_manager,l2cap::internal::DynamicChannelAllocator * channel_allocator,FixedChannelServiceManagerImpl * fixed_service_manager)51 ClassicSignallingManager::ClassicSignallingManager(os::Handler* handler, Link* link,
52                                                    l2cap::internal::DataPipelineManager* data_pipeline_manager,
53                                                    DynamicChannelServiceManagerImpl* dynamic_service_manager,
54                                                    l2cap::internal::DynamicChannelAllocator* channel_allocator,
55                                                    FixedChannelServiceManagerImpl* fixed_service_manager)
56     : handler_(handler), link_(link), data_pipeline_manager_(data_pipeline_manager),
57       dynamic_service_manager_(dynamic_service_manager), channel_allocator_(channel_allocator),
58       fixed_service_manager_(fixed_service_manager), alarm_(handler) {
59   ASSERT(handler_ != nullptr);
60   ASSERT(link_ != nullptr);
61   signalling_channel_ = link_->AllocateFixedChannel(kClassicSignallingCid);
62   signalling_channel_->GetQueueUpEnd()->RegisterDequeue(
63       handler_, common::Bind(&ClassicSignallingManager::on_incoming_packet, common::Unretained(this)));
64   enqueue_buffer_ =
65       std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(signalling_channel_->GetQueueUpEnd());
66 }
67 
~ClassicSignallingManager()68 ClassicSignallingManager::~ClassicSignallingManager() {
69   alarm_.Cancel();
70   signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
71   signalling_channel_ = nullptr;
72   enqueue_buffer_->Clear();
73   enqueue_buffer_.reset();
74 }
75 
OnCommandReject(CommandRejectView command_reject_view)76 void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
77   if (command_just_sent_.signal_id_ != command_reject_view.GetIdentifier()) {
78     LOG_WARN("Unexpected command reject: no pending request");
79     return;
80   }
81   if (command_just_sent_.command_code_ == CommandCode::INFORMATION_REQUEST &&
82       command_just_sent_.info_type_ == InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) {
83     link_->OnRemoteExtendedFeatureReceived(false, false);
84   }
85   alarm_.Cancel();
86   handle_send_next_command();
87 
88   LOG_INFO("Command rejected");
89 }
90 
SendConnectionRequest(Psm psm,Cid local_cid)91 void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
92   dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
93       link_->GetDevice(),
94       dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
95       handler_->BindOnceOn(
96           this,
97           &ClassicSignallingManager::on_security_result_for_outgoing,
98           SecurityEnforcementType::LINK_KEY,
99           psm,
100           local_cid));
101 }
102 
on_security_result_for_outgoing(SecurityEnforcementType type,Psm psm,Cid local_cid,bool result)103 void ClassicSignallingManager::on_security_result_for_outgoing(
104     SecurityEnforcementType type, Psm psm, Cid local_cid, bool result) {
105   if (enqueue_buffer_.get() == nullptr) {
106     LOG_ERROR("Got security result callback after deletion");
107     return;
108   }
109   if (!result) {
110     LOG_WARN("Security requirement can't be satisfied. Dropping connection request");
111     DynamicChannelManager::ConnectionResult connection_result{
112         .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK,
113         .hci_error = hci::ErrorCode::SUCCESS,
114         .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
115     };
116     link_->OnOutgoingConnectionRequestFail(local_cid, connection_result);
117     return;
118   }
119   if (type == SecurityEnforcementType::LINK_KEY && !link_->IsAuthenticated() &&
120       dynamic_service_manager_->GetService(psm)->GetSecurityPolicy() !=
121           SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK) {
122     link_->Encrypt();
123     // TODO(b/171253721): If we can receive ENCRYPTION_CHANGE event, we can send command after callback is received.
124   }
125 
126   PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}};
127   next_signal_id_++;
128   pending_commands_.push(std::move(pending_command));
129   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
130     handle_send_next_command();
131   }
132 }
133 
send_configuration_request(Cid remote_cid,std::vector<std::unique_ptr<ConfigurationOption>> config)134 void ClassicSignallingManager::send_configuration_request(Cid remote_cid,
135                                                           std::vector<std::unique_ptr<ConfigurationOption>> config) {
136   PendingCommand pending_command = {next_signal_id_,  CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {},
137                                     std::move(config)};
138   next_signal_id_++;
139   pending_commands_.push(std::move(pending_command));
140   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
141     handle_send_next_command();
142   }
143 }
144 
SendDisconnectionRequest(Cid local_cid,Cid remote_cid)145 void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
146   PendingCommand pending_command = {
147       next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
148   next_signal_id_++;
149   pending_commands_.push(std::move(pending_command));
150   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
151     handle_send_next_command();
152   }
153 }
154 
SendInformationRequest(InformationRequestInfoType type)155 void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) {
156   PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}};
157   next_signal_id_++;
158   pending_commands_.push(std::move(pending_command));
159   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
160     handle_send_next_command();
161   }
162 }
163 
SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload)164 void ClassicSignallingManager::SendEchoRequest(std::unique_ptr<packet::RawBuilder> payload) {
165   LOG_WARN("Not supported");
166 }
167 
CancelAlarm()168 void ClassicSignallingManager::CancelAlarm() {
169   alarm_.Cancel();
170 }
171 
OnConnectionRequest(SignalId signal_id,Psm psm,Cid remote_cid)172 void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid) {
173   if (!IsPsmValid(psm)) {
174     LOG_WARN("Invalid psm received from remote psm:%d remote_cid:%d", psm, remote_cid);
175     send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
176                              ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
177     return;
178   }
179 
180   if (remote_cid == kInvalidCid) {
181     LOG_WARN("Invalid remote cid received from remote psm:%d remote_cid:%d", psm, remote_cid);
182     send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::INVALID_CID,
183                              ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
184     return;
185   }
186   /* TODO(zachoverflow): add back in with policy
187   if (channel_allocator_->IsPsmUsed(psm)) {
188     LOG_WARN("Psm already exists");
189     send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
190                              ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
191     return;
192   }
193   */
194 
195   if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
196     LOG_INFO("Service for this psm (%d) is not registered", psm);
197     send_connection_response(signal_id, remote_cid, kInvalidCid, ConnectionResponseResult::PSM_NOT_SUPPORTED,
198                              ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
199     return;
200   }
201 
202   dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
203       link_->GetDevice(),
204       dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
205       handler_->BindOnceOn(
206           this, &ClassicSignallingManager::on_security_result_for_incoming, psm, remote_cid, signal_id));
207 }
208 
on_security_result_for_incoming(Psm psm,Cid remote_cid,SignalId signal_id,bool result)209 void ClassicSignallingManager::on_security_result_for_incoming(
210     Psm psm, Cid remote_cid, SignalId signal_id, bool result) {
211   if (enqueue_buffer_.get() == nullptr) {
212     LOG_ERROR("Got security result callback after deletion");
213     return;
214   }
215   if (!result) {
216     send_connection_response(
217         signal_id,
218         remote_cid,
219         0,
220         ConnectionResponseResult::SECURITY_BLOCK,
221         ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
222     DynamicChannelManager::ConnectionResult connection_result{
223         .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_SECURITY_BLOCK,
224         .hci_error = hci::ErrorCode::SUCCESS,
225         .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
226     };
227     link_->OnOutgoingConnectionRequestFail(0, connection_result);
228   }
229 
230   auto new_channel = link_->AllocateDynamicChannel(psm, remote_cid);
231   if (new_channel == nullptr) {
232     LOG_WARN("Can't allocate dynamic channel");
233     return;
234   }
235   send_connection_response(
236       signal_id,
237       remote_cid,
238       new_channel->GetCid(),
239       ConnectionResponseResult::SUCCESS,
240       ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
241 
242   link_->SendInitialConfigRequestOrQueue(new_channel->GetCid());
243 }
244 
OnConnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid,ConnectionResponseResult result,ConnectionResponseStatus status)245 void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
246                                                     ConnectionResponseResult result, ConnectionResponseStatus status) {
247   if (command_just_sent_.signal_id_ != signal_id ||
248       command_just_sent_.command_code_ != CommandCode::CONNECTION_REQUEST) {
249     LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
250              command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
251              signal_id.Value());
252     return;
253   }
254   if (command_just_sent_.source_cid_ != cid) {
255     LOG_WARN("SCID doesn't match: expected %d, received %d", command_just_sent_.source_cid_, cid);
256     handle_send_next_command();
257     return;
258   }
259   if (result == ConnectionResponseResult::PENDING) {
260     alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
261                     kTimeout);
262     return;
263   }
264 
265   command_just_sent_.signal_id_ = kInvalidSignalId;
266   alarm_.Cancel();
267   if (result != ConnectionResponseResult::SUCCESS) {
268     DynamicChannelManager::ConnectionResult connection_result{
269         .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
270         .hci_error = hci::ErrorCode::SUCCESS,
271         .l2cap_connection_response_result = result,
272     };
273     link_->OnOutgoingConnectionRequestFail(cid, connection_result);
274     handle_send_next_command();
275     return;
276   }
277   Psm pending_psm = command_just_sent_.psm_;
278   auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid);
279   if (new_channel == nullptr) {
280     LOG_WARN("Can't allocate dynamic channel");
281     DynamicChannelManager::ConnectionResult connection_result{
282         .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
283         .hci_error = hci::ErrorCode::SUCCESS,
284         .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
285     };
286     link_->OnOutgoingConnectionRequestFail(cid, connection_result);
287     handle_send_next_command();
288     return;
289   }
290 
291   link_->SendInitialConfigRequestOrQueue(cid);
292 }
293 
OnConfigurationRequest(SignalId signal_id,Cid cid,Continuation is_continuation,std::vector<std::unique_ptr<ConfigurationOption>> options)294 void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
295                                                       std::vector<std::unique_ptr<ConfigurationOption>> options) {
296   auto channel = channel_allocator_->FindChannelByCid(cid);
297   if (channel == nullptr) {
298     LOG_WARN("Configuration request for an unknown channel");
299     return;
300   }
301 
302   auto& configuration_state = channel_configuration_[cid];
303   std::vector<std::unique_ptr<ConfigurationOption>> rsp_options;
304   ConfigurationResponseResult result = ConfigurationResponseResult::SUCCESS;
305   auto remote_rfc_mode = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
306 
307   auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();
308 
309   for (auto& option : options) {
310     switch (option->type_) {
311       case ConfigurationOptionType::MTU: {
312         auto* config = MtuConfigurationOption::Specialize(option.get());
313         if (config->mtu_ < initial_config_option.minimal_remote_mtu) {
314           LOG_WARN("Configuration request with unacceptable MTU");
315           config->mtu_ = initial_config_option.minimal_remote_mtu;
316           result = ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS;
317         }
318         rsp_options.emplace_back(std::make_unique<MtuConfigurationOption>(*config));
319         break;
320       }
321       case ConfigurationOptionType::FLUSH_TIMEOUT: {
322         auto* config = FlushTimeoutConfigurationOption::Specialize(option.get());
323         rsp_options.emplace_back(std::make_unique<FlushTimeoutConfigurationOption>(*config));
324         break;
325       }
326       case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
327         auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
328         remote_rfc_mode = config->mode_;
329         if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
330           if (config->retransmission_time_out_ == 0) {
331             config->retransmission_time_out_ = 2000;
332           }
333           if (config->monitor_time_out_ == 0) {
334             config->monitor_time_out_ = 12000;
335           }
336         }
337         configuration_state.remote_retransmission_and_flow_control_ = *config;
338         configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
339         rsp_options.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
340         break;
341       }
342       case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
343         // We determine whether to use FCS or not when we send config request
344         break;
345       }
346       default:
347         if (option->is_hint_ != ConfigurationOptionIsHint::OPTION_IS_A_HINT) {
348           LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
349           auto response =
350               ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
351                                                    ConfigurationResponseResult::UNKNOWN_OPTIONS, {});
352           enqueue_buffer_->Enqueue(std::move(response), handler_);
353           return;
354         }
355         break;
356     }
357   }
358 
359   if (remote_rfc_mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC &&
360       initial_config_option.channel_mode ==
361           DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
362     LOG_WARN("ERTM mandatory not allow mode configuration, disconnect channel.");
363     SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
364     return;
365   }
366 
367   if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) {
368     std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
369     if (channel->local_initiated_) {
370       link_->NotifyChannelCreation(cid, std::move(user_channel));
371     } else {
372       dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
373     }
374     configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
375     data_pipeline_manager_->AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC);
376     data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
377   } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
378     configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_RSP;
379   }
380 
381   auto response = ConfigurationResponseBuilder::Create(signal_id.Value(), channel->GetRemoteCid(), is_continuation,
382                                                        result, std::move(rsp_options));
383   enqueue_buffer_->Enqueue(std::move(response), handler_);
384 }
385 
SendInitialConfigRequest(Cid local_cid)386 void ClassicSignallingManager::SendInitialConfigRequest(Cid local_cid) {
387   auto channel = channel_allocator_->FindChannelByCid(local_cid);
388   auto psm = channel->GetPsm();
389   auto& configuration_state = channel_configuration_[local_cid];
390   auto* service = dynamic_service_manager_->GetService(psm);
391   auto initial_config = service->GetConfigOption();
392 
393   auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
394   mtu_configuration->mtu_ = initial_config.incoming_mtu;
395 
396   auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
397   fcs_option->fcs_type_ = FcsType::NO_FCS;
398   configuration_state.fcs_type_ = FcsType::NO_FCS;
399   if (link_->GetRemoteSupportsFcs()) {
400     fcs_option->fcs_type_ = FcsType::DEFAULT;
401     configuration_state.fcs_type_ = FcsType::DEFAULT;
402   }
403 
404   auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
405   switch (initial_config.channel_mode) {
406     case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
407       retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
408       configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
409       break;
410     case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
411     case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION_OPTIONAL:
412       retransmission_flow_control_configuration->mode_ =
413           RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
414       configuration_state.retransmission_and_flow_control_mode_ =
415           RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
416       // TODO: Decide where to put initial values
417       retransmission_flow_control_configuration->tx_window_size_ = 10;
418       retransmission_flow_control_configuration->max_transmit_ = 20;
419       retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
420       retransmission_flow_control_configuration->monitor_time_out_ = 12000;
421       retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
422       break;
423   }
424   configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;
425 
426   std::vector<std::unique_ptr<ConfigurationOption>> config;
427   config.emplace_back(std::move(mtu_configuration));
428   if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
429     config.emplace_back(std::move(retransmission_flow_control_configuration));
430     config.emplace_back(std::move(fcs_option));
431   }
432   send_configuration_request(channel->GetRemoteCid(), std::move(config));
433 }
434 
negotiate_configuration(Cid cid,Continuation is_continuation,std::vector<std::unique_ptr<ConfigurationOption>> options)435 void ClassicSignallingManager::negotiate_configuration(Cid cid, Continuation is_continuation,
436                                                        std::vector<std::unique_ptr<ConfigurationOption>> options) {
437   auto channel = channel_allocator_->FindChannelByCid(cid);
438   auto& configuration_state = channel_configuration_[channel->GetCid()];
439   std::vector<std::unique_ptr<ConfigurationOption>> negotiation_config;
440   bool can_negotiate = false;
441   for (auto& option : options) {
442     switch (option->type_) {
443       case ConfigurationOptionType::MTU: {
444         // MTU is non-negotiable option. Use default mtu size
445         auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
446         mtu_configuration->mtu_ = kDefaultClassicMtu;
447         negotiation_config.emplace_back(std::move(mtu_configuration));
448         can_negotiate = true;
449         break;
450       }
451       case ConfigurationOptionType::FRAME_CHECK_SEQUENCE:
452       case ConfigurationOptionType::FLUSH_TIMEOUT: {
453         // TODO: Handle these two configuration options negotiation.
454         can_negotiate = true;
455         break;
456       }
457       case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
458         auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
459         if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
460           configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
461           configuration_state.local_retransmission_and_flow_control_ = *config;
462           negotiation_config.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
463         } else if (config->mode_ == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
464           auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();
465           if (initial_config_option.channel_mode ==
466               DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
467             // ERTM mandatory is not allow negotiating of retransmission and flow control mode, disconnect channel
468             SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
469             return;
470           } else if (initial_config_option.channel_mode ==
471                      DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::
472                          ENHANCED_RETRANSMISSION_OPTIONAL) {
473             can_negotiate = true;
474             negotiation_config.emplace_back(std::make_unique<RetransmissionAndFlowControlConfigurationOption>(*config));
475           }
476         } else {
477           // Not support other retransmission and flow control mode, disconnect channel.
478           SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
479           return;
480         }
481         break;
482       }
483       default:
484         LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
485         return;
486     }
487   }
488   if (can_negotiate) {
489     send_configuration_request(channel->GetRemoteCid(), std::move(negotiation_config));
490   } else {
491     LOG_INFO("No suggested parameter received");
492   }
493 }
494 
OnConfigurationResponse(SignalId signal_id,Cid cid,Continuation is_continuation,ConfigurationResponseResult result,std::vector<std::unique_ptr<ConfigurationOption>> options)495 void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
496                                                        ConfigurationResponseResult result,
497                                                        std::vector<std::unique_ptr<ConfigurationOption>> options) {
498   if (command_just_sent_.signal_id_ != signal_id ||
499       command_just_sent_.command_code_ != CommandCode::CONFIGURATION_REQUEST) {
500     LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
501              command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
502              signal_id.Value());
503     return;
504   }
505 
506   auto channel = channel_allocator_->FindChannelByCid(cid);
507   if (channel == nullptr) {
508     LOG_WARN("Configuration request for an unknown channel");
509     handle_send_next_command();
510     return;
511   }
512 
513   switch (result) {
514     default:
515     case ConfigurationResponseResult::REJECTED:
516     case ConfigurationResponseResult::UNKNOWN_OPTIONS:
517     case ConfigurationResponseResult::FLOW_SPEC_REJECTED:
518       LOG_WARN("Configuration response not SUCCESS: %s", ConfigurationResponseResultText(result).c_str());
519       alarm_.Cancel();
520       handle_send_next_command();
521       return;
522 
523     case ConfigurationResponseResult::PENDING:
524       alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
525                       kTimeout);
526       return;
527 
528     case ConfigurationResponseResult::UNACCEPTABLE_PARAMETERS:
529       LOG_INFO("Configuration response with unacceptable parameters");
530       alarm_.Cancel();
531       negotiate_configuration(cid, is_continuation, std::move(options));
532       handle_send_next_command();
533       return;
534 
535     case ConfigurationResponseResult::SUCCESS:
536       break;
537   }
538   auto& configuration_state = channel_configuration_[channel->GetCid()];
539 
540   for (auto& option : options) {
541     switch (option->type_) {
542       case ConfigurationOptionType::MTU: {
543         // Since they accepted our MTU, no need to read the new value.
544         break;
545       }
546       case ConfigurationOptionType::FLUSH_TIMEOUT: {
547         break;
548       }
549       case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
550         auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
551         if (configuration_state.retransmission_and_flow_control_mode_ != config->mode_) {
552           SendDisconnectionRequest(cid, channel->GetRemoteCid());
553           alarm_.Cancel();
554           handle_send_next_command();
555           return;
556         }
557         configuration_state.local_retransmission_and_flow_control_ = *config;
558         break;
559       }
560       case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
561         configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
562         break;
563       }
564       default:
565         LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
566         alarm_.Cancel();
567         handle_send_next_command();
568         return;
569     }
570   }
571 
572   if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_RSP) {
573     std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
574     if (channel->local_initiated_) {
575       link_->NotifyChannelCreation(cid, std::move(user_channel));
576     } else {
577       dynamic_service_manager_->GetService(channel->GetPsm())->NotifyChannelCreation(std::move(user_channel));
578     }
579     configuration_state.state_ = ChannelConfigurationState::State::CONFIGURED;
580     data_pipeline_manager_->AttachChannel(cid, channel, l2cap::internal::DataPipelineManager::ChannelMode::BASIC);
581     data_pipeline_manager_->UpdateClassicConfiguration(cid, configuration_state);
582   } else if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ_RSP) {
583     configuration_state.state_ = ChannelConfigurationState::State::WAIT_CONFIG_REQ;
584   }
585 
586   alarm_.Cancel();
587   handle_send_next_command();
588 }
589 
OnDisconnectionRequest(SignalId signal_id,Cid cid,Cid remote_cid)590 void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
591   // TODO: check cid match
592   auto channel = channel_allocator_->FindChannelByCid(cid);
593   if (channel == nullptr) {
594     LOG_WARN("Disconnect request for an unknown channel");
595     return;
596   }
597   auto builder = DisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
598   enqueue_buffer_->Enqueue(std::move(builder), handler_);
599   channel->OnClosed(hci::ErrorCode::SUCCESS);
600   auto& configuration_state = channel_configuration_[channel->GetCid()];
601   if (configuration_state.state_ == configuration_state.CONFIGURED) {
602     data_pipeline_manager_->DetachChannel(cid);
603   }
604   link_->FreeDynamicChannel(cid);
605   channel_configuration_.erase(cid);
606 }
607 
OnDisconnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid)608 void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
609   if (command_just_sent_.signal_id_ != signal_id ||
610       command_just_sent_.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
611     LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
612              command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
613              signal_id.Value());
614     return;
615   }
616 
617   alarm_.Cancel();
618 
619   auto channel = channel_allocator_->FindChannelByCid(cid);
620   if (channel == nullptr) {
621     LOG_WARN("Disconnect response for an unknown channel");
622     handle_send_next_command();
623     return;
624   }
625 
626   channel->OnClosed(hci::ErrorCode::SUCCESS);
627   auto& configuration_state = channel_configuration_[cid];
628   if (configuration_state.state_ == configuration_state.CONFIGURED) {
629     data_pipeline_manager_->DetachChannel(cid);
630   }
631   link_->FreeDynamicChannel(cid);
632   handle_send_next_command();
633   channel_configuration_.erase(cid);
634 }
635 
OnEchoRequest(SignalId signal_id,const PacketView<kLittleEndian> & packet)636 void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
637   std::vector<uint8_t> packet_vector{packet.begin(), packet.end()};
638   auto raw_builder = std::make_unique<packet::RawBuilder>();
639   raw_builder->AddOctets(packet_vector);
640   auto builder = EchoResponseBuilder::Create(signal_id.Value(), std::move(raw_builder));
641   enqueue_buffer_->Enqueue(std::move(builder), handler_);
642 }
643 
OnEchoResponse(SignalId signal_id,const PacketView<kLittleEndian> & packet)644 void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
645   if (command_just_sent_.signal_id_ != signal_id || command_just_sent_.command_code_ != CommandCode::ECHO_REQUEST) {
646     LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
647              command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
648              signal_id.Value());
649     return;
650   }
651   LOG_INFO("Echo response received");
652   alarm_.Cancel();
653   handle_send_next_command();
654 }
655 
OnInformationRequest(SignalId signal_id,InformationRequestInfoType type)656 void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, InformationRequestInfoType type) {
657   switch (type) {
658     case InformationRequestInfoType::CONNECTIONLESS_MTU: {
659       auto response = InformationResponseConnectionlessMtuBuilder::Create(
660           signal_id.Value(), InformationRequestResult::SUCCESS, kDefaultClassicMtu);
661       enqueue_buffer_->Enqueue(std::move(response), handler_);
662       break;
663     }
664     case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
665       auto response = InformationResponseExtendedFeaturesBuilder::Create(
666           signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1 /* ERTM */, 0 /* Streaming mode */,
667           1 /* FCS */, 0, 1 /* Fixed Channels */, 0, 0, 0 /* COC */);
668       enqueue_buffer_->Enqueue(std::move(response), handler_);
669       break;
670     }
671     case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
672       auto response = InformationResponseFixedChannelsBuilder::Create(
673           signal_id.Value(), InformationRequestResult::SUCCESS, fixed_service_manager_->GetSupportedFixedChannelMask());
674       enqueue_buffer_->Enqueue(std::move(response), handler_);
675       break;
676     }
677   }
678 }
679 
OnInformationResponse(SignalId signal_id,const InformationResponseView & response)680 void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
681   if (command_just_sent_.signal_id_ != signal_id ||
682       command_just_sent_.command_code_ != CommandCode::INFORMATION_REQUEST) {
683     LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
684              command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
685              signal_id.Value());
686     return;
687   }
688 
689   auto type = response.GetInfoType();
690   switch (type) {
691     case InformationRequestInfoType::CONNECTIONLESS_MTU: {
692       auto view = InformationResponseConnectionlessMtuView::Create(response);
693       if (!view.IsValid()) {
694         LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
695         return;
696       }
697       link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
698       break;
699     }
700     case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
701       auto view = InformationResponseExtendedFeaturesView::Create(response);
702       if (!view.IsValid()) {
703         LOG_WARN("Invalid InformationResponseExtendedFeatures received");
704         return;
705       }
706       link_->OnRemoteExtendedFeatureReceived(view.GetEnhancedRetransmissionMode(), view.GetFcsOption());
707       // We don't care about other parameters
708       break;
709     }
710     case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
711       auto view = InformationResponseFixedChannelsView::Create(response);
712       if (!view.IsValid()) {
713         LOG_WARN("Invalid InformationResponseFixedChannel received");
714         return;
715       }
716       // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
717       break;
718     }
719   }
720 
721   alarm_.Cancel();
722   handle_send_next_command();
723 }
724 
on_incoming_packet()725 void ClassicSignallingManager::on_incoming_packet() {
726   auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
727   auto command_list = GetCommandsFromPacketView(*packet);
728   for (auto& command : command_list) {
729     handle_one_command(command);
730   }
731 }
732 
handle_one_command(ControlView control_packet_view)733 void ClassicSignallingManager::handle_one_command(ControlView control_packet_view) {
734   if (!control_packet_view.IsValid()) {
735     LOG_WARN("Invalid signalling packet received");
736     return;
737   }
738   auto code = control_packet_view.GetCode();
739   switch (code) {
740     case CommandCode::COMMAND_REJECT: {
741       CommandRejectView command_reject_view = CommandRejectView::Create(control_packet_view);
742       if (!command_reject_view.IsValid()) {
743         return;
744       }
745       OnCommandReject(command_reject_view);
746       return;
747     }
748     case CommandCode::CONNECTION_REQUEST: {
749       ConnectionRequestView connection_request_view = ConnectionRequestView::Create(control_packet_view);
750       if (!connection_request_view.IsValid()) {
751         return;
752       }
753       OnConnectionRequest(control_packet_view.GetIdentifier(), connection_request_view.GetPsm(),
754                           connection_request_view.GetSourceCid());
755       return;
756     }
757     case CommandCode::CONNECTION_RESPONSE: {
758       ConnectionResponseView connection_response_view = ConnectionResponseView::Create(control_packet_view);
759       if (!connection_response_view.IsValid()) {
760         return;
761       }
762       OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
763                            connection_response_view.GetSourceCid(), connection_response_view.GetResult(),
764                            connection_response_view.GetStatus());
765       return;
766     }
767     case CommandCode::CONFIGURATION_REQUEST: {
768       ConfigurationRequestView configuration_request_view = ConfigurationRequestView::Create(control_packet_view);
769       if (!configuration_request_view.IsValid()) {
770         return;
771       }
772       OnConfigurationRequest(configuration_request_view.GetIdentifier(), configuration_request_view.GetDestinationCid(),
773                              configuration_request_view.GetContinuation(), configuration_request_view.GetConfig());
774       return;
775     }
776     case CommandCode::CONFIGURATION_RESPONSE: {
777       ConfigurationResponseView configuration_response_view = ConfigurationResponseView::Create(control_packet_view);
778       if (!configuration_response_view.IsValid()) {
779         return;
780       }
781       OnConfigurationResponse(configuration_response_view.GetIdentifier(), configuration_response_view.GetSourceCid(),
782                               configuration_response_view.GetContinuation(), configuration_response_view.GetResult(),
783                               configuration_response_view.GetConfig());
784       return;
785     }
786     case CommandCode::DISCONNECTION_REQUEST: {
787       DisconnectionRequestView disconnection_request_view = DisconnectionRequestView::Create(control_packet_view);
788       if (!disconnection_request_view.IsValid()) {
789         return;
790       }
791       OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
792                              disconnection_request_view.GetSourceCid());
793       return;
794     }
795     case CommandCode::DISCONNECTION_RESPONSE: {
796       DisconnectionResponseView disconnection_response_view = DisconnectionResponseView::Create(control_packet_view);
797       if (!disconnection_response_view.IsValid()) {
798         return;
799       }
800       OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
801                               disconnection_response_view.GetDestinationCid(),
802                               disconnection_response_view.GetSourceCid());
803       return;
804     }
805     case CommandCode::ECHO_REQUEST: {
806       EchoRequestView echo_request_view = EchoRequestView::Create(control_packet_view);
807       if (!echo_request_view.IsValid()) {
808         return;
809       }
810       OnEchoRequest(echo_request_view.GetIdentifier(), echo_request_view.GetPayload());
811       return;
812     }
813     case CommandCode::ECHO_RESPONSE: {
814       EchoResponseView echo_response_view = EchoResponseView::Create(control_packet_view);
815       if (!echo_response_view.IsValid()) {
816         return;
817       }
818       OnEchoResponse(echo_response_view.GetIdentifier(), echo_response_view.GetPayload());
819       return;
820     }
821     case CommandCode::INFORMATION_REQUEST: {
822       InformationRequestView information_request_view = InformationRequestView::Create(control_packet_view);
823       if (!information_request_view.IsValid()) {
824         return;
825       }
826       OnInformationRequest(information_request_view.GetIdentifier(), information_request_view.GetInfoType());
827       return;
828     }
829     case CommandCode::INFORMATION_RESPONSE: {
830       InformationResponseView information_response_view = InformationResponseView::Create(control_packet_view);
831       if (!information_response_view.IsValid()) {
832         return;
833       }
834       OnInformationResponse(information_response_view.GetIdentifier(), information_response_view);
835       return;
836     }
837     case CommandCode::CREDIT_BASED_CONNECTION_REQUEST: {
838       CreditBasedConnectionRequestView request_view = CreditBasedConnectionRequestView::Create(control_packet_view);
839       if (!request_view.IsValid()) {
840         return;
841       }
842       return;
843     }
844     case CommandCode::CREDIT_BASED_CONNECTION_RESPONSE: {
845       CreditBasedConnectionResponseView response_view = CreditBasedConnectionResponseView::Create(control_packet_view);
846       if (!response_view.IsValid()) {
847         return;
848       }
849       return;
850     }
851     case CommandCode::CREDIT_BASED_RECONFIGURE_REQUEST: {
852       CreditBasedReconfigureRequestView request_view = CreditBasedReconfigureRequestView::Create(control_packet_view);
853       if (!request_view.IsValid()) {
854         return;
855       }
856       return;
857     }
858     case CommandCode::CREDIT_BASED_RECONFIGURE_RESPONSE: {
859       CreditBasedReconfigureResponseView response_view =
860           CreditBasedReconfigureResponseView::Create(control_packet_view);
861       if (!response_view.IsValid()) {
862         return;
863       }
864       return;
865     }
866     case CommandCode::FLOW_CONTROL_CREDIT: {
867       FlowControlCreditView credit_view = FlowControlCreditView::Create(control_packet_view);
868       if (!credit_view.IsValid()) {
869         return;
870       }
871       return;
872     }
873     default:
874       LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
875       auto builder = CommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
876       enqueue_buffer_->Enqueue(std::move(builder), handler_);
877       return;
878   }
879 }
880 
send_connection_response(SignalId signal_id,Cid remote_cid,Cid local_cid,ConnectionResponseResult result,ConnectionResponseStatus status)881 void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid remote_cid, Cid local_cid,
882                                                         ConnectionResponseResult result,
883                                                         ConnectionResponseStatus status) {
884   auto builder = ConnectionResponseBuilder::Create(signal_id.Value(), local_cid, remote_cid, result, status);
885   enqueue_buffer_->Enqueue(std::move(builder), handler_);
886 }
887 
on_command_timeout()888 void ClassicSignallingManager::on_command_timeout() {
889   LOG_WARN("Response time out");
890   if (command_just_sent_.signal_id_ == kInvalidSignalId) {
891     LOG_ERROR("No pending command");
892     return;
893   }
894   LOG_WARN("Response time out for %s", CommandCodeText(command_just_sent_.command_code_).c_str());
895   switch (command_just_sent_.command_code_) {
896     case CommandCode::CONNECTION_REQUEST: {
897       DynamicChannelManager::ConnectionResult connection_result{
898           .connection_result_code = DynamicChannelManager::ConnectionResultCode::FAIL_L2CAP_ERROR,
899           .hci_error = hci::ErrorCode::SUCCESS,
900           .l2cap_connection_response_result = ConnectionResponseResult::NO_RESOURCES_AVAILABLE,
901       };
902       link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, connection_result);
903       break;
904     }
905     case CommandCode::CONFIGURATION_REQUEST: {
906       auto channel = channel_allocator_->FindChannelByRemoteCid(command_just_sent_.destination_cid_);
907       SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
908       return;
909     }
910     case CommandCode::INFORMATION_REQUEST: {
911       if (command_just_sent_.info_type_ == InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED) {
912         link_->OnRemoteExtendedFeatureReceived(false, false);
913       }
914       break;
915     }
916     default:
917       break;
918   }
919   handle_send_next_command();
920 }
921 
handle_send_next_command()922 void ClassicSignallingManager::handle_send_next_command() {
923   command_just_sent_.signal_id_ = kInvalidSignalId;
924   if (pending_commands_.empty()) {
925     return;
926   }
927   command_just_sent_ = std::move(pending_commands_.front());
928   pending_commands_.pop();
929 
930   auto signal_id = command_just_sent_.signal_id_;
931   auto psm = command_just_sent_.psm_;
932   auto source_cid = command_just_sent_.source_cid_;
933   auto destination_cid = command_just_sent_.destination_cid_;
934   auto info_type = command_just_sent_.info_type_;
935   auto config = std::move(command_just_sent_.config_);
936   switch (command_just_sent_.command_code_) {
937     case CommandCode::CONNECTION_REQUEST: {
938       auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
939       enqueue_buffer_->Enqueue(std::move(builder), handler_);
940       alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
941                       kTimeout);
942       break;
943     }
944     case CommandCode::CONFIGURATION_REQUEST: {
945       auto builder =
946           ConfigurationRequestBuilder::Create(signal_id.Value(), destination_cid, Continuation::END, std::move(config));
947       enqueue_buffer_->Enqueue(std::move(builder), handler_);
948       alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
949                       kTimeout);
950       break;
951     }
952     case CommandCode::DISCONNECTION_REQUEST: {
953       auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid);
954       enqueue_buffer_->Enqueue(std::move(builder), handler_);
955       alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
956                       kTimeout);
957       break;
958     }
959     case CommandCode::INFORMATION_REQUEST: {
960       auto builder = InformationRequestBuilder::Create(signal_id.Value(), info_type);
961       enqueue_buffer_->Enqueue(std::move(builder), handler_);
962       alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)),
963                       kTimeout);
964       break;
965     }
966     default:
967       LOG_WARN("Unsupported command code 0x%x", static_cast<int>(command_just_sent_.command_code_));
968   }
969 }
970 
971 }  // namespace internal
972 }  // namespace classic
973 }  // namespace l2cap
974 }  // namespace bluetooth
975