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