| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_COMMAND_HANDLER_H_ |
| #define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_COMMAND_HANDLER_H_ |
| |
| #include <lib/fit/function.h> |
| |
| #include <memory> |
| |
| #include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/channel_configuration.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/command_handler.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/signaling_channel.h" |
| |
| namespace bt::l2cap::internal { |
| |
| // Wrapper for a BR/EDR signaling channel that sends and receives command |
| // transactions. |
| class BrEdrCommandHandler final : public CommandHandler { |
| public: |
| class ConnectionResponse final : public Response { |
| public: |
| using PayloadT = ConnectionResponsePayload; |
| static constexpr const char* kName = "Connection Response"; |
| |
| using Response::Response; // Inherit ctor |
| bool Decode(const ByteBuffer& payload_buf); |
| |
| ConnectionResult result() const { return result_; } |
| ConnectionStatus conn_status() const { return conn_status_; } |
| |
| private: |
| ConnectionResult result_; |
| ConnectionStatus conn_status_; |
| }; |
| |
| class ConfigurationResponse final : public Response { |
| public: |
| using PayloadT = ConfigurationResponsePayload; |
| static constexpr const char* kName = "Configuration Response"; |
| |
| using Response::Response; // Inherit ctor |
| bool Decode(const ByteBuffer& payload_buf); |
| |
| uint16_t flags() const { return flags_; } |
| ConfigurationResult result() const { return result_; } |
| const ChannelConfiguration& config() const { return config_; } |
| |
| private: |
| friend class BrEdrCommandHandler; |
| |
| uint16_t flags_; |
| ConfigurationResult result_; |
| ChannelConfiguration config_; |
| }; |
| |
| class InformationResponse final : public Response { |
| public: |
| using PayloadT = InformationResponsePayload; |
| static constexpr const char* kName = "Information Response"; |
| |
| using Response::Response; // Inherit ctor |
| bool Decode(const ByteBuffer& payload_buf); |
| |
| InformationType type() const { return type_; } |
| InformationResult result() const { return result_; } |
| |
| uint16_t connectionless_mtu() const { |
| ZX_ASSERT(result() == InformationResult::kSuccess); |
| ZX_ASSERT(type() == InformationType::kConnectionlessMTU); |
| return data_.As<uint16_t>(); |
| } |
| |
| ExtendedFeatures extended_features() const { |
| ZX_ASSERT(result() == InformationResult::kSuccess); |
| ZX_ASSERT(type() == InformationType::kExtendedFeaturesSupported); |
| return data_.As<ExtendedFeatures>(); |
| } |
| |
| FixedChannelsSupported fixed_channels() const { |
| ZX_ASSERT(result() == InformationResult::kSuccess); |
| ZX_ASSERT(type() == InformationType::kFixedChannelsSupported); |
| return data_.As<FixedChannelsSupported>(); |
| } |
| |
| private: |
| friend class BrEdrCommandHandler; |
| |
| InformationType type_; |
| InformationResult result_; |
| |
| // View into the payload received from the peer in host endianness. It is |
| // only valid for the duration of the InformationResponseCallback |
| // invocation. |
| BufferView data_; |
| }; |
| |
| using ConnectionResponseCallback = fit::function<SignalingChannelInterface::ResponseHandlerAction( |
| const ConnectionResponse& rsp)>; |
| using ConfigurationResponseCallback = |
| fit::function<ResponseHandlerAction(const ConfigurationResponse& rsp)>; |
| // Information Responses never have additional responses. |
| using InformationResponseCallback = fit::function<void(const InformationResponse& rsp)>; |
| |
| class ConnectionResponder final : public Responder { |
| public: |
| ConnectionResponder(SignalingChannel::Responder* sig_responder, ChannelId remote_cid); |
| |
| void Send(ChannelId local_cid, ConnectionResult result, ConnectionStatus status); |
| }; |
| |
| class ConfigurationResponder final : public Responder { |
| public: |
| ConfigurationResponder(SignalingChannel::Responder* sig_responder, ChannelId local_cid); |
| |
| void Send(ChannelId remote_cid, uint16_t flags, ConfigurationResult result, |
| ChannelConfiguration::ConfigurationOptions options); |
| }; |
| |
| class InformationResponder final : public Responder { |
| public: |
| InformationResponder(SignalingChannel::Responder* sig_responder, InformationType type); |
| |
| void SendNotSupported(); |
| |
| void SendConnectionlessMtu(uint16_t mtu); |
| |
| void SendExtendedFeaturesSupported(ExtendedFeatures extended_features); |
| |
| void SendFixedChannelsSupported(FixedChannelsSupported channels_supported); |
| |
| private: |
| void Send(InformationResult result, const ByteBuffer& data); |
| InformationType type_; |
| }; |
| |
| using ConnectionRequestCallback = |
| fit::function<void(PSM psm, ChannelId remote_cid, ConnectionResponder* responder)>; |
| using ConfigurationRequestCallback = |
| fit::function<void(ChannelId local_cid, uint16_t flags, ChannelConfiguration config, |
| ConfigurationResponder* responder)>; |
| using InformationRequestCallback = |
| fit::function<void(InformationType type, InformationResponder* responder)>; |
| |
| // |sig| must be valid for the lifetime of this object. |
| // |command_failed_callback| is called if an outbound request timed out with |
| // RTX or ERTX timers after retransmission (if configured). The call may come |
| // after the lifetime of this object. |
| explicit BrEdrCommandHandler(SignalingChannelInterface* sig, |
| fit::closure request_fail_callback = nullptr); |
| ~BrEdrCommandHandler() = default; |
| |
| // Disallow copy even though there's no state because having multiple |
| // BrEdrCommandHandlers in the same scope is likely due to a bug or is at |
| // least redundant. |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrCommandHandler); |
| |
| // Outbound request sending methods. Response callbacks are required to be |
| // non-empty. The callbacks are wrapped and moved into the SignalingChannel |
| // and may outlive BrEdrCommandHandler. |
| bool SendConnectionRequest(uint16_t psm, ChannelId local_cid, ConnectionResponseCallback cb); |
| bool SendConfigurationRequest(ChannelId remote_cid, uint16_t flags, |
| ChannelConfiguration::ConfigurationOptions options, |
| ConfigurationResponseCallback cb); |
| bool SendInformationRequest(InformationType type, InformationResponseCallback cb); |
| |
| // Inbound request delegate registration methods. The callbacks are wrapped |
| // and moved into the SignalingChannel and may outlive BrEdrCommandHandler. It |
| // is expected that any request delegates registered will span the lifetime of |
| // its signaling channel and hence link, so no unregistration is provided. |
| // However each call to register will replace any currently registered request |
| // delegate. |
| void ServeConnectionRequest(ConnectionRequestCallback cb); |
| void ServeConfigurationRequest(ConfigurationRequestCallback cb); |
| void ServeInformationRequest(InformationRequestCallback cb); |
| }; |
| |
| } // namespace bt::l2cap::internal |
| |
| #endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_COMMAND_HANDLER_H_ |