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 <memory> 19 20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 21 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_configuration.h" 22 #include "pw_bluetooth_sapphire/internal/host/l2cap/command_handler.h" 23 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 24 #include "pw_bluetooth_sapphire/internal/host/l2cap/signaling_channel.h" 25 26 namespace bt::l2cap::internal { 27 28 // Wrapper for a BR/EDR signaling channel that sends and receives command 29 // transactions. 30 class BrEdrCommandHandler final : public CommandHandler { 31 public: 32 class ConnectionResponse final : public Response { 33 public: 34 using PayloadT = ConnectionResponsePayload; 35 static constexpr const char* kName = "Connection Response"; 36 37 using Response::Response; // Inherit ctor 38 bool Decode(const ByteBuffer& payload_buf); 39 result()40 ConnectionResult result() const { return result_; } conn_status()41 ConnectionStatus conn_status() const { return conn_status_; } 42 43 private: 44 ConnectionResult result_; 45 ConnectionStatus conn_status_; 46 }; 47 48 class ConfigurationResponse final : public Response { 49 public: 50 using PayloadT = ConfigurationResponsePayload; 51 static constexpr const char* kName = "Configuration Response"; 52 53 using Response::Response; // Inherit ctor 54 bool Decode(const ByteBuffer& payload_buf); 55 flags()56 uint16_t flags() const { return flags_; } result()57 ConfigurationResult result() const { return result_; } config()58 const ChannelConfiguration& config() const { return config_; } 59 60 private: 61 friend class BrEdrCommandHandler; 62 63 uint16_t flags_; 64 ConfigurationResult result_; 65 ChannelConfiguration config_; 66 }; 67 68 class InformationResponse final : public Response { 69 public: 70 using PayloadT = InformationResponsePayload; 71 static constexpr const char* kName = "Information Response"; 72 73 using Response::Response; // Inherit ctor 74 bool Decode(const ByteBuffer& payload_buf); 75 type()76 InformationType type() const { return type_; } result()77 InformationResult result() const { return result_; } 78 connectionless_mtu()79 uint16_t connectionless_mtu() const { 80 BT_ASSERT(result() == InformationResult::kSuccess); 81 BT_ASSERT(type() == InformationType::kConnectionlessMTU); 82 return data_.To<uint16_t>(); 83 } 84 extended_features()85 ExtendedFeatures extended_features() const { 86 BT_ASSERT(result() == InformationResult::kSuccess); 87 BT_ASSERT(type() == InformationType::kExtendedFeaturesSupported); 88 return data_.To<ExtendedFeatures>(); 89 } 90 fixed_channels()91 FixedChannelsSupported fixed_channels() const { 92 BT_ASSERT(result() == InformationResult::kSuccess); 93 BT_ASSERT(type() == InformationType::kFixedChannelsSupported); 94 return data_.To<FixedChannelsSupported>(); 95 } 96 97 private: 98 friend class BrEdrCommandHandler; 99 100 InformationType type_; 101 InformationResult result_; 102 103 // View into the payload received from the peer in host endianness. It is 104 // only valid for the duration of the InformationResponseCallback 105 // invocation. 106 BufferView data_; 107 }; 108 109 using ConnectionResponseCallback = 110 fit::function<SignalingChannelInterface::ResponseHandlerAction( 111 const ConnectionResponse& rsp)>; 112 using ConfigurationResponseCallback = 113 fit::function<ResponseHandlerAction(const ConfigurationResponse& rsp)>; 114 // Information Responses never have additional responses. 115 using InformationResponseCallback = 116 fit::function<void(const InformationResponse& rsp)>; 117 118 class ConnectionResponder final : public Responder { 119 public: 120 ConnectionResponder(SignalingChannel::Responder* sig_responder, 121 ChannelId remote_cid); 122 123 void Send(ChannelId local_cid, 124 ConnectionResult result, 125 ConnectionStatus status); 126 }; 127 128 class ConfigurationResponder final : public Responder { 129 public: 130 ConfigurationResponder(SignalingChannel::Responder* sig_responder, 131 ChannelId local_cid); 132 133 void Send(ChannelId remote_cid, 134 uint16_t flags, 135 ConfigurationResult result, 136 ChannelConfiguration::ConfigurationOptions options); 137 }; 138 139 class InformationResponder final : public Responder { 140 public: 141 InformationResponder(SignalingChannel::Responder* sig_responder, 142 InformationType type); 143 144 void SendNotSupported(); 145 146 void SendConnectionlessMtu(uint16_t mtu); 147 148 void SendExtendedFeaturesSupported(ExtendedFeatures extended_features); 149 150 void SendFixedChannelsSupported(FixedChannelsSupported channels_supported); 151 152 private: 153 void Send(InformationResult result, const ByteBuffer& data); 154 InformationType type_; 155 }; 156 157 using ConnectionRequestCallback = fit::function<void( 158 Psm psm, ChannelId remote_cid, ConnectionResponder* responder)>; 159 using ConfigurationRequestCallback = 160 fit::function<void(ChannelId local_cid, 161 uint16_t flags, 162 ChannelConfiguration config, 163 ConfigurationResponder* responder)>; 164 using InformationRequestCallback = fit::function<void( 165 InformationType type, InformationResponder* responder)>; 166 167 // |sig| must be valid for the lifetime of this object. 168 // |command_failed_callback| is called if an outbound request timed out with 169 // RTX or ERTX timers after retransmission (if configured). The call may come 170 // after the lifetime of this object. 171 explicit BrEdrCommandHandler(SignalingChannelInterface* sig, 172 fit::closure request_fail_callback = nullptr); 173 ~BrEdrCommandHandler() = default; 174 175 // Disallow copy even though there's no state because having multiple 176 // BrEdrCommandHandlers in the same scope is likely due to a bug or is at 177 // least redundant. 178 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrCommandHandler); 179 180 // Outbound request sending methods. Response callbacks are required to be 181 // non-empty. The callbacks are wrapped and moved into the SignalingChannel 182 // and may outlive BrEdrCommandHandler. 183 bool SendConnectionRequest(uint16_t psm, 184 ChannelId local_cid, 185 ConnectionResponseCallback cb); 186 bool SendConfigurationRequest( 187 ChannelId remote_cid, 188 uint16_t flags, 189 ChannelConfiguration::ConfigurationOptions options, 190 ConfigurationResponseCallback cb); 191 bool SendInformationRequest(InformationType type, 192 InformationResponseCallback cb); 193 194 // Inbound request delegate registration methods. The callbacks are wrapped 195 // and moved into the SignalingChannel and may outlive BrEdrCommandHandler. It 196 // is expected that any request delegates registered will span the lifetime of 197 // its signaling channel and hence link, so no unregistration is provided. 198 // However each call to register will replace any currently registered request 199 // delegate. 200 void ServeConnectionRequest(ConnectionRequestCallback cb); 201 void ServeConfigurationRequest(ConfigurationRequestCallback cb); 202 void ServeInformationRequest(InformationRequestCallback cb); 203 }; 204 205 } // namespace bt::l2cap::internal 206