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 <fidl/fuchsia.hardware.bluetooth/cpp/fidl.h> 18 #include <lib/fpromise/result.h> 19 20 #include <vector> 21 22 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h" 23 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h" 24 25 namespace bt_hci_virtual { 26 27 // Responsible for processing FIDL messages to/from an emulated peer instance. 28 // This class is not thread-safe. 29 // 30 // When the remote end of the FIDL channel gets closed the underlying FakePeer 31 // will be removed from the fake controller and the |closed_callback| that is 32 // passed to the constructor will get notified. The owner of this object should 33 // act on this by destroying this Peer instance. 34 class EmulatedPeer : public fidl::Server<fuchsia_hardware_bluetooth::Peer> { 35 public: 36 using Result = 37 fpromise::result<std::unique_ptr<EmulatedPeer>, 38 fuchsia_hardware_bluetooth::EmulatorPeerError>; 39 40 // Registers a peer with the FakeController using the provided LE parameters. 41 // Returns the peer on success or an error reporting the failure. 42 static Result NewLowEnergy( 43 fuchsia_hardware_bluetooth::PeerParameters parameters, 44 bt::testing::FakeController* fake_controller, 45 async_dispatcher_t* dispatcher); 46 47 // Registers a peer with the FakeController using the provided BR/EDR 48 // parameters. Returns the peer on success or an error reporting the failure. 49 static Result NewBredr(fuchsia_hardware_bluetooth::PeerParameters parameters, 50 bt::testing::FakeController* fake_controller, 51 async_dispatcher_t* dispatcher); 52 53 // The destructor unregisters the Peer if initialized. 54 ~EmulatedPeer(); 55 56 // Rerturns the device address that this instance was initialized with based 57 // on the FIDL parameters. address()58 const bt::DeviceAddress& address() const { return address_; } 59 60 // Assign a callback that will run when the Peer handle gets closed. set_closed_callback(fit::callback<void ()> closed_callback)61 void set_closed_callback(fit::callback<void()> closed_callback) { 62 closed_callback_ = std::move(closed_callback); 63 } 64 65 // fuchsia_hardware_bluetooth::Peer overrides: 66 void AssignConnectionStatus( 67 AssignConnectionStatusRequest& request, 68 AssignConnectionStatusCompleter::Sync& completer) override; 69 void EmulateLeConnectionComplete( 70 EmulateLeConnectionCompleteRequest& request, 71 EmulateLeConnectionCompleteCompleter::Sync& completer) override; 72 void EmulateDisconnectionComplete( 73 EmulateDisconnectionCompleteCompleter::Sync& completer) override; 74 void WatchConnectionStates( 75 WatchConnectionStatesCompleter::Sync& completer) override; 76 void SetDeviceClass(SetDeviceClassRequest& request, 77 SetDeviceClassCompleter::Sync& completer) override; 78 void SetServiceDefinitions( 79 SetServiceDefinitionsRequest& request, 80 SetServiceDefinitionsCompleter::Sync& completer) override; 81 void SetLeAdvertisement( 82 SetLeAdvertisementRequest& request, 83 SetLeAdvertisementCompleter::Sync& completer) override; 84 void handle_unknown_method( 85 fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Peer> metadata, 86 fidl::UnknownMethodCompleter::Sync& completer) override; 87 88 // Updates this peer with the current connection state which is used to notify 89 // its FIDL client of state changes that it is observing. 90 void UpdateConnectionState(bool connected); 91 void MaybeUpdateConnectionStates(); 92 93 private: 94 EmulatedPeer(bt::DeviceAddress address, 95 fidl::ServerEnd<fuchsia_hardware_bluetooth::Peer> request, 96 bt::testing::FakeController* fake_controller, 97 async_dispatcher_t* dispatcher); 98 99 void OnChannelClosed(fidl::UnbindInfo info); 100 void CleanUp(); 101 void NotifyChannelClosed(); 102 103 bt::DeviceAddress address_; 104 bt::testing::FakeController* fake_controller_; 105 fidl::ServerBinding<fuchsia_hardware_bluetooth::Peer> binding_; 106 fit::callback<void()> closed_callback_; 107 108 std::mutex connection_states_lock_; 109 std::vector<fuchsia_hardware_bluetooth::ConnectionState> connection_states_; 110 std::queue<WatchConnectionStatesCompleter::Async> 111 connection_states_completers_ __TA_GUARDED(connection_states_lock_); 112 }; 113 114 } // namespace bt_hci_virtual 115