• 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 #include <pw_string/to_string.h>
18 
19 #include <chrono>
20 #include <optional>
21 #include <variant>
22 
23 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
25 #include "pw_bluetooth_sapphire/internal/host/hci-spec/le_connection_parameters.h"
26 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
27 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
28 #include "pw_bluetooth_sapphire/internal/host/sm/error.h"
29 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
30 
31 namespace bt::l2cap {
32 
33 class Channel;
34 // Callback invoked when a channel has been created or when an error occurs
35 // during channel creation (in which case the channel will be nullptr).
36 using ChannelCallback = fit::function<void(WeakSelf<Channel>::WeakPtr)>;
37 
38 // Callback invoked when a logical link should be closed due to an error.
39 using LinkErrorCallback = fit::closure;
40 
41 // Callback called to notify LE preferred connection parameters during the "LE
42 // Connection Parameter Update" procedure.
43 using LEConnectionParameterUpdateCallback =
44     fit::function<void(const hci_spec::LEPreferredConnectionParameters&)>;
45 
46 // Callback called when response received to LE signaling channel Connection
47 // Parameters Update Request. |accepted| indicates whether the parameters were
48 // accepted by the peer.
49 using ConnectionParameterUpdateRequestCallback =
50     fit::function<void(bool accepted)>;
51 
52 // Callback used to deliver LE fixed channels that are created when a LE link is
53 // registered with L2CAP.
54 using LEFixedChannelsCallback = fit::function<void(
55     WeakSelf<Channel>::WeakPtr att, WeakSelf<Channel>::WeakPtr smp)>;
56 
57 // Callback used to request a security upgrade for an active logical link.
58 // Invokes its |callback| argument with the result of the operation.
59 using SecurityUpgradeCallback =
60     fit::function<void(hci_spec::ConnectionHandle ll_handle,
61                        sm::SecurityLevel level,
62                        sm::ResultFunction<> callback)>;
63 
64 // A variant that can hold any channel mode. While the
65 // `CreditBasedFlowControlMode` codes do not intersect with the
66 // `RetransmissionAndFlowControlMode` retransmission and flow control codes,
67 // that is not a property that is guaranteed to hold for all future versions,
68 // and the request-based codes would not be valid in a configuration packet,
69 // unlike the "classic" modes. This type allows us to treat them as separate
70 // namespaces and access each through the variant. Note: Equality comparison
71 // with enum values for either enum are supported.
72 using AnyChannelMode =
73     std::variant<RetransmissionAndFlowControlMode, CreditBasedFlowControlMode>;
74 
75 bool operator==(const AnyChannelMode& any,
76                 RetransmissionAndFlowControlMode mode);
77 bool operator==(RetransmissionAndFlowControlMode mode,
78                 const AnyChannelMode& any);
79 bool operator==(const AnyChannelMode& any, CreditBasedFlowControlMode mode);
80 bool operator==(CreditBasedFlowControlMode mode, const AnyChannelMode& any);
81 bool operator!=(const AnyChannelMode& any,
82                 RetransmissionAndFlowControlMode mode);
83 bool operator!=(RetransmissionAndFlowControlMode mode,
84                 const AnyChannelMode& any);
85 bool operator!=(const AnyChannelMode& any, CreditBasedFlowControlMode mode);
86 bool operator!=(CreditBasedFlowControlMode mode, const AnyChannelMode& any);
87 std::string AnyChannelModeToString(const AnyChannelMode& mode);
88 pw::StatusWithSize AnyChannelModeToPwString(const AnyChannelMode& mode,
89                                             pw::span<char> span);
90 
91 // Channel configuration parameters specified by higher layers.
92 struct ChannelParameters {
93   std::optional<AnyChannelMode> mode;
94   // MTU
95   std::optional<uint16_t> max_rx_sdu_size;
96 
97   std::optional<pw::chrono::SystemClock::duration> flush_timeout;
98 
99   bool operator==(const ChannelParameters& rhs) const {
100     return mode == rhs.mode && max_rx_sdu_size == rhs.max_rx_sdu_size &&
101            flush_timeout == rhs.flush_timeout;
102   }
103 
ToStringChannelParameters104   std::string ToString() const {
105     auto mode_string = mode.has_value() ? AnyChannelModeToString(*mode)
106                                         : std::string("nullopt");
107     auto sdu_string =
108         max_rx_sdu_size.has_value()
109             ? bt_lib_cpp_string::StringPrintf("%hu", *max_rx_sdu_size)
110             : std::string("nullopt");
111     auto flush_timeout_string =
112         flush_timeout
113             ? bt_lib_cpp_string::StringPrintf(
114                   "%lldms",
115                   std::chrono::duration_cast<std::chrono::milliseconds>(
116                       *flush_timeout)
117                       .count())
118             : std::string("nullopt");
119     return bt_lib_cpp_string::StringPrintf(
120         "ChannelParameters{mode: %s, max_rx_sdu_size: %s, flush_timeout: %s}",
121         mode_string.c_str(),
122         sdu_string.c_str(),
123         flush_timeout_string.c_str());
124   }
125 };
126 
127 // Convenience struct for passsing around information about an opened channel.
128 // For example, this is useful when describing the L2CAP channel underlying a
129 // zx::socket.
130 struct ChannelInfo {
131   ChannelInfo() = default;
132 
133   static ChannelInfo MakeBasicMode(
134       uint16_t max_rx_sdu_size,
135       uint16_t max_tx_sdu_size,
136       std::optional<Psm> psm = std::nullopt,
137       std::optional<pw::chrono::SystemClock::duration> flush_timeout =
138           std::nullopt) {
139     return ChannelInfo(RetransmissionAndFlowControlMode::kBasic,
140                        max_rx_sdu_size,
141                        max_tx_sdu_size,
142                        0,
143                        0,
144                        0,
145                        psm,
146                        flush_timeout);
147   }
148 
149   static ChannelInfo MakeEnhancedRetransmissionMode(
150       uint16_t max_rx_sdu_size,
151       uint16_t max_tx_sdu_size,
152       uint8_t n_frames_in_tx_window,
153       uint8_t max_transmissions,
154       uint16_t max_tx_pdu_payload_size,
155       std::optional<Psm> psm = std::nullopt,
156       std::optional<pw::chrono::SystemClock::duration> flush_timeout =
157           std::nullopt) {
158     return ChannelInfo(
159         RetransmissionAndFlowControlMode::kEnhancedRetransmission,
160         max_rx_sdu_size,
161         max_tx_sdu_size,
162         n_frames_in_tx_window,
163         max_transmissions,
164         max_tx_pdu_payload_size,
165         psm,
166         flush_timeout);
167   }
168 
169   ChannelInfo(AnyChannelMode mode,
170               uint16_t max_rx_sdu_size,
171               uint16_t max_tx_sdu_size,
172               uint8_t n_frames_in_tx_window,
173               uint8_t max_transmissions,
174               uint16_t max_tx_pdu_payload_size,
175               std::optional<Psm> psm = std::nullopt,
176               std::optional<pw::chrono::SystemClock::duration> flush_timeout =
177                   std::nullopt)
modeChannelInfo178       : mode(mode),
179         max_rx_sdu_size(max_rx_sdu_size),
180         max_tx_sdu_size(max_tx_sdu_size),
181         n_frames_in_tx_window(n_frames_in_tx_window),
182         max_transmissions(max_transmissions),
183         max_tx_pdu_payload_size(max_tx_pdu_payload_size),
184         psm(psm),
185         flush_timeout(flush_timeout) {}
186 
187   AnyChannelMode mode;
188   uint16_t max_rx_sdu_size;
189   uint16_t max_tx_sdu_size;
190 
191   // For Enhanced Retransmission Mode only. See Core Spec v5.0 Vol 3, Part A,
192   // Sec 5.4 for details on each field. Values are not meaningful if mode =
193   // RetransmissionAndFlowControlMode::kBasic.
194   uint8_t n_frames_in_tx_window;
195   uint8_t max_transmissions;
196   uint16_t max_tx_pdu_payload_size;
197 
198   // PSM of the service the channel is used for.
199   std::optional<Psm> psm;
200 
201   // If present, the channel's packets will be marked as flushable. The value
202   // will be used to configure the link's automatic flush timeout.
203   std::optional<pw::chrono::SystemClock::duration> flush_timeout;
204 };
205 
206 // Data stored for services registered by higher layers.
207 template <typename ChannelCallbackT>
208 struct ServiceInfo {
ServiceInfoServiceInfo209   ServiceInfo(ChannelParameters params, ChannelCallbackT cb)
210       : channel_params(params), channel_cb(std::move(cb)) {}
211   ServiceInfo(ServiceInfo&&) = default;
212   ServiceInfo& operator=(ServiceInfo&&) = default;
213   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ServiceInfo);
214 
215   // Preferred channel configuration parameters for new channels for this
216   // service.
217   ChannelParameters channel_params;
218 
219   // Callback for forwarding new channels to locally-hosted service.
220   ChannelCallbackT channel_cb;
221 };
222 
223 }  // namespace bt::l2cap
224 
225 namespace pw {
226 // AnyChannelMode supports pw::ToString.
227 template <>
228 StatusWithSize ToString(const bt::l2cap::AnyChannelMode& mode,
229                         span<char> buffer);
230 }  // namespace pw
231