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 synchronously, 93 // regardless of peer support. See channel.h for documentation on 94 // |rx_callback| and |closed_callback|. Returns nullptr if a Channel for 95 // |channel_id| already exists. 96 // 97 // The link MUST not be closed when this is called. 98 Channel::WeakPtr OpenFixedChannel(ChannelId channel_id); 99 100 // Same as |OpenFixedChannel|, but waits for interrogation of the peer to 101 // complete before returning the channel asynchronously via |callback|. The 102 // channel will be null if it is not supported by the peer. 103 void OpenFixedChannelAsync(ChannelId channel_id, ChannelCallback callback); 104 105 // Opens a dynamic channel to the requested |psm| with the preferred 106 // parameters |params| and returns a channel asynchronously via |callback|. 107 // 108 // The link MUST not be closed when this is called. 109 void OpenChannel(Psm psm, ChannelParameters params, ChannelCallback callback); 110 111 // Takes ownership of |packet| for PDU processing and routes it to its target 112 // channel. This must be called on this object's creation thread. 113 // 114 // The link MUST not be closed when this is called. 115 void HandleRxPacket(hci::ACLDataPacketPtr packet); 116 117 // Called by l2cap::Channel when a packet is available. 118 void OnOutboundPacketAvailable(); 119 120 // Requests a security upgrade using the registered security upgrade callback. 121 // Invokes the |callback| argument with the result of the operation. 122 // 123 // Has no effect if the link is closed. 124 void UpgradeSecurity(sm::SecurityLevel level, sm::ResultFunction<> callback); 125 126 // Assigns the security level of this link and resolves pending security 127 // upgrade requests. Has no effect if the link is closed. 128 void AssignSecurityProperties(const sm::SecurityProperties& security); 129 130 // Send a Connection Parameter Update Request on the LE signaling channel. 131 // When the Connection Parameter Update Response is received, |request_cb| 132 // will be called with the result, |accepted|. NOTE: the local Host must be an 133 // LE peripheral. 134 void SendConnectionParameterUpdateRequest( 135 hci_spec::LEPreferredConnectionParameters params, 136 ConnectionParameterUpdateRequestCallback request_cb); 137 138 // Request a change of this link's ACL priority to |priority|. 139 // |channel| must indicate the channel making the request, which must be 140 // alive. |callback| will be called with the result of the request. The 141 // request will fail if |priority| conflicts with another channel's priority 142 // or the controller does not support changing the ACL priority. 143 // 144 // Requests are queued and handled sequentially in order to prevent race 145 // conditions. 146 void RequestAclPriority( 147 Channel::WeakPtr channel, 148 pw::bluetooth::AclPriority priority, 149 fit::callback<void(fit::result<fit::failed>)> callback); 150 151 // Sets an automatic flush timeout with duration |flush_timeout|. |callback| 152 // will be called with the result of the operation. This is only supported if 153 // the link type is kACL (BR/EDR). |flush_timeout| must be in the range [1ms - 154 // hci_spec::kMaxAutomaticFlushTimeoutDuration]. A flush timeout of 155 // pw::chrono::SystemClock::duration::max() indicates an infinite flush 156 // timeout (no automatic flush), the default. 157 void SetBrEdrAutomaticFlushTimeout( 158 pw::chrono::SystemClock::duration flush_timeout, 159 hci::ResultCallback<> callback); 160 161 // Attach LogicalLink's inspect node as a child of |parent| with the given 162 // |name|. 163 void AttachInspect(inspect::Node& parent, std::string name); 164 165 // Assigns the link error callback to be invoked when a channel signals a link 166 // error. 167 void set_error_callback(fit::closure callback); 168 169 // Assigns the security upgrade delegate for this link. 170 void set_security_upgrade_callback(SecurityUpgradeCallback callback); 171 172 // Assigns the callback to be invoked when a valid Connection Parameter Update 173 // Request is received on the signaling channel. 174 void set_connection_parameter_update_callback( 175 LEConnectionParameterUpdateCallback callback); 176 security()177 const sm::SecurityProperties security() { return security_; } 178 179 using WeakPtr = WeakSelf<LogicalLink>::WeakPtr; GetWeakPtr()180 WeakPtr GetWeakPtr() { return weak_self_.GetWeakPtr(); } 181 182 // ConnectionInterface overrides: handle()183 hci_spec::ConnectionHandle handle() const override { return handle_; } type()184 bt::LinkType type() const override { return type_; } 185 std::unique_ptr<hci::ACLDataPacket> GetNextOutboundPacket() override; 186 bool HasAvailablePacket() const override; 187 188 private: 189 friend class ChannelImpl; 190 191 // Returns true if |id| is valid and supported by the peer. 192 bool AllowsFixedChannel(ChannelId id); 193 194 // Called by ChannelImpl::Deactivate(). Removes the channel from the given 195 // link. Calls |removed_cb| when the channel no longer exists. 196 void RemoveChannel(Channel* chan, fit::closure removed_cb); 197 198 // Called by ChannelImpl::SignalLinkError() to disconnect all channels then 199 // signal an error to the lower layers (usually GAP, to request a link 200 // disconnection). Has no effect if the link is closed. 201 void SignalError(); 202 203 // If the service identified by |psm| can be opened, return a function to 204 // complete the channel open for a newly-opened DynamicChannel. Otherwise, 205 // return nullptr. 206 // 207 // This MUST not be called on a closed link. 208 std::optional<DynamicChannelRegistry::ServiceInfo> OnServiceRequest(Psm psm); 209 210 // Called by |dynamic_registry_| when the peer requests the closure of a 211 // dynamic channel using a signaling PDU. 212 // 213 // This MUST not be called on a closed link. 214 void OnChannelDisconnectRequest(const DynamicChannel* dyn_chan); 215 216 // Given a newly-opened dynamic channel as reported by this link's 217 // DynamicChannelRegistry, create a ChannelImpl for it to carry user data, 218 // then pass a pointer to it through |open_cb|. If |dyn_chan| is null, then 219 // pass nullptr into |open_cb|. 220 // 221 // This MUST not be called on a closed link. 222 void CompleteDynamicOpen(const DynamicChannel* dyn_chan, 223 ChannelCallback open_cb); 224 225 // Send an Information Request signaling packet of type Fixed Channels 226 // Supported. 227 void SendFixedChannelsSupportedInformationRequest(); 228 229 // Handler for Information Response signaling packet. This is used to handle 230 // the Fixed Channels Supported information response, which indicates which 231 // fixed channels the peer supports (Core Spec v5.1, Vol 3, Part A, Sec 4.13). 232 // Except for the signaling channels, fixed channels may not be created until 233 // this response has been received. 234 // TODO(fxbug.dev/42119997): save fixed channels mask and use to verify opened 235 // fixed channel ids are supported 236 void OnRxFixedChannelsSupportedInfoRsp( 237 const BrEdrCommandHandler::InformationResponse& rsp); 238 239 // Start serving Connection Parameter Update Requests on the LE signaling 240 // channel. 241 void ServeConnectionParameterUpdateRequest(); 242 243 // Handler called when a Connection Parameter Update Request is received on 244 // the LE signaling channel. 245 void OnRxConnectionParameterUpdateRequest( 246 uint16_t interval_min, 247 uint16_t interval_max, 248 uint16_t peripheral_latency, 249 uint16_t timeout_multiplier, 250 LowEnergyCommandHandler::ConnectionParameterUpdateResponder* responder); 251 252 // Processes the next ACL priority request in the |pending_acl_requests_| 253 // queue. In order to optimize radio performance, ACL priority is downgraded 254 // whenever possible (i.e. when no more channels are requesting high 255 // priority). 256 void HandleNextAclPriorityRequest(); 257 258 // Return true if |current_channel_|'s next packet is part of a PDU that is 259 // already in the process of being sent 260 bool IsNextPacketContinuingFragment() const; 261 262 // Round robins through channels in logical link to get next packet to send 263 // Returns nullptr if there are no connections with pending packets 264 void RoundRobinChannels(); 265 266 pw::async::Dispatcher& pw_dispatcher_; 267 268 sm::SecurityProperties security_; 269 270 // Information about the underlying controller logical link. 271 hci_spec::ConnectionHandle handle_; 272 bt::LinkType type_; 273 pw::bluetooth::emboss::ConnectionRole role_; 274 275 // Maximum number of bytes that should be allowed in a ACL data packet, 276 // excluding the header 277 uint16_t max_acl_payload_size_; 278 279 // The duration after which BR/EDR packets are flushed from the controller. 280 // By default, the flush timeout is pw::chrono::SystemClock::duration::max() 281 // (no automatic flush). 282 UintInspectable<pw::chrono::SystemClock::duration> flush_timeout_; 283 284 fit::closure link_error_cb_; 285 286 SecurityUpgradeCallback security_callback_; 287 288 LEConnectionParameterUpdateCallback connection_parameter_update_callback_; 289 290 // No data packets are processed once this gets set to true. 291 bool closed_; 292 293 // Recombiner is always accessed on the L2CAP thread. 294 Recombiner recombiner_; 295 296 // Channels that were created on this link. Channels notify the link for 297 // removal when deactivated. 298 using ChannelMap = 299 std::unordered_map<ChannelId, std::unique_ptr<ChannelImpl>>; 300 ChannelMap channels_; 301 302 // Round robin iterator for sending packets from channels 303 ChannelMap::iterator current_channel_; 304 305 // Channel that Logical Link is currently sending PDUs from 306 ChannelImpl::WeakPtr current_pdus_channel_; 307 308 // Manages the L2CAP signaling channel on this logical link. Depending on 309 // |type_| this will either implement the LE or BR/EDR signaling commands. 310 std::unique_ptr<SignalingChannel> signaling_channel_; 311 312 std::optional<FixedChannelsSupported> fixed_channels_supported_; 313 std::unordered_map<ChannelId, fit::closure> 314 fixed_channels_supported_callbacks_; 315 316 // Stores packets that have been received on a currently closed channel. We 317 // buffer these for fixed channels so that the data is available when the 318 // channel is opened. 319 using PendingPduMap = std::unordered_map<ChannelId, std::list<PDU>>; 320 PendingPduMap pending_pdus_; 321 322 struct PendingAclRequest { 323 Channel::WeakPtr channel; 324 pw::bluetooth::AclPriority priority; 325 fit::callback<void(fit::result<fit::failed>)> callback; 326 }; 327 std::queue<PendingAclRequest> pending_acl_requests_; 328 329 // The current ACL priority of this link. 330 pw::bluetooth::AclPriority acl_priority_ = 331 pw::bluetooth::AclPriority::kNormal; 332 333 // Dynamic channels opened with the remote. The registry is destroyed and all 334 // procedures terminated when this link gets closed. 335 std::unique_ptr<DynamicChannelRegistry> dynamic_registry_; 336 337 hci::AclDataChannel* acl_data_channel_; 338 hci::CommandChannel* cmd_channel_; 339 340 // Search function for inbound service requests. Returns handler that accepts 341 // opened channels. 342 QueryServiceCallback query_service_cb_; 343 344 struct InspectProperties { 345 inspect::Node node; 346 inspect::Node channels_node; 347 inspect::StringProperty handle; 348 inspect::StringProperty link_type; 349 }; 350 InspectProperties inspect_properties_; 351 352 A2dpOffloadManager& a2dp_offload_manager_; 353 354 WeakSelf<hci::AclDataChannel::ConnectionInterface> weak_conn_interface_; 355 WeakSelf<LogicalLink> weak_self_; 356 357 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LogicalLink); 358 }; 359 360 } // namespace bt::l2cap::internal 361