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