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