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