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/host/cpp/fidl.h> 18 #include <lib/zx/channel.h> 19 20 #include <memory> 21 #include <unordered_map> 22 #include <unordered_set> 23 24 #include "fuchsia/bluetooth/cpp/fidl.h" 25 #include "fuchsia/bluetooth/sys/cpp/fidl.h" 26 #include "lib/fidl/cpp/interface_request.h" 27 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/server_base.h" 28 #include "pw_bluetooth_sapphire/fuchsia/lib/fidl/hanging_getter.h" 29 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h" 30 #include "pw_bluetooth_sapphire/internal/host/common/macros.h" 31 #include "pw_bluetooth_sapphire/internal/host/gap/adapter.h" 32 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection_manager.h" 33 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_discovery_manager.h" 34 #include "pw_bluetooth_sapphire/internal/host/gap/low_energy_discovery_manager.h" 35 #include "pw_bluetooth_sapphire/internal/host/gap/pairing_delegate.h" 36 #include "pw_bluetooth_sapphire/internal/host/sm/types.h" 37 38 namespace bthost { 39 40 // Implements the Host FIDL interface. Owns all FIDL connections that have been 41 // opened through it. 42 class HostServer : public AdapterServerBase<fuchsia::bluetooth::host::Host>, 43 public bt::gap::PairingDelegate { 44 public: 45 HostServer(zx::channel channel, 46 const bt::gap::Adapter::WeakPtr& adapter, 47 bt::gatt::GATT::WeakPtr gatt); 48 ~HostServer() override; 49 50 // ::fuchsia::bluetooth::host::Host overrides: 51 void RequestProtocol( 52 ::fuchsia::bluetooth::host::ProtocolRequest request) override; 53 void WatchState(WatchStateCallback callback) override; 54 void SetLocalData(::fuchsia::bluetooth::sys::HostData host_data) override; 55 void SetPeerWatcher( 56 ::fidl::InterfaceRequest<::fuchsia::bluetooth::host::PeerWatcher> 57 peer_watcher) override; 58 void SetLocalName(::std::string local_name, 59 SetLocalNameCallback callback) override; 60 void SetDeviceClass(fuchsia::bluetooth::DeviceClass device_class, 61 SetDeviceClassCallback callback) override; 62 63 void StartDiscovery( 64 ::fuchsia::bluetooth::host::HostStartDiscoveryRequest request) override; 65 void SetConnectable(bool connectable, 66 SetConnectableCallback callback) override; 67 void SetDiscoverable(bool discoverable, 68 SetDiscoverableCallback callback) override; 69 void EnableBackgroundScan(bool enabled) override; 70 void EnablePrivacy(bool enabled) override; 71 void SetBrEdrSecurityMode( 72 ::fuchsia::bluetooth::sys::BrEdrSecurityMode mode) override; 73 void SetLeSecurityMode( 74 ::fuchsia::bluetooth::sys::LeSecurityMode mode) override; 75 void SetPairingDelegate( 76 ::fuchsia::bluetooth::sys::InputCapability input, 77 ::fuchsia::bluetooth::sys::OutputCapability output, 78 ::fidl::InterfaceHandle<::fuchsia::bluetooth::sys::PairingDelegate> 79 delegate) override; 80 void Connect(::fuchsia::bluetooth::PeerId id, 81 ConnectCallback callback) override; 82 void Disconnect(::fuchsia::bluetooth::PeerId id, 83 DisconnectCallback callback) override; 84 void Pair(::fuchsia::bluetooth::PeerId id, 85 ::fuchsia::bluetooth::sys::PairingOptions options, 86 PairCallback callback) override; 87 void Forget(::fuchsia::bluetooth::PeerId id, 88 ForgetCallback callback) override; 89 void Shutdown() override; 90 void SetBondingDelegate( 91 ::fidl::InterfaceRequest<::fuchsia::bluetooth::host::BondingDelegate> 92 request) override; 93 void handle_unknown_method(uint64_t ordinal, 94 bool method_has_response) override; 95 96 private: 97 class DiscoverySessionServer 98 : public ServerBase<::fuchsia::bluetooth::host::DiscoverySession> { 99 public: 100 explicit DiscoverySessionServer( 101 fidl::InterfaceRequest<::fuchsia::bluetooth::host::DiscoverySession> 102 request, 103 HostServer* host); 104 Close(zx_status_t epitaph)105 void Close(zx_status_t epitaph) { binding()->Close(epitaph); } 106 107 // ::fuchsia::bluetooth::host::Discovery overrides: 108 void Stop() override; 109 110 private: 111 void handle_unknown_method(uint64_t ordinal, 112 bool method_has_response) override; 113 114 HostServer* host_; 115 }; 116 117 class PeerWatcherServer 118 : public ServerBase<::fuchsia::bluetooth::host::PeerWatcher> { 119 public: 120 PeerWatcherServer(::fidl::InterfaceRequest< 121 ::fuchsia::bluetooth::host::PeerWatcher> request, 122 bt::gap::PeerCache* peer_cache, 123 HostServer* host); 124 ~PeerWatcherServer() override; 125 126 // Called by |adapter()->peer_cache()| when a peer is updated. 127 void OnPeerUpdated(const bt::gap::Peer& peer); 128 129 // Called by |adapter()->peer_cache()| when a peer is removed. 130 void OnPeerRemoved(bt::PeerId identifier); 131 132 void MaybeCallCallback(); 133 134 private: 135 using Updated = std::vector<fuchsia::bluetooth::sys::Peer>; 136 using Removed = std::vector<fuchsia::bluetooth::PeerId>; 137 138 // PeerWatcher overrides: 139 void GetNext(::fuchsia::bluetooth::host::PeerWatcher::GetNextCallback 140 callback) override; 141 void handle_unknown_method(uint64_t ordinal, 142 bool method_has_response) override; 143 144 std::unordered_set<bt::PeerId> updated_; 145 std::unordered_set<bt::PeerId> removed_; 146 147 bt::gap::PeerCache* peer_cache_; 148 // Id of the PeerCache::add_peer_updated_callback callback. Used to remove 149 // the callback when this server is closed. 150 bt::gap::PeerCache::CallbackId peer_updated_callback_id_; 151 152 ::fuchsia::bluetooth::host::PeerWatcher::GetNextCallback callback_ = 153 nullptr; 154 155 HostServer* host_; 156 157 // Keep this as the last member to make sure that all weak pointers are 158 // invalidated before other members get destroyed. 159 WeakSelf<PeerWatcherServer> weak_self_; 160 }; 161 162 class BondingDelegateServer 163 : public ServerBase<::fuchsia::bluetooth::host::BondingDelegate> { 164 public: 165 explicit BondingDelegateServer( 166 ::fidl::InterfaceRequest<::fuchsia::bluetooth::host::BondingDelegate> 167 request, 168 HostServer* host); 169 170 void OnNewBondingData(const bt::gap::Peer& peer); 171 172 private: 173 // BondingDelegate overrides: 174 void RestoreBonds( 175 ::std::vector<::fuchsia::bluetooth::sys::BondingData> bonds, 176 RestoreBondsCallback callback) override; 177 void WatchBonds(WatchBondsCallback callback) override; 178 void handle_unknown_method(uint64_t ordinal, 179 bool method_has_response) override; 180 181 void MaybeNotifyWatchBonds(); 182 183 HostServer* host_; 184 // Queued bond updates that will be sent on the next call to WatchBonds. 185 std::queue<::fuchsia::bluetooth::sys::BondingData> updated_; 186 fit::callback<void( 187 ::fuchsia::bluetooth::host::BondingDelegate_WatchBonds_Result)> 188 watch_bonds_cb_; 189 }; 190 191 // bt::gap::PairingDelegate overrides: 192 bt::sm::IOCapability io_capability() const override; 193 void CompletePairing(bt::PeerId id, bt::sm::Result<> status) override; 194 void ConfirmPairing(bt::PeerId id, ConfirmCallback confirm) override; 195 void DisplayPasskey(bt::PeerId id, 196 uint32_t passkey, 197 DisplayMethod method, 198 ConfirmCallback confirm) override; 199 void RequestPasskey(bt::PeerId id, PasskeyResponseCallback respond) override; 200 201 // Common code used for showing a user intent (except passkey request). 202 void DisplayPairingRequest(bt::PeerId id, 203 std::optional<uint32_t> passkey, 204 fuchsia::bluetooth::sys::PairingMethod method, 205 ConfirmCallback confirm); 206 207 // Called by |adapter()->peer_cache()| when a peer is bonded. 208 void OnPeerBonded(const bt::gap::Peer& peer); 209 210 void ConnectLowEnergy(bt::PeerId id, ConnectCallback callback); 211 void ConnectBrEdr(bt::PeerId peer_id, ConnectCallback callback); 212 213 void PairLowEnergy(bt::PeerId id, 214 ::fuchsia::bluetooth::sys::PairingOptions options, 215 PairCallback callback); 216 void PairBrEdr(bt::PeerId id, PairCallback callback); 217 // Called when a connection is established to a peer, either when initiated 218 // by a user via a client of Host.fidl, or automatically by the GAP adapter 219 void RegisterLowEnergyConnection( 220 std::unique_ptr<bt::gap::LowEnergyConnectionHandle> conn_ref, 221 bool auto_connect); 222 223 // Called when |server| receives a channel connection error. 224 void OnConnectionError(Server* server); 225 226 // Helper to start LE Discovery (called by StartDiscovery) 227 void StartLEDiscovery(); 228 229 void StopDiscovery(zx_status_t epitaph, bool notify_info_change = true); 230 231 void OnDiscoverySessionServerClose(DiscoverySessionServer* server); 232 233 // Resets the I/O capability of this server to no I/O and tells the GAP layer 234 // to reject incoming pairing requests. 235 void ResetPairingDelegate(); 236 237 // Resolves any HostInfo watcher with the current adapter state. 238 void NotifyInfoChange(); 239 240 void RestoreBonds( 241 ::std::vector<::fuchsia::bluetooth::sys::BondingData> bonds, 242 ::fuchsia::bluetooth::host::BondingDelegate::RestoreBondsCallback 243 callback); 244 245 // Helper for binding a fidl::InterfaceRequest to a FIDL server of type 246 // ServerType. 247 template <typename ServerType, typename... Args> BindServer(Args...args)248 void BindServer(Args... args) { 249 auto server = std::make_unique<ServerType>(std::move(args)...); 250 Server* s = server.get(); 251 server->set_error_handler( 252 [this, s](zx_status_t status) { this->OnConnectionError(s); }); 253 servers_[server.get()] = std::move(server); 254 } 255 256 fuchsia::bluetooth::sys::PairingDelegatePtr pairing_delegate_; 257 258 // We hold a weak pointer to GATT for dispatching GATT FIDL requests. 259 bt::gatt::GATT::WeakPtr gatt_; 260 261 std::unordered_map<DiscoverySessionServer*, 262 std::unique_ptr<DiscoverySessionServer>> 263 discovery_session_servers_; 264 std::unique_ptr<bt::gap::LowEnergyDiscoverySession> le_discovery_session_; 265 std::unique_ptr<bt::gap::BrEdrDiscoverySession> bredr_discovery_session_; 266 267 bool requesting_background_scan_; 268 std::unique_ptr<bt::gap::LowEnergyDiscoverySession> le_background_scan_; 269 270 bool requesting_discoverable_; 271 std::unique_ptr<bt::gap::BrEdrDiscoverableSession> 272 bredr_discoverable_session_; 273 274 bt::sm::IOCapability io_capability_; 275 276 // All active FIDL interface servers. 277 // NOTE: Each key is a raw pointer that is owned by the corresponding value. 278 // This allows us to create a set of managed objects that can be looked up via 279 // raw pointer. 280 std::unordered_map<Server*, std::unique_ptr<Server>> servers_; 281 282 // All LE connections that were either initiated by this HostServer or 283 // auto-connected by the system. 284 // TODO(armansito): Consider storing auto-connected references separately from 285 // directly connected references. 286 std::unordered_map<bt::PeerId, 287 std::unique_ptr<bt::gap::LowEnergyConnectionHandle>> 288 le_connections_; 289 290 // Used to drive the WatchState() method. 291 bt_lib_fidl::HangingGetter<fuchsia::bluetooth::sys::HostInfo> info_getter_; 292 293 std::optional<PeerWatcherServer> peer_watcher_server_; 294 295 std::optional<BondingDelegateServer> bonding_delegate_server_; 296 297 // Keep this as the last member to make sure that all weak pointers are 298 // invalidated before other members get destroyed. 299 WeakSelf<HostServer> weak_self_; 300 301 WeakSelf<PairingDelegate> weak_pairing_; 302 303 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(HostServer); 304 }; 305 306 } // namespace bthost 307