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