• 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 #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