• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/l2cap/logical_link.h"
16 
17 #include <cpp-string/string_printf.h>
18 #include <pw_assert/check.h>
19 
20 #include <cinttypes>
21 #include <functional>
22 #include <memory>
23 
24 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
25 #include "pw_bluetooth_sapphire/internal/host/common/trace.h"
26 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_dynamic_channel.h"
27 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_signaling_channel.h"
28 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h"
29 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
30 #include "pw_bluetooth_sapphire/internal/host/l2cap/le_dynamic_channel.h"
31 #include "pw_bluetooth_sapphire/internal/host/l2cap/le_signaling_channel.h"
32 #include "pw_bluetooth_sapphire/internal/host/transport/link_type.h"
33 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
34 
35 namespace bt::l2cap::internal {
36 
37 using pw::bluetooth::AclPriority;
38 
39 namespace {
40 
41 const char* kInspectHandlePropertyName = "handle";
42 const char* kInspectLinkTypePropertyName = "link_type";
43 const char* kInspectChannelsNodeName = "channels";
44 const char* kInspectChannelNodePrefix = "channel_";
45 const char* kInspectFlushTimeoutPropertyName = "flush_timeout_ms";
46 
IsValidLEFixedChannel(ChannelId id)47 constexpr bool IsValidLEFixedChannel(ChannelId id) {
48   switch (id) {
49     case kATTChannelId:
50     case kLESignalingChannelId:
51     case kLESMPChannelId:
52       return true;
53     default:
54       break;
55   }
56   return false;
57 }
58 
IsValidBREDRFixedChannel(ChannelId id)59 constexpr bool IsValidBREDRFixedChannel(ChannelId id) {
60   switch (id) {
61     case kSignalingChannelId:
62     case kConnectionlessChannelId:
63     case kSMPChannelId:
64       return true;
65     default:
66       break;
67   }
68   return false;
69 }
70 
FixedChannelsSupportedBitForChannelId(ChannelId channel_id)71 FixedChannelsSupported FixedChannelsSupportedBitForChannelId(
72     ChannelId channel_id) {
73   switch (channel_id) {
74     case kSignalingChannelId:
75       return kFixedChannelsSupportedBitSignaling;
76     case kConnectionlessChannelId:
77       return kFixedChannelsSupportedBitConnectionless;
78     case kSMPChannelId:
79       return kFixedChannelsSupportedBitSM;
80     default:
81       return 0;
82   }
83 }
84 
85 }  // namespace
86 
LogicalLink(hci_spec::ConnectionHandle handle,bt::LinkType type,pw::bluetooth::emboss::ConnectionRole role,uint16_t max_acl_payload_size,QueryServiceCallback query_service_cb,hci::AclDataChannel * acl_data_channel,hci::CommandChannel * cmd_channel,bool random_channel_ids,A2dpOffloadManager & a2dp_offload_manager,pw::async::Dispatcher & dispatcher)87 LogicalLink::LogicalLink(hci_spec::ConnectionHandle handle,
88                          bt::LinkType type,
89                          pw::bluetooth::emboss::ConnectionRole role,
90                          uint16_t max_acl_payload_size,
91                          QueryServiceCallback query_service_cb,
92                          hci::AclDataChannel* acl_data_channel,
93                          hci::CommandChannel* cmd_channel,
94                          bool random_channel_ids,
95                          A2dpOffloadManager& a2dp_offload_manager,
96                          pw::async::Dispatcher& dispatcher)
97     : pw_dispatcher_(dispatcher),
98       handle_(handle),
99       type_(type),
100       role_(role),
101       max_acl_payload_size_(max_acl_payload_size),
102       flush_timeout_(
103           pw::chrono::SystemClock::duration::max(), /*convert=*/
104           [](pw::chrono::SystemClock::duration f) {
105             return std::chrono::duration_cast<std::chrono::milliseconds>(f)
106                 .count();
107           }),
108       closed_(false),
109       recombiner_(handle),
110       acl_data_channel_(acl_data_channel),
111       cmd_channel_(cmd_channel),
112       query_service_cb_(std::move(query_service_cb)),
113       a2dp_offload_manager_(a2dp_offload_manager),
114       weak_conn_interface_(this),
115       weak_self_(this) {
116   PW_CHECK(type_ == bt::LinkType::kLE || type_ == bt::LinkType::kACL);
117   PW_CHECK(acl_data_channel_);
118   PW_CHECK(cmd_channel_);
119   PW_CHECK(query_service_cb_);
120 
121   // Allow packets to be sent on this link immediately.
122   acl_data_channel_->RegisterConnection(weak_conn_interface_.GetWeakPtr());
123 
124   // Set up the signaling channel and dynamic channels.
125   if (type_ == bt::LinkType::kLE) {
126     signaling_channel_ = std::make_unique<LESignalingChannel>(
127         OpenFixedChannel(kLESignalingChannelId), role_, pw_dispatcher_);
128     dynamic_registry_ = std::make_unique<LeDynamicChannelRegistry>(
129         signaling_channel_.get(),
130         fit::bind_member<&LogicalLink::OnChannelDisconnectRequest>(this),
131         fit::bind_member<&LogicalLink::OnServiceRequest>(this),
132         random_channel_ids);
133 
134     ServeConnectionParameterUpdateRequest();
135   } else {
136     signaling_channel_ = std::make_unique<BrEdrSignalingChannel>(
137         OpenFixedChannel(kSignalingChannelId), role_, pw_dispatcher_);
138     dynamic_registry_ = std::make_unique<BrEdrDynamicChannelRegistry>(
139         signaling_channel_.get(),
140         fit::bind_member<&LogicalLink::OnChannelDisconnectRequest>(this),
141         fit::bind_member<&LogicalLink::OnServiceRequest>(this),
142         random_channel_ids);
143 
144     SendFixedChannelsSupportedInformationRequest();
145   }
146 }
147 
~LogicalLink()148 LogicalLink::~LogicalLink() {
149   bt_log(DEBUG, "l2cap", "LogicalLink destroyed (handle: %#.4x)", handle_);
150   PW_CHECK(closed_);
151 }
152 
OpenFixedChannel(ChannelId id)153 Channel::WeakPtr LogicalLink::OpenFixedChannel(ChannelId id) {
154   PW_DCHECK(!closed_);
155 
156   TRACE_DURATION("bluetooth",
157                  "LogicalLink::OpenFixedChannel",
158                  "handle",
159                  handle_,
160                  "channel id",
161                  id);
162 
163   // We currently only support the pre-defined fixed-channels.
164   if (!AllowsFixedChannel(id)) {
165     bt_log(ERROR, "l2cap", "cannot open fixed channel with id %#.4x", id);
166     return Channel::WeakPtr();
167   }
168 
169   auto iter = channels_.find(id);
170   if (iter != channels_.end()) {
171     bt_log(ERROR,
172            "l2cap",
173            "channel is already open! (id: %#.4x, handle: %#.4x)",
174            id,
175            handle_);
176     return Channel::WeakPtr();
177   }
178 
179   std::unique_ptr<ChannelImpl> chan =
180       ChannelImpl::CreateFixedChannel(pw_dispatcher_,
181                                       id,
182                                       GetWeakPtr(),
183                                       cmd_channel_->AsWeakPtr(),
184                                       max_acl_payload_size_,
185                                       a2dp_offload_manager_);
186 
187   auto pp_iter = pending_pdus_.find(id);
188   if (pp_iter != pending_pdus_.end()) {
189     for (auto& pdu : pp_iter->second) {
190       TRACE_FLOW_END(
191           "bluetooth", "LogicalLink::HandleRxPacket queued", pdu.trace_id());
192       chan->HandleRxPdu(std::move(pdu));
193     }
194     pending_pdus_.erase(pp_iter);
195   }
196 
197   if (inspect_properties_.channels_node) {
198     chan->AttachInspect(inspect_properties_.channels_node,
199                         inspect_properties_.channels_node.UniqueName(
200                             kInspectChannelNodePrefix));
201   }
202 
203   channels_[id] = std::move(chan);
204 
205   // Reset round robin iterator
206   current_channel_ = channels_.begin();
207 
208   return channels_[id]->GetWeakPtr();
209 }
210 
OpenFixedChannelAsync(ChannelId channel_id,ChannelCallback callback)211 void LogicalLink::OpenFixedChannelAsync(ChannelId channel_id,
212                                         ChannelCallback callback) {
213   if (type_ == LinkType::kACL) {
214     if (fixed_channels_supported_callbacks_.count(channel_id) > 0) {
215       bt_log(ERROR,
216              "l2cap",
217              "fixed channel is already pending! (id: %#.4x, handle: %#.4x)",
218              channel_id,
219              handle_);
220       callback(Channel::WeakPtr());
221       return;
222     }
223 
224     if (!fixed_channels_supported_.has_value()) {
225       fixed_channels_supported_callbacks_.emplace(
226           channel_id, [this, channel_id, cb = std::move(callback)]() mutable {
227             OpenFixedChannelAsync(channel_id, std::move(cb));
228           });
229       return;
230     }
231 
232     bool channel_supported = *fixed_channels_supported_ &
233                              FixedChannelsSupportedBitForChannelId(channel_id);
234 
235     if (!channel_supported) {
236       bt_log(DEBUG,
237              "l2cap",
238              "tried to open fixed channel not supported by peer (id: %#.4x, "
239              "handle: %#.4x)",
240              channel_id,
241              handle_);
242       callback(Channel::WeakPtr());
243       return;
244     }
245   }
246 
247   callback(OpenFixedChannel(channel_id));
248 }
249 
OpenChannel(Psm psm,ChannelParameters params,ChannelCallback callback)250 void LogicalLink::OpenChannel(Psm psm,
251                               ChannelParameters params,
252                               ChannelCallback callback) {
253   PW_DCHECK(!closed_);
254   PW_DCHECK(dynamic_registry_);
255 
256   auto create_channel =
257       [this, cb = std::move(callback)](const DynamicChannel* dyn_chan) mutable {
258         CompleteDynamicOpen(dyn_chan, std::move(cb));
259       };
260   dynamic_registry_->OpenOutbound(psm, params, std::move(create_channel));
261 
262   // Reset round robin iterator
263   current_channel_ = channels_.begin();
264 }
265 
HandleRxPacket(hci::ACLDataPacketPtr packet)266 void LogicalLink::HandleRxPacket(hci::ACLDataPacketPtr packet) {
267   PW_DCHECK(packet);
268   PW_DCHECK(!closed_);
269 
270   TRACE_DURATION("bluetooth", "LogicalLink::HandleRxPacket", "handle", handle_);
271 
272   // We do not support the Connectionless data channel, and the active broadcast
273   // flag can only be used on the connectionless channel.  Drop packets that are
274   // broadcast.
275   if (packet->broadcast_flag() ==
276       hci_spec::ACLBroadcastFlag::kActivePeripheralBroadcast) {
277     bt_log(DEBUG, "l2cap", "Unsupported Broadcast Frame dropped");
278     return;
279   }
280 
281   auto result = recombiner_.ConsumeFragment(std::move(packet));
282   if (result.frames_dropped) {
283     bt_log(TRACE, "l2cap", "Frame(s) dropped due to recombination error");
284   }
285 
286   if (!result.pdu) {
287     // Either a partial fragment was received, which was buffered for
288     // recombination, or the packet was dropped.
289     return;
290   }
291 
292   PW_DCHECK(result.pdu->is_valid());
293 
294   uint16_t channel_id = result.pdu->channel_id();
295   auto iter = channels_.find(channel_id);
296   PendingPduMap::iterator pp_iter;
297 
298   if (iter == channels_.end()) {
299     // Only buffer data for fixed channels. This prevents stale data that is
300     // intended for a closed dynamic channel from being delivered to a new
301     // channel that recycled the former's ID. The downside is that it's possible
302     // to lose any data that is received after a dynamic channel's connection
303     // request and before its completed configuration. This would require tricky
304     // additional state to track "pending open" channels here and it's not clear
305     // if that is necessary since hosts should not send data before a channel is
306     // first configured.
307     if (!AllowsFixedChannel(channel_id)) {
308       bt_log(WARN,
309              "l2cap",
310              "Dropping PDU for nonexistent dynamic channel %#.4x on link %#.4x",
311              channel_id,
312              handle_);
313       return;
314     }
315 
316     // The packet was received on a channel for which no ChannelImpl currently
317     // exists. Buffer packets for the channel to receive when it gets created.
318     pp_iter = pending_pdus_.emplace(channel_id, std::list<PDU>()).first;
319   } else {
320     // A channel exists. |pp_iter| will be valid only if the drain task has not
321     // run yet (see LogicalLink::OpenFixedChannel()).
322     pp_iter = pending_pdus_.find(channel_id);
323   }
324 
325   if (pp_iter != pending_pdus_.end()) {
326     result.pdu->set_trace_id(TRACE_NONCE());
327     TRACE_FLOW_BEGIN("bluetooth",
328                      "LogicalLink::HandleRxPacket queued",
329                      result.pdu->trace_id());
330 
331     pp_iter->second.emplace_back(std::move(*result.pdu));
332 
333     bt_log(TRACE,
334            "l2cap",
335            "PDU buffered (channel: %#.4x, ll: %#.4x)",
336            channel_id,
337            handle_);
338     return;
339   }
340 
341   iter->second->HandleRxPdu(std::move(*result.pdu));
342 }
343 
UpgradeSecurity(sm::SecurityLevel level,sm::ResultFunction<> callback)344 void LogicalLink::UpgradeSecurity(sm::SecurityLevel level,
345                                   sm::ResultFunction<> callback) {
346   PW_DCHECK(security_callback_);
347 
348   if (closed_) {
349     bt_log(DEBUG, "l2cap", "Ignoring security request on closed link");
350     return;
351   }
352 
353   // Report success If the link already has the expected security level.
354   if (level <= security().level()) {
355     callback(fit::ok());
356     return;
357   }
358 
359   bt_log(DEBUG,
360          "l2cap",
361          "Security upgrade requested (level = %s)",
362          sm::LevelToString(level));
363   security_callback_(handle_, level, std::move(callback));
364 }
365 
AssignSecurityProperties(const sm::SecurityProperties & security)366 void LogicalLink::AssignSecurityProperties(
367     const sm::SecurityProperties& security) {
368   if (closed_) {
369     bt_log(DEBUG, "l2cap", "Ignoring security request on closed link");
370     return;
371   }
372 
373   bt_log(DEBUG,
374          "l2cap",
375          "Link security updated (handle: %#.4x): %s",
376          handle_,
377          security.ToString().c_str());
378 
379   security_ = security;
380 }
381 
HasAvailablePacket() const382 bool LogicalLink::HasAvailablePacket() const {
383   for (auto& [_, channel] : channels_) {
384     // TODO(fxbug.dev/42074553): Check HasSDUs() after transmission engines are
385     // refactored
386     if (channel->HasPDUs() || channel->HasFragments()) {
387       return true;
388     }
389   }
390   return false;
391 }
392 
RoundRobinChannels()393 void LogicalLink::RoundRobinChannels() {
394   // Go through all channels in map
395   if (next(current_channel_) == channels_.end()) {
396     current_channel_ = channels_.begin();
397   } else {
398     current_channel_++;
399   }
400 }
401 
IsNextPacketContinuingFragment() const402 bool LogicalLink::IsNextPacketContinuingFragment() const {
403   return current_pdus_channel_.is_alive() &&
404          current_pdus_channel_->HasFragments();
405 }
406 
GetNextOutboundPacket()407 std::unique_ptr<hci::ACLDataPacket> LogicalLink::GetNextOutboundPacket() {
408   for (size_t i = 0; i < channels_.size(); i++) {
409     if (!IsNextPacketContinuingFragment()) {
410       current_pdus_channel_ = ChannelImpl::WeakPtr();
411 
412       // Go to next channel to try and get next packet to send
413       RoundRobinChannels();
414 
415       if (current_channel_->second->HasPDUs()) {
416         current_pdus_channel_ = current_channel_->second->GetWeakPtr();
417       }
418     }
419 
420     if (current_pdus_channel_.is_alive()) {
421       // Next packet will either be a starting or continuing fragment
422       return current_pdus_channel_->GetNextOutboundPacket();
423     }
424   }
425   // All channels are empty
426   // This should never actually return a nullptr since we only call
427   // LogicalLink::GetNextOutboundPacket() when LogicalLink::HasAvailablePacket()
428   // is true
429   return nullptr;
430 }
431 
OnOutboundPacketAvailable()432 void LogicalLink::OnOutboundPacketAvailable() {
433   acl_data_channel_->OnOutboundPacketAvailable();
434 }
435 
set_error_callback(fit::closure callback)436 void LogicalLink::set_error_callback(fit::closure callback) {
437   link_error_cb_ = std::move(callback);
438 }
439 
set_security_upgrade_callback(SecurityUpgradeCallback callback)440 void LogicalLink::set_security_upgrade_callback(
441     SecurityUpgradeCallback callback) {
442   security_callback_ = std::move(callback);
443 }
444 
set_connection_parameter_update_callback(LEConnectionParameterUpdateCallback callback)445 void LogicalLink::set_connection_parameter_update_callback(
446     LEConnectionParameterUpdateCallback callback) {
447   connection_parameter_update_callback_ = std::move(callback);
448 }
449 
AllowsFixedChannel(ChannelId id)450 bool LogicalLink::AllowsFixedChannel(ChannelId id) {
451   return (type_ == bt::LinkType::kLE) ? IsValidLEFixedChannel(id)
452                                       : IsValidBREDRFixedChannel(id);
453 }
454 
RemoveChannel(Channel * chan,fit::closure removed_cb)455 void LogicalLink::RemoveChannel(Channel* chan, fit::closure removed_cb) {
456   PW_DCHECK(chan);
457 
458   if (closed_) {
459     bt_log(DEBUG, "l2cap", "Ignore RemoveChannel() on closed link");
460     removed_cb();
461     return;
462   }
463 
464   const ChannelId id = chan->id();
465   auto iter = channels_.find(id);
466   if (iter == channels_.end()) {
467     removed_cb();
468     return;
469   }
470 
471   // Ignore if the found channel doesn't match the requested one (even though
472   // their IDs are the same).
473   if (iter->second.get() != chan) {
474     removed_cb();
475     return;
476   }
477 
478   pending_pdus_.erase(id);
479   channels_.erase(iter);
480 
481   // Reset round robin iterator
482   current_channel_ = channels_.begin();
483 
484   // Disconnect the channel if it's a dynamic channel. This path is for local-
485   // initiated closures and does not invoke callbacks back to the channel user.
486   // TODO(armansito): Change this if statement into an assert when a registry
487   // gets created for LE channels.
488   if (dynamic_registry_) {
489     dynamic_registry_->CloseChannel(id, std::move(removed_cb));
490     return;
491   }
492 
493   removed_cb();
494 }
495 
SignalError()496 void LogicalLink::SignalError() {
497   if (closed_) {
498     bt_log(DEBUG, "l2cap", "Ignore SignalError() on closed link");
499     return;
500   }
501 
502   bt_log(INFO,
503          "l2cap",
504          "Upper layer error on link %#.4x; closing all channels",
505          handle());
506 
507   size_t num_channels_to_close = channels_.size();
508 
509   if (signaling_channel_) {
510     PW_CHECK(channels_.count(kSignalingChannelId) ||
511              channels_.count(kLESignalingChannelId));
512     // There is no need to close the signaling channel.
513     num_channels_to_close--;
514   }
515 
516   if (num_channels_to_close == 0) {
517     link_error_cb_();
518     return;
519   }
520 
521   // num_channels_closing is shared across all callbacks.
522   fit::closure channel_removed_cb =
523       [this, channels_remaining = num_channels_to_close]() mutable {
524         channels_remaining--;
525         if (channels_remaining != 0) {
526           return;
527         }
528         bt_log(TRACE,
529                "l2cap",
530                "Channels on link %#.4x closed; passing error to lower layer",
531                handle());
532         // Invoking error callback may destroy this LogicalLink.
533         link_error_cb_();
534       };
535 
536   for (auto channel_iter = channels_.begin();
537        channel_iter != channels_.end();) {
538     auto& [id, channel] = *channel_iter++;
539 
540     // Do not close the signaling channel, as it is used to close the dynamic
541     // channels.
542     if (id == kSignalingChannelId || id == kLESignalingChannelId) {
543       continue;
544     }
545 
546     // Signal the channel, as it did not request the closure.
547     channel->OnClosed();
548 
549     // This erases from |channel_| and invalidates any iterator pointing to
550     // |channel|.
551     RemoveChannel(channel.get(), channel_removed_cb.share());
552   }
553 }
554 
Close()555 void LogicalLink::Close() {
556   PW_DCHECK(!closed_);
557 
558   closed_ = true;
559 
560   acl_data_channel_->UnregisterConnection(handle_);
561 
562   for (auto& iter : channels_) {
563     iter.second->OnClosed();
564   }
565   channels_.clear();
566   dynamic_registry_.reset();
567 }
568 
569 std::optional<DynamicChannelRegistry::ServiceInfo>
OnServiceRequest(Psm psm)570 LogicalLink::OnServiceRequest(Psm psm) {
571   PW_DCHECK(!closed_);
572 
573   // Query upper layer for a service handler attached to this PSM.
574   auto result = query_service_cb_(handle_, psm);
575   if (!result) {
576     return std::nullopt;
577   }
578 
579   auto channel_cb = [this, chan_cb = std::move(result->channel_cb)](
580                         const DynamicChannel* dyn_chan) mutable {
581     CompleteDynamicOpen(dyn_chan, std::move(chan_cb));
582   };
583   return DynamicChannelRegistry::ServiceInfo(result->channel_params,
584                                              std::move(channel_cb));
585 }
586 
OnChannelDisconnectRequest(const DynamicChannel * dyn_chan)587 void LogicalLink::OnChannelDisconnectRequest(const DynamicChannel* dyn_chan) {
588   PW_DCHECK(dyn_chan);
589   PW_DCHECK(!closed_);
590 
591   auto iter = channels_.find(dyn_chan->local_cid());
592   if (iter == channels_.end()) {
593     bt_log(WARN,
594            "l2cap",
595            "No ChannelImpl found for closing dynamic channel %#.4x",
596            dyn_chan->local_cid());
597     return;
598   }
599 
600   ChannelImpl* channel = iter->second.get();
601   PW_DCHECK(channel->remote_id() == dyn_chan->remote_cid());
602 
603   // Signal closure because this is a remote disconnection.
604   channel->OnClosed();
605   channels_.erase(iter);
606 
607   // Reset round robin iterator
608   current_channel_ = channels_.begin();
609 }
610 
CompleteDynamicOpen(const DynamicChannel * dyn_chan,ChannelCallback open_cb)611 void LogicalLink::CompleteDynamicOpen(const DynamicChannel* dyn_chan,
612                                       ChannelCallback open_cb) {
613   PW_DCHECK(!closed_);
614 
615   if (!dyn_chan) {
616     open_cb(Channel::WeakPtr());
617     return;
618   }
619 
620   const ChannelId local_cid = dyn_chan->local_cid();
621   const ChannelId remote_cid = dyn_chan->remote_cid();
622   bt_log(DEBUG,
623          "l2cap",
624          "Link %#.4x: Channel opened with ID %#.4x (remote ID: %#.4x, psm: %s)",
625          handle_,
626          local_cid,
627          remote_cid,
628          PsmToString(dyn_chan->psm()).c_str());
629 
630   auto chan_info = dyn_chan->info();
631   // Extract preferred flush timeout to avoid creating channel with a flush
632   // timeout that hasn't been successfully configured yet.
633   auto preferred_flush_timeout = chan_info.flush_timeout;
634   chan_info.flush_timeout.reset();
635 
636   std::unique_ptr<ChannelImpl> chan =
637       ChannelImpl::CreateDynamicChannel(pw_dispatcher_,
638                                         local_cid,
639                                         remote_cid,
640                                         GetWeakPtr(),
641                                         chan_info,
642                                         cmd_channel_->AsWeakPtr(),
643                                         max_acl_payload_size_,
644                                         a2dp_offload_manager_);
645   auto chan_weak = chan->GetWeakPtr();
646   channels_[local_cid] = std::move(chan);
647 
648   if (inspect_properties_.channels_node) {
649     chan_weak->AttachInspect(inspect_properties_.channels_node,
650                              inspect_properties_.channels_node.UniqueName(
651                                  kInspectChannelNodePrefix));
652   }
653 
654   // If a flush timeout was requested for this channel, try to set it before
655   // returning the channel to the client to ensure outbound PDUs have correct
656   // flushable flag.
657   if (preferred_flush_timeout.has_value()) {
658     chan_weak->SetBrEdrAutomaticFlushTimeout(
659         preferred_flush_timeout.value(),
660         [cb = std::move(open_cb), chan_weak](auto /*result*/) {
661           cb(chan_weak);
662         });
663     return;
664   }
665 
666   open_cb(std::move(chan_weak));
667 }
668 
SendFixedChannelsSupportedInformationRequest()669 void LogicalLink::SendFixedChannelsSupportedInformationRequest() {
670   PW_CHECK(signaling_channel_);
671 
672   BrEdrCommandHandler cmd_handler(signaling_channel_.get());
673   if (!cmd_handler.SendInformationRequest(
674           InformationType::kFixedChannelsSupported,
675           [self = GetWeakPtr()](auto& rsp) {
676             if (self.is_alive()) {
677               self->OnRxFixedChannelsSupportedInfoRsp(rsp);
678             }
679           })) {
680     bt_log(ERROR,
681            "l2cap",
682            "Failed to send Fixed Channels Supported Information Request");
683     return;
684   }
685 
686   bt_log(TRACE, "l2cap", "Sent Fixed Channels Supported Information Request");
687 }
688 
OnRxFixedChannelsSupportedInfoRsp(const BrEdrCommandHandler::InformationResponse & rsp)689 void LogicalLink::OnRxFixedChannelsSupportedInfoRsp(
690     const BrEdrCommandHandler::InformationResponse& rsp) {
691   if (rsp.status() == BrEdrCommandHandler::Status::kReject) {
692     bt_log(
693         TRACE,
694         "l2cap",
695         "Fixed Channels Supported Information Request rejected (reason %#.4hx)",
696         static_cast<unsigned short>(rsp.reject_reason()));
697     return;
698   }
699 
700   if (rsp.result() == InformationResult::kNotSupported) {
701     bt_log(TRACE,
702            "l2cap",
703            "Received Fixed Channels Supported Information Response (result: "
704            "Not Supported)");
705     return;
706   }
707 
708   if (rsp.result() != InformationResult::kSuccess) {
709     bt_log(TRACE,
710            "l2cap",
711            "Received Fixed Channels Supported Information Response (result: "
712            "%.4hx)",
713            static_cast<uint16_t>(rsp.result()));
714     return;
715   }
716 
717   if (rsp.type() != InformationType::kFixedChannelsSupported) {
718     bt_log(TRACE,
719            "l2cap",
720            "Incorrect Fixed Channels Supported Information Response type "
721            "(type: %#.4hx)",
722            static_cast<unsigned short>(rsp.type()));
723     return;
724   }
725 
726   bt_log(TRACE,
727          "l2cap",
728          "Received Fixed Channels Supported Information Response (mask: "
729          "%#016" PRIx64 ")",
730          rsp.fixed_channels());
731 
732   fixed_channels_supported_ = rsp.fixed_channels();
733   auto callbacks = std::move(fixed_channels_supported_callbacks_);
734   fixed_channels_supported_callbacks_.clear();
735   for (auto& [_, cb] : callbacks) {
736     cb();
737   }
738 }
739 
SendConnectionParameterUpdateRequest(hci_spec::LEPreferredConnectionParameters params,ConnectionParameterUpdateRequestCallback request_cb)740 void LogicalLink::SendConnectionParameterUpdateRequest(
741     hci_spec::LEPreferredConnectionParameters params,
742     ConnectionParameterUpdateRequestCallback request_cb) {
743   PW_CHECK(signaling_channel_);
744   PW_CHECK(type_ == bt::LinkType::kLE);
745   PW_CHECK(role_ == pw::bluetooth::emboss::ConnectionRole::PERIPHERAL);
746 
747   LowEnergyCommandHandler cmd_handler(signaling_channel_.get());
748   cmd_handler.SendConnectionParameterUpdateRequest(
749       params.min_interval(),
750       params.max_interval(),
751       params.max_latency(),
752       params.supervision_timeout(),
753       [cb = std::move(request_cb)](
754           const LowEnergyCommandHandler::ConnectionParameterUpdateResponse&
755               rsp) mutable {
756         bool accepted = false;
757 
758         if (rsp.status() != LowEnergyCommandHandler::Status::kSuccess) {
759           bt_log(TRACE,
760                  "l2cap",
761                  "LE Connection Parameter Update Request rejected (reason: "
762                  "%#.4hx)",
763                  static_cast<unsigned short>(rsp.reject_reason()));
764         } else {
765           accepted = rsp.result() == ConnectionParameterUpdateResult::kAccepted;
766         }
767         cb(accepted);
768       });
769 }
770 
RequestAclPriority(Channel::WeakPtr channel,AclPriority priority,fit::callback<void (fit::result<fit::failed>)> callback)771 void LogicalLink::RequestAclPriority(
772     Channel::WeakPtr channel,
773     AclPriority priority,
774     fit::callback<void(fit::result<fit::failed>)> callback) {
775   PW_CHECK(channel.is_alive());
776   auto iter = channels_.find(channel->id());
777   PW_CHECK(iter != channels_.end());
778   pending_acl_requests_.push(
779       PendingAclRequest{std::move(channel), priority, std::move(callback)});
780   if (pending_acl_requests_.size() == 1) {
781     HandleNextAclPriorityRequest();
782   }
783 }
784 
SetBrEdrAutomaticFlushTimeout(pw::chrono::SystemClock::duration flush_timeout,hci::ResultCallback<> callback)785 void LogicalLink::SetBrEdrAutomaticFlushTimeout(
786     pw::chrono::SystemClock::duration flush_timeout,
787     hci::ResultCallback<> callback) {
788   if (type_ != bt::LinkType::kACL) {
789     bt_log(
790         ERROR, "l2cap", "attempt to set flush timeout on non-ACL logical link");
791     callback(ToResult(
792         pw::bluetooth::emboss::StatusCode::INVALID_HCI_COMMAND_PARAMETERS));
793     return;
794   }
795 
796   auto callback_wrapper = [self = GetWeakPtr(),
797                            flush_timeout,
798                            cb = std::move(callback)](auto result) mutable {
799     if (self.is_alive() && result.is_ok()) {
800       self->flush_timeout_.Set(flush_timeout);
801     }
802     cb(result);
803   };
804 
805   if (flush_timeout < std::chrono::milliseconds(1) ||
806       (flush_timeout > hci_spec::kMaxAutomaticFlushTimeoutDuration &&
807        flush_timeout != pw::chrono::SystemClock::duration::max())) {
808     callback_wrapper(ToResult(
809         pw::bluetooth::emboss::StatusCode::INVALID_HCI_COMMAND_PARAMETERS));
810     return;
811   }
812 
813   uint16_t converted_flush_timeout;
814   if (flush_timeout == pw::chrono::SystemClock::duration::max()) {
815     // The command treats a flush timeout of 0 as infinite.
816     converted_flush_timeout = 0;
817   } else {
818     // Slight imprecision from casting or converting to ms is fine for the flush
819     // timeout (a few ms difference from the requested value doesn't matter).
820     // Overflow is not possible because of the max value check above.
821     converted_flush_timeout = static_cast<uint16_t>(
822         static_cast<float>(
823             std::chrono::duration_cast<std::chrono::milliseconds>(flush_timeout)
824                 .count()) *
825         hci_spec::kFlushTimeoutMsToCommandParameterConversionFactor);
826     PW_CHECK(converted_flush_timeout != 0);
827     PW_CHECK(converted_flush_timeout <=
828              hci_spec::kMaxAutomaticFlushTimeoutCommandParameterValue);
829   }
830 
831   auto write_timeout = hci::CommandPacket::New<
832       pw::bluetooth::emboss::WriteAutomaticFlushTimeoutCommandWriter>(
833       hci_spec::kWriteAutomaticFlushTimeout);
834   auto write_timeout_view = write_timeout.view_t();
835   write_timeout_view.connection_handle().Write(handle_);
836   write_timeout_view.flush_timeout().Write(converted_flush_timeout);
837 
838   cmd_channel_->SendCommand(
839       std::move(write_timeout),
840       [cb = std::move(callback_wrapper), handle = handle_, flush_timeout](
841           auto, const hci::EventPacket& event) mutable {
842         if (event.ToResult().is_error()) {
843           bt_log(WARN,
844                  "hci",
845                  "WriteAutomaticFlushTimeout command failed (result: %s, "
846                  "handle: %#.4x)",
847                  bt_str(event.ToResult()),
848                  handle);
849         } else {
850           bt_log(DEBUG,
851                  "hci",
852                  "automatic flush timeout updated (handle: %#.4x, timeout: "
853                  "%lld ms)",
854                  handle,
855                  std::chrono::duration_cast<std::chrono::milliseconds>(
856                      flush_timeout)
857                      .count());
858         }
859         cb(event.ToResult());
860       });
861 }
862 
AttachInspect(inspect::Node & parent,std::string name)863 void LogicalLink::AttachInspect(inspect::Node& parent, std::string name) {
864   if (!parent) {
865     return;
866   }
867 
868   auto node = parent.CreateChild(name);
869   inspect_properties_.handle =
870       node.CreateString(kInspectHandlePropertyName,
871                         bt_lib_cpp_string::StringPrintf("%#.4x", handle_));
872   inspect_properties_.link_type =
873       node.CreateString(kInspectLinkTypePropertyName, LinkTypeToString(type_));
874   inspect_properties_.channels_node =
875       node.CreateChild(kInspectChannelsNodeName);
876   flush_timeout_.AttachInspect(node, kInspectFlushTimeoutPropertyName);
877   inspect_properties_.node = std::move(node);
878 
879   for (auto& [_, chan] : channels_) {
880     chan->AttachInspect(inspect_properties_.channels_node,
881                         inspect_properties_.channels_node.UniqueName(
882                             kInspectChannelNodePrefix));
883   }
884 }
885 
HandleNextAclPriorityRequest()886 void LogicalLink::HandleNextAclPriorityRequest() {
887   if (pending_acl_requests_.empty() || closed_) {
888     return;
889   }
890 
891   auto& request = pending_acl_requests_.front();
892   PW_CHECK(request.callback);
893 
894   // Prevent closed channels with queued requests from upgrading channel
895   // priority. Allow closed channels to downgrade priority so that they can
896   // clean up their priority on destruction.
897   if (!request.channel.is_alive() && request.priority != AclPriority::kNormal) {
898     request.callback(fit::failed());
899     pending_acl_requests_.pop();
900     HandleNextAclPriorityRequest();
901     return;
902   }
903 
904   // Skip sending command if desired priority is already set. Do this here
905   // instead of Channel in case Channel queues up multiple requests.
906   if (request.priority == acl_priority_) {
907     request.callback(fit::ok());
908     pending_acl_requests_.pop();
909     HandleNextAclPriorityRequest();
910     return;
911   }
912 
913   // If priority is not kNormal, then a channel might be using a conflicting
914   // priority, and the new priority should not be requested.
915   if (acl_priority_ != AclPriority::kNormal) {
916     for (auto& [chan_id, chan] : channels_) {
917       if ((request.channel.is_alive() &&
918            chan.get() == &request.channel.get()) ||
919           chan->requested_acl_priority() == AclPriority::kNormal) {
920         continue;
921       }
922 
923       // If the request returns priority to normal but a different channel still
924       // requires high priority, skip sending command and just report success.
925       if (request.priority == AclPriority::kNormal) {
926         request.callback(fit::ok());
927         break;
928       }
929 
930       // If the request tries to upgrade priority but it conflicts with another
931       // channel's priority (e.g. sink vs. source), report an error.
932       if (request.priority != chan->requested_acl_priority()) {
933         request.callback(fit::failed());
934         break;
935       }
936     }
937 
938     if (!request.callback) {
939       pending_acl_requests_.pop();
940       HandleNextAclPriorityRequest();
941       return;
942     }
943   }
944 
945   auto cb_wrapper = [self = GetWeakPtr(),
946                      cb = std::move(request.callback),
947                      priority = request.priority](auto result) mutable {
948     if (!self.is_alive()) {
949       return;
950     }
951     if (result.is_ok()) {
952       self->acl_priority_ = priority;
953     }
954     cb(result);
955     self->pending_acl_requests_.pop();
956     self->HandleNextAclPriorityRequest();
957   };
958 
959   acl_data_channel_->RequestAclPriority(
960       request.priority, handle_, std::move(cb_wrapper));
961 }
962 
ServeConnectionParameterUpdateRequest()963 void LogicalLink::ServeConnectionParameterUpdateRequest() {
964   PW_CHECK(signaling_channel_);
965   PW_CHECK(type_ == bt::LinkType::kLE);
966 
967   LowEnergyCommandHandler cmd_handler(signaling_channel_.get());
968   cmd_handler.ServeConnectionParameterUpdateRequest(
969       fit::bind_member<&LogicalLink::OnRxConnectionParameterUpdateRequest>(
970           this));
971 }
972 
OnRxConnectionParameterUpdateRequest(uint16_t interval_min,uint16_t interval_max,uint16_t peripheral_latency,uint16_t timeout_multiplier,LowEnergyCommandHandler::ConnectionParameterUpdateResponder * responder)973 void LogicalLink::OnRxConnectionParameterUpdateRequest(
974     uint16_t interval_min,
975     uint16_t interval_max,
976     uint16_t peripheral_latency,
977     uint16_t timeout_multiplier,
978     LowEnergyCommandHandler::ConnectionParameterUpdateResponder* responder) {
979   // Only a LE peripheral can send this command. "If a Peripheral’s Host
980   // receives an L2CAP_CONNECTION_PARAMETER_UPDATE_REQ packet it shall respond
981   // with an L2CAP_COMMAND_REJECT_RSP packet with reason 0x0000 (Command not
982   // understood)." (v5.0, Vol 3, Part A, Section 4.20)
983   if (role_ == pw::bluetooth::emboss::ConnectionRole::PERIPHERAL) {
984     bt_log(
985         DEBUG, "l2cap", "rejecting conn. param. update request from central");
986     responder->RejectNotUnderstood();
987     return;
988   }
989 
990   // Reject the connection parameters if they are outside the ranges allowed by
991   // the HCI specification (see HCI_LE_Connection_Update command v5.0, Vol 2,
992   // Part E, Section 7.8.18).
993   bool reject = false;
994 
995   hci_spec::LEPreferredConnectionParameters params(
996       interval_min, interval_max, peripheral_latency, timeout_multiplier);
997 
998   if (params.min_interval() > params.max_interval()) {
999     bt_log(DEBUG, "l2cap", "conn. min interval larger than max");
1000     reject = true;
1001   } else if (params.min_interval() < hci_spec::kLEConnectionIntervalMin) {
1002     bt_log(DEBUG,
1003            "l2cap",
1004            "conn. min interval outside allowed range: %#.4x",
1005            params.min_interval());
1006     reject = true;
1007   } else if (params.max_interval() > hci_spec::kLEConnectionIntervalMax) {
1008     bt_log(DEBUG,
1009            "l2cap",
1010            "conn. max interval outside allowed range: %#.4x",
1011            params.max_interval());
1012     reject = true;
1013   } else if (params.max_latency() > hci_spec::kLEConnectionLatencyMax) {
1014     bt_log(DEBUG,
1015            "l2cap",
1016            "conn. peripheral latency too large: %#.4x",
1017            params.max_latency());
1018     reject = true;
1019   } else if (params.supervision_timeout() <
1020                  hci_spec::kLEConnectionSupervisionTimeoutMin ||
1021              params.supervision_timeout() >
1022                  hci_spec::kLEConnectionSupervisionTimeoutMax) {
1023     bt_log(DEBUG,
1024            "l2cap",
1025            "conn supv. timeout outside allowed range: %#.4x",
1026            params.supervision_timeout());
1027     reject = true;
1028   }
1029 
1030   ConnectionParameterUpdateResult result =
1031       reject ? ConnectionParameterUpdateResult::kRejected
1032              : ConnectionParameterUpdateResult::kAccepted;
1033   responder->Send(result);
1034 
1035   if (!reject) {
1036     if (!connection_parameter_update_callback_) {
1037       bt_log(DEBUG,
1038              "l2cap",
1039              "no callback set for LE Connection Parameter Update Request");
1040       return;
1041     }
1042 
1043     connection_parameter_update_callback_(params);
1044   }
1045 }
1046 }  // namespace bt::l2cap::internal
1047