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 #pragma once 16 #include <lib/fit/function.h> 17 18 #include <list> 19 #include <memory> 20 #include <mutex> 21 #include <unordered_map> 22 23 #include "pw_bluetooth/vendor.h" 24 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h" 25 #include "pw_bluetooth_sapphire/internal/host/common/macros.h" 26 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" 27 #include "pw_bluetooth_sapphire/internal/host/l2cap/a2dp_offload_manager.h" 28 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_command_handler.h" 29 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h" 30 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h" 31 #include "pw_bluetooth_sapphire/internal/host/l2cap/dynamic_channel_registry.h" 32 #include "pw_bluetooth_sapphire/internal/host/l2cap/fragmenter.h" 33 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 34 #include "pw_bluetooth_sapphire/internal/host/l2cap/low_energy_command_handler.h" 35 #include "pw_bluetooth_sapphire/internal/host/l2cap/recombiner.h" 36 #include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h" 37 #include "pw_bluetooth_sapphire/internal/host/transport/link_type.h" 38 39 namespace bt::l2cap::internal { 40 41 class ChannelImpl; 42 class LESignalingChannel; 43 class SignalingChannel; 44 45 // Represents a controller logical link. Each instance aids in mapping L2CAP 46 // channels to their corresponding controller logical link and vice versa. This 47 // owns each link's signaling fixed channel and the dynamic channel logic that 48 // operates on that channel. A LogicalLink must be explicitly `Close`d before 49 // destruction, and will assert on this behavior in its destructor. 50 // 51 // Instances are created and owned by a ChannelManager. 52 class LogicalLink : public hci::AclDataChannel::ConnectionInterface { 53 public: 54 // Returns a function that accepts opened channels for a registered local 55 // service identified by |psm| on a given connection identified by |handle|, 56 // or nullptr if there is no service registered for that PSM. 57 using QueryServiceCallback = 58 fit::function<std::optional<ChannelManager::ServiceInfo>( 59 hci_spec::ConnectionHandle handle, Psm psm)>; 60 61 // Constructs a new LogicalLink and initializes the signaling fixed channel. 62 // |max_payload_size| shall be the maximum "host to controller" data packet 63 // payload size for the link |type|, per Core Spec v5.0 Vol 2, Part E, 64 // Sec 4.1. Both |query_service_cb| and the inbound channel delivery callback 65 // that it returns will be executed on this object's creation thread. If 66 // |random_channel_ids| is true, assign dynamic channels randomly instead of 67 // starting at the beginning of the dynamic channel range. 68 // |a2dp_offload_manager| is a reference to A2dpOffloadManager that is passed 69 // to channels to use 70 LogicalLink(hci_spec::ConnectionHandle handle, 71 bt::LinkType type, 72 pw::bluetooth::emboss::ConnectionRole role, 73 uint16_t max_acl_payload_size, 74 QueryServiceCallback query_service_cb, 75 hci::AclDataChannel* acl_data_channel, 76 hci::CommandChannel* cmd_channel, 77 bool random_channel_ids, 78 A2dpOffloadManager& a2dp_offload_manager, 79 pw::async::Dispatcher& dispatcher); 80 81 // When a logical link is destroyed it notifies all of its channels to close 82 // themselves. Data packets will no longer be routed to the associated 83 // channels. 84 ~LogicalLink() override; 85 86 // Notifies and closes all open channels on this link. This must be called to 87 // cleanly shut down a LogicalLink. 88 // 89 // The link MUST not be closed when this is called. 90 void Close(); 91 92 // Opens the channel with |channel_id| over this logical link. See channel.h 93 // for documentation on |rx_callback| and |closed_callback|. Returns nullptr 94 // if a Channel for |channel_id| already exists. 95 // 96 // The link MUST not be closed when this is called. 97 Channel::WeakPtr OpenFixedChannel(ChannelId channel_id); 98 99 // Opens a dynamic channel to the requested |psm| with the preferred 100 // parameters |params| and returns a channel asynchronously via |callback|. 101 // 102 // The link MUST not be closed when this is called. 103 void OpenChannel(Psm psm, ChannelParameters params, ChannelCallback callback); 104 105 // Takes ownership of |packet| for PDU processing and routes it to its target 106 // channel. This must be called on this object's creation thread. 107 // 108 // The link MUST not be closed when this is called. 109 void HandleRxPacket(hci::ACLDataPacketPtr packet); 110 111 // Called by l2cap::Channel when a packet is available. 112 void OnOutboundPacketAvailable(); 113 114 // Requests a security upgrade using the registered security upgrade callback. 115 // Invokes the |callback| argument with the result of the operation. 116 // 117 // Has no effect if the link is closed. 118 void UpgradeSecurity(sm::SecurityLevel level, sm::ResultFunction<> callback); 119 120 // Assigns the security level of this link and resolves pending security 121 // upgrade requests. Has no effect if the link is closed. 122 void AssignSecurityProperties(const sm::SecurityProperties& security); 123 124 // Send a Connection Parameter Update Request on the LE signaling channel. 125 // When the Connection Parameter Update Response is received, |request_cb| 126 // will be called with the result, |accepted|. NOTE: the local Host must be an 127 // LE peripheral. 128 void SendConnectionParameterUpdateRequest( 129 hci_spec::LEPreferredConnectionParameters params, 130 ConnectionParameterUpdateRequestCallback request_cb); 131 132 // Request a change of this link's ACL priority to |priority|. 133 // |channel| must indicate the channel making the request, which must be 134 // alive. |callback| will be called with the result of the request. The 135 // request will fail if |priority| conflicts with another channel's priority 136 // or the controller does not support changing the ACL priority. 137 // 138 // Requests are queued and handled sequentially in order to prevent race 139 // conditions. 140 void RequestAclPriority( 141 Channel::WeakPtr channel, 142 pw::bluetooth::AclPriority priority, 143 fit::callback<void(fit::result<fit::failed>)> callback); 144 145 // Sets an automatic flush timeout with duration |flush_timeout|. |callback| 146 // will be called with the result of the operation. This is only supported if 147 // the link type is kACL (BR/EDR). |flush_timeout| must be in the range [1ms - 148 // hci_spec::kMaxAutomaticFlushTimeoutDuration]. A flush timeout of 149 // pw::chrono::SystemClock::duration::max() indicates an infinite flush 150 // timeout (no automatic flush), the default. 151 void SetBrEdrAutomaticFlushTimeout( 152 pw::chrono::SystemClock::duration flush_timeout, 153 hci::ResultCallback<> callback); 154 155 // Attach LogicalLink's inspect node as a child of |parent| with the given 156 // |name|. 157 void AttachInspect(inspect::Node& parent, std::string name); 158 159 // Assigns the link error callback to be invoked when a channel signals a link 160 // error. 161 void set_error_callback(fit::closure callback); 162 163 // Assigns the security upgrade delegate for this link. 164 void set_security_upgrade_callback(SecurityUpgradeCallback callback); 165 166 // Assigns the callback to be invoked when a valid Connection Parameter Update 167 // Request is received on the signaling channel. 168 void set_connection_parameter_update_callback( 169 LEConnectionParameterUpdateCallback callback); 170 security()171 const sm::SecurityProperties security() { return security_; } 172 173 using WeakPtr = WeakSelf<LogicalLink>::WeakPtr; GetWeakPtr()174 WeakPtr GetWeakPtr() { return weak_self_.GetWeakPtr(); } 175 176 // ConnectionInterface overrides: handle()177 hci_spec::ConnectionHandle handle() const override { return handle_; } type()178 bt::LinkType type() const override { return type_; } 179 std::unique_ptr<hci::ACLDataPacket> GetNextOutboundPacket() override; 180 bool HasAvailablePacket() const override; 181 182 private: 183 friend class ChannelImpl; 184 185 // Returns true if |id| is valid and supported by the peer. 186 bool AllowsFixedChannel(ChannelId id); 187 188 // Called by ChannelImpl::Deactivate(). Removes the channel from the given 189 // link. Calls |removed_cb| when the channel no longer exists. 190 void RemoveChannel(Channel* chan, fit::closure removed_cb); 191 192 // Called by ChannelImpl::SignalLinkError() to disconnect all channels then 193 // signal an error to the lower layers (usually GAP, to request a link 194 // disconnection). Has no effect if the link is closed. 195 void SignalError(); 196 197 // If the service identified by |psm| can be opened, return a function to 198 // complete the channel open for a newly-opened DynamicChannel. Otherwise, 199 // return nullptr. 200 // 201 // This MUST not be called on a closed link. 202 std::optional<DynamicChannelRegistry::ServiceInfo> OnServiceRequest(Psm psm); 203 204 // Called by |dynamic_registry_| when the peer requests the closure of a 205 // dynamic channel using a signaling PDU. 206 // 207 // This MUST not be called on a closed link. 208 void OnChannelDisconnectRequest(const DynamicChannel* dyn_chan); 209 210 // Given a newly-opened dynamic channel as reported by this link's 211 // DynamicChannelRegistry, create a ChannelImpl for it to carry user data, 212 // then pass a pointer to it through |open_cb|. If |dyn_chan| is null, then 213 // pass nullptr into |open_cb|. 214 // 215 // This MUST not be called on a closed link. 216 void CompleteDynamicOpen(const DynamicChannel* dyn_chan, 217 ChannelCallback open_cb); 218 219 // Send an Information Request signaling packet of type Fixed Channels 220 // Supported. 221 void SendFixedChannelsSupportedInformationRequest(); 222 223 // Handler for Information Response signaling packet. This is used to handle 224 // the Fixed Channels Supported information response, which indicates which 225 // fixed channels the peer supports (Core Spec v5.1, Vol 3, Part A, Sec 4.13). 226 // Except for the signaling channels, fixed channels may not be created until 227 // this response has been received. 228 // TODO(fxbug.dev/42119997): save fixed channels mask and use to verify opened 229 // fixed channel ids are supported 230 void OnRxFixedChannelsSupportedInfoRsp( 231 const BrEdrCommandHandler::InformationResponse& rsp); 232 233 // Start serving Connection Parameter Update Requests on the LE signaling 234 // channel. 235 void ServeConnectionParameterUpdateRequest(); 236 237 // Handler called when a Connection Parameter Update Request is received on 238 // the LE signaling channel. 239 void OnRxConnectionParameterUpdateRequest( 240 uint16_t interval_min, 241 uint16_t interval_max, 242 uint16_t peripheral_latency, 243 uint16_t timeout_multiplier, 244 LowEnergyCommandHandler::ConnectionParameterUpdateResponder* responder); 245 246 // Processes the next ACL priority request in the |pending_acl_requests_| 247 // queue. In order to optimize radio performance, ACL priority is downgraded 248 // whenever possible (i.e. when no more channels are requesting high 249 // priority). 250 void HandleNextAclPriorityRequest(); 251 252 // Return true if |current_channel_|'s next packet is part of a PDU that is 253 // already in the process of being sent 254 bool IsNextPacketContinuingFragment() const; 255 256 // Round robins through channels in logical link to get next packet to send 257 // Returns nullptr if there are no connections with pending packets 258 void RoundRobinChannels(); 259 260 pw::async::Dispatcher& pw_dispatcher_; 261 262 sm::SecurityProperties security_; 263 264 // Information about the underlying controller logical link. 265 hci_spec::ConnectionHandle handle_; 266 bt::LinkType type_; 267 pw::bluetooth::emboss::ConnectionRole role_; 268 269 // Maximum number of bytes that should be allowed in a ACL data packet, 270 // excluding the header 271 uint16_t max_acl_payload_size_; 272 273 // The duration after which BR/EDR packets are flushed from the controller. 274 // By default, the flush timeout is pw::chrono::SystemClock::duration::max() 275 // (no automatic flush). 276 UintInspectable<pw::chrono::SystemClock::duration> flush_timeout_; 277 278 fit::closure link_error_cb_; 279 280 SecurityUpgradeCallback security_callback_; 281 282 LEConnectionParameterUpdateCallback connection_parameter_update_callback_; 283 284 // No data packets are processed once this gets set to true. 285 bool closed_; 286 287 // Recombiner is always accessed on the L2CAP thread. 288 Recombiner recombiner_; 289 290 // Channels that were created on this link. Channels notify the link for 291 // removal when deactivated. 292 using ChannelMap = 293 std::unordered_map<ChannelId, std::unique_ptr<ChannelImpl>>; 294 ChannelMap channels_; 295 296 // Round robin iterator for sending packets from channels 297 ChannelMap::iterator current_channel_; 298 299 // Channel that Logical Link is currently sending PDUs from 300 ChannelImpl::WeakPtr current_pdus_channel_; 301 302 // Manages the L2CAP signaling channel on this logical link. Depending on 303 // |type_| this will either implement the LE or BR/EDR signaling commands. 304 std::unique_ptr<SignalingChannel> signaling_channel_; 305 306 // Stores packets that have been received on a currently closed channel. We 307 // buffer these for fixed channels so that the data is available when the 308 // channel is opened. 309 using PendingPduMap = std::unordered_map<ChannelId, std::list<PDU>>; 310 PendingPduMap pending_pdus_; 311 312 struct PendingAclRequest { 313 Channel::WeakPtr channel; 314 pw::bluetooth::AclPriority priority; 315 fit::callback<void(fit::result<fit::failed>)> callback; 316 }; 317 std::queue<PendingAclRequest> pending_acl_requests_; 318 319 // The current ACL priority of this link. 320 pw::bluetooth::AclPriority acl_priority_ = 321 pw::bluetooth::AclPriority::kNormal; 322 323 // Dynamic channels opened with the remote. The registry is destroyed and all 324 // procedures terminated when this link gets closed. 325 std::unique_ptr<DynamicChannelRegistry> dynamic_registry_; 326 327 hci::AclDataChannel* acl_data_channel_; 328 hci::CommandChannel* cmd_channel_; 329 330 // Search function for inbound service requests. Returns handler that accepts 331 // opened channels. 332 QueryServiceCallback query_service_cb_; 333 334 struct InspectProperties { 335 inspect::Node node; 336 inspect::Node channels_node; 337 inspect::StringProperty handle; 338 inspect::StringProperty link_type; 339 }; 340 InspectProperties inspect_properties_; 341 342 A2dpOffloadManager& a2dp_offload_manager_; 343 344 WeakSelf<hci::AclDataChannel::ConnectionInterface> weak_conn_interface_; 345 WeakSelf<LogicalLink> weak_self_; 346 347 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LogicalLink); 348 }; 349 350 } // namespace bt::l2cap::internal 351