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.driver.framework/cpp/fidl.h> 18 #include <fidl/fuchsia.hardware.bluetooth/cpp/fidl.h> 19 #include <lib/async/cpp/wait.h> 20 #include <lib/driver/devfs/cpp/connector.h> 21 #include <pw_async_fuchsia/dispatcher.h> 22 23 #include <queue> 24 #include <unordered_map> 25 26 #include "emulated_peer.h" 27 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h" 28 #include "pw_random_fuchsia/zircon_random_generator.h" 29 30 namespace bt_hci_virtual { 31 32 enum class ChannelType : uint8_t { ACL, COMMAND, EMULATOR, ISO, SNOOP }; 33 34 using AddChildCallback = 35 fit::function<void(fuchsia_driver_framework::wire::NodeAddArgs)>; 36 using ShutdownCallback = fit::function<void()>; 37 38 class EmulatorDevice 39 : public fidl::WireAsyncEventHandler< 40 fuchsia_driver_framework::NodeController>, 41 public fidl::WireAsyncEventHandler<fuchsia_driver_framework::Node>, 42 public fidl::Server<fuchsia_hardware_bluetooth::Emulator>, 43 public fidl::Server<fuchsia_hardware_bluetooth::HciTransport>, 44 public fidl::WireServer<fuchsia_hardware_bluetooth::Vendor> { 45 public: 46 explicit EmulatorDevice(); 47 ~EmulatorDevice(); 48 49 // This error handler is called when the EmulatorDevice is shut down by DFv2. 50 // We call |Shutdown()| to manually delete the heap-allocated EmulatorDevice. on_fidl_error(fidl::UnbindInfo error)51 void on_fidl_error(fidl::UnbindInfo error) override { Shutdown(); } 52 handle_unknown_event(fidl::UnknownEventMetadata<fuchsia_driver_framework::Node> metadata)53 void handle_unknown_event( 54 fidl::UnknownEventMetadata<fuchsia_driver_framework::Node> metadata) 55 override {} handle_unknown_event(fidl::UnknownEventMetadata<fuchsia_driver_framework::NodeController> metadata)56 void handle_unknown_event( 57 fidl::UnknownEventMetadata<fuchsia_driver_framework::NodeController> 58 metadata) override {} 59 60 // Methods used by the VirtualController to control the EmulatorDevice's 61 // lifecycle 62 zx_status_t Initialize(std::string_view name, 63 AddChildCallback callback, 64 ShutdownCallback shutdown); 65 void Shutdown(); 66 set_emulator_ptr(std::unique_ptr<EmulatorDevice> ptr)67 void set_emulator_ptr(std::unique_ptr<EmulatorDevice> ptr) { 68 emulator_ptr_ = std::move(ptr); 69 } 70 emulator_child_node()71 fidl::WireClient<fuchsia_driver_framework::Node>* emulator_child_node() { 72 return &emulator_child_node_; 73 } set_emulator_child_node(fidl::WireClient<fuchsia_driver_framework::Node> node)74 void set_emulator_child_node( 75 fidl::WireClient<fuchsia_driver_framework::Node> node) { 76 emulator_child_node_ = std::move(node); 77 } 78 79 private: 80 // fuchsia_hardware_bluetooth::Emulator overrides: 81 void Publish(PublishRequest& request, 82 PublishCompleter::Sync& completer) override; 83 void AddLowEnergyPeer(AddLowEnergyPeerRequest& request, 84 AddLowEnergyPeerCompleter::Sync& completer) override; 85 void AddBredrPeer(AddBredrPeerRequest& request, 86 AddBredrPeerCompleter::Sync& completer) override; 87 void WatchControllerParameters( 88 WatchControllerParametersCompleter::Sync& completer) override; 89 void WatchLeScanStates(WatchLeScanStatesCompleter::Sync& completer) override; 90 void WatchLegacyAdvertisingStates( 91 WatchLegacyAdvertisingStatesCompleter::Sync& completer) override; 92 void handle_unknown_method( 93 fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Emulator> 94 metadata, 95 fidl::UnknownMethodCompleter::Sync& completer) override; 96 97 // fuchsia_hardware_bluetooth::Vendor overrides: 98 void GetFeatures(GetFeaturesCompleter::Sync& completer) override; 99 void EncodeCommand(EncodeCommandRequestView request, 100 EncodeCommandCompleter::Sync& completer) override; OpenHci(OpenHciCompleter::Sync & completer)101 void OpenHci(OpenHciCompleter::Sync& completer) override {} 102 void OpenHciTransport(OpenHciTransportCompleter::Sync& completer) override; 103 void OpenSnoop(OpenSnoopCompleter::Sync& completer) override; 104 void handle_unknown_method( 105 fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Vendor> metadata, 106 fidl::UnknownMethodCompleter::Sync& completer) override; 107 108 // Server<HciTransport> overrides: 109 void Send(SendRequest& request, SendCompleter::Sync& completer) override; AckReceive(AckReceiveCompleter::Sync & completer)110 void AckReceive(AckReceiveCompleter::Sync& completer) override {} 111 void ConfigureSco(ConfigureScoRequest& request, 112 fidl::Server<fuchsia_hardware_bluetooth::HciTransport>:: 113 ConfigureScoCompleter::Sync& completer) override; 114 void handle_unknown_method( 115 ::fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::HciTransport> 116 metadata, 117 ::fidl::UnknownMethodCompleter::Sync& completer) override; 118 119 void ConnectEmulator( 120 fidl::ServerEnd<fuchsia_hardware_bluetooth::Emulator> request); 121 void ConnectVendor( 122 fidl::ServerEnd<fuchsia_hardware_bluetooth::Vendor> request); 123 124 // Helper function for fuchsia.hardware.bluetooth.Emulator.Publish that adds 125 // bt-hci-device as a child of EmulatorDevice device node 126 zx_status_t AddHciDeviceChildNode(); 127 128 // Helper function used to initialize BR/EDR and LE peers 129 void AddPeer(std::unique_ptr<EmulatedPeer> peer); 130 131 // Event handlers 132 void OnControllerParametersChanged(); 133 void MaybeUpdateControllerParametersChanged(); 134 void OnLegacyAdvertisingStateChanged(); 135 void MaybeUpdateLegacyAdvertisingStates(); 136 137 // Remove bt-hci-device node 138 void UnpublishHci(); 139 140 void OnPeerConnectionStateChanged(const bt::DeviceAddress& address, 141 bt::hci_spec::ConnectionHandle handle, 142 bool connected, 143 bool canceled); 144 145 void SendEventToHost(pw::span<const std::byte> buffer); 146 void SendAclPacketToHost(pw::span<const std::byte> buffer); 147 void SendIsoPacketToHost(pw::span<const std::byte> buffer); 148 149 pw::random_fuchsia::ZirconRandomGenerator rng_; 150 151 // Responsible for running the thread-hostile |fake_device_| 152 pw::async_fuchsia::FuchsiaDispatcher pw_dispatcher_; 153 154 bt::testing::FakeController fake_device_; 155 156 // List of active peers that have been registered with us 157 std::unordered_map<bt::DeviceAddress, std::unique_ptr<EmulatedPeer>> peers_; 158 159 ShutdownCallback shutdown_cb_; 160 161 std::optional<fuchsia_hardware_bluetooth::ControllerParameters> 162 controller_parameters_; 163 std::optional<WatchControllerParametersCompleter::Async> 164 controller_parameters_completer_; 165 166 std::vector<fuchsia_hardware_bluetooth::LegacyAdvertisingState> 167 legacy_adv_states_; 168 std::queue<WatchLegacyAdvertisingStatesCompleter::Async> 169 legacy_adv_states_completers_; 170 171 // HciTransport protocol 172 fidl::ServerBindingGroup<fuchsia_hardware_bluetooth::HciTransport> 173 hci_transport_bindings_; 174 175 // EmulatorDevice 176 fidl::WireClient<fuchsia_driver_framework::Node> emulator_child_node_; 177 driver_devfs::Connector<fuchsia_hardware_bluetooth::Emulator> 178 emulator_devfs_connector_; 179 fidl::ServerBindingGroup<fuchsia_hardware_bluetooth::Emulator> 180 emulator_binding_group_; 181 driver_devfs::Connector<fuchsia_hardware_bluetooth::Vendor> 182 vendor_devfs_connector_; 183 fidl::ServerBindingGroup<fuchsia_hardware_bluetooth::Vendor> 184 vendor_binding_group_; 185 std::unique_ptr<EmulatorDevice> emulator_ptr_; 186 187 // bt-hci-device 188 fidl::WireClient<fuchsia_driver_framework::NodeController> 189 hci_node_controller_; 190 fidl::WireClient<fuchsia_driver_framework::Node> hci_child_node_; 191 }; 192 193 } // namespace bt_hci_virtual 194