1 // Copyright 2024 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 17 #include <fuchsia/bluetooth/cpp/fidl.h> 18 19 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/server_base.h" 20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 21 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h" 22 23 namespace bthost { 24 25 // ChannelServer relays packets and disconnections between the 26 // Connection FIDL protocol and a corresponding L2CAP channel. 27 class ChannelServer : public ServerBase<fuchsia::bluetooth::Channel> { 28 public: 29 // The number of inbound packets to queue in this class. 30 static constexpr size_t kDefaultReceiveQueueLimit = 20; 31 32 // `channel` is the Channel that this ChannelServer corresponds to. This 33 // server will activate and manage the lifetime of this channel. 34 // `closed_callback` will be called when either the fuchsia.bluetooth.Channel 35 // protocol or the L2CAP channel closes. Returns nullptr on failure (failure 36 // to activate the Channel). 37 static std::unique_ptr<ChannelServer> Create( 38 fidl::InterfaceRequest<fuchsia::bluetooth::Channel> request, 39 bt::l2cap::Channel::WeakPtr channel, 40 fit::callback<void()> closed_callback); 41 42 ~ChannelServer() override; 43 44 private: 45 enum class State { 46 kActivating, // Default state. 47 kActivated, 48 kDeactivating, 49 kDeactivated, 50 }; 51 52 ChannelServer(fidl::InterfaceRequest<fuchsia::bluetooth::Channel> request, 53 bt::l2cap::Channel::WeakPtr channel, 54 fit::callback<void()> closed_callback); 55 56 // fuchsia::bluetooth::Channel overrides: 57 void Send(std::vector<::fuchsia::bluetooth::Packet> packets, 58 SendCallback callback) override; 59 void Receive(ReceiveCallback callback) override; 60 void WatchChannelParameters(WatchChannelParametersCallback callback) override; 61 void handle_unknown_method(uint64_t ordinal, 62 bool method_has_response) override; 63 64 bool Activate(); 65 void Deactivate(); 66 67 void OnChannelDataReceived(bt::ByteBufferPtr rx_data); 68 void OnChannelClosed(); 69 void OnProtocolClosed(); 70 void DeactivateAndRequestDestruction(); 71 void ServiceReceiveQueue(); 72 73 bt::l2cap::Channel::WeakPtr channel_; 74 75 // The maximum number of inbound packets to queue when the FIDL protocol is 76 // full. 77 const size_t receive_queue_max_frames_ = kDefaultReceiveQueueLimit; 78 79 // We use a std::deque here to minimize the number dynamic memory allocations 80 // (cf. std::list, which would require allocation on each SDU). This comes, 81 // however, at the cost of higher memory usage when the number of SDUs is 82 // small. (libc++ uses a minimum of 4KB per deque.) 83 std::deque<bt::ByteBufferPtr> receive_queue_; 84 85 // Client callback called when either FIDL protocol closes or L2CAP channel 86 // closes. 87 fit::callback<void()> closed_cb_; 88 89 // Callback for pending Channel::Receive() call. 90 ReceiveCallback receive_cb_ = nullptr; 91 92 // Pending callback for a WatchChannelParameters call. 93 std::optional<WatchChannelParametersCallback> 94 pending_watch_channel_parameters_; 95 96 State state_ = State::kActivating; 97 98 WeakSelf<ChannelServer> weak_self_; // Keep last. 99 }; 100 101 } // namespace bthost 102