• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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