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 <lib/async/dispatcher.h>
18 
19 #include <cstdint>
20 
21 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/fake_hci_transport_server.h"
22 
23 namespace bt::fidl::testing {
24 
25 class FakeVendorServer final
26     : public ::fidl::Server<fuchsia_hardware_bluetooth::Vendor> {
27  public:
FakeVendorServer(::fidl::ServerEnd<fuchsia_hardware_bluetooth::Vendor> server_end,async_dispatcher_t * dispatcher)28   FakeVendorServer(
29       ::fidl::ServerEnd<fuchsia_hardware_bluetooth::Vendor> server_end,
30       async_dispatcher_t* dispatcher)
31       : binding_(::fidl::BindServer(dispatcher, std::move(server_end), this)),
32         dispatcher_(dispatcher) {}
33 
Unbind()34   void Unbind() { binding_.Unbind(); }
35 
hci_server()36   fidl::testing::FakeHciTransportServer* hci_server() {
37     return &fake_hci_server_.value();
38   }
39 
set_open_hci_error(bool val)40   void set_open_hci_error(bool val) { open_hci_error_ = val; }
41 
42  private:
GetFeatures(GetFeaturesCompleter::Sync & completer)43   void GetFeatures(GetFeaturesCompleter::Sync& completer) override {
44     fuchsia_hardware_bluetooth::VendorFeatures features;
45     features.acl_priority_command(true);
46     completer.Reply(features);
47   }
48 
EncodeCommand(EncodeCommandRequest & request,EncodeCommandCompleter::Sync & completer)49   void EncodeCommand(EncodeCommandRequest& request,
50                      EncodeCommandCompleter::Sync& completer) override {
51     PW_CHECK(request.set_acl_priority()->priority().has_value());
52     PW_CHECK(request.set_acl_priority()->direction().has_value());
53     std::vector<uint8_t> tmp{static_cast<unsigned char>(
54         WhichSetAclPriority(request.set_acl_priority()->priority().value(),
55                             request.set_acl_priority()->direction().value()))};
56     completer.Reply(fit::success(tmp));
57   }
58 
59   // Not supported
OpenHci(OpenHciCompleter::Sync & completer)60   void OpenHci(OpenHciCompleter::Sync& completer) override {
61     BT_PANIC("OpenHci not supported");
62   }
63 
OpenSnoop(OpenSnoopCompleter::Sync & completer)64   void OpenSnoop(OpenSnoopCompleter::Sync& completer) override {
65     BT_PANIC("OpenSnoop not supported");
66   }
67 
OpenHciTransport(OpenHciTransportCompleter::Sync & completer)68   void OpenHciTransport(OpenHciTransportCompleter::Sync& completer) override {
69     if (open_hci_error_) {
70       completer.Reply(fit::error(ZX_ERR_INTERNAL));
71       return;
72     }
73 
74     auto [hci_client_end, hci_server_end] =
75         ::fidl::Endpoints<fuchsia_hardware_bluetooth::HciTransport>::Create();
76 
77     fake_hci_server_.emplace(std::move(hci_server_end), dispatcher_);
78     completer.Reply(fit::success(std::move(hci_client_end)));
79   }
80 
handle_unknown_method(::fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Vendor> metadata,::fidl::UnknownMethodCompleter::Sync & completer)81   void handle_unknown_method(
82       ::fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Vendor>
83           metadata,
84       ::fidl::UnknownMethodCompleter::Sync& completer) override {
85     // Not implemented
86   }
87 
WhichSetAclPriority(fuchsia_hardware_bluetooth::VendorAclPriority priority,fuchsia_hardware_bluetooth::VendorAclDirection direction)88   uint8_t WhichSetAclPriority(
89       fuchsia_hardware_bluetooth::VendorAclPriority priority,
90       fuchsia_hardware_bluetooth::VendorAclDirection direction) {
91     if (priority == fuchsia_hardware_bluetooth::VendorAclPriority::kHigh) {
92       if (direction ==
93           fuchsia_hardware_bluetooth::VendorAclDirection::kSource) {
94         return static_cast<uint8_t>(pw::bluetooth::AclPriority::kSource);
95       }
96       return static_cast<uint8_t>(pw::bluetooth::AclPriority::kSink);
97     }
98     return static_cast<uint8_t>(pw::bluetooth::AclPriority::kNormal);
99   }
100 
101   // Flag for testing. |OpenHci()| returns an error when set to true
102   bool open_hci_error_ = false;
103 
104   std::optional<fidl::testing::FakeHciTransportServer> fake_hci_server_;
105 
106   ::fidl::ServerBindingRef<fuchsia_hardware_bluetooth::Vendor> binding_;
107 
108   async_dispatcher_t* dispatcher_;
109 };
110 
111 }  // namespace bt::fidl::testing
112