• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 #include <pw_async/dispatcher.h>
17 #include <pw_async/heap_dispatcher.h>
18 
19 #include "pw_bluetooth/controller.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h"
23 
24 namespace bt::testing {
25 
26 // Abstract base for implementing a fake HCI controller endpoint. This can
27 // directly send ACL data and event packets on request and forward outgoing ACL
28 // data packets to subclass implementations.
29 class ControllerTestDoubleBase : public pw::bluetooth::Controller {
30  public:
31   using PwStatusCallback = pw::Callback<void(pw::Status)>;
32 
33   using EncodeVendorCommandFunction = fit::function<void(
34       pw::bluetooth::VendorCommandParameters,
35       pw::Callback<void(pw::Result<pw::span<const std::byte>>)>)>;
36 
37   using ConfigureScoFunction =
38       fit::function<void(ScoCodingFormat,
39                          ScoEncoding,
40                          ScoSampleRate,
41                          fit::callback<void(pw::Status)>)>;
42 
43   using ResetScoFunction = fit::function<void(fit::callback<void(pw::Status)>)>;
44 
45   explicit ControllerTestDoubleBase(pw::async::Dispatcher& pw_dispatcher);
46   ~ControllerTestDoubleBase() override;
47 
pw_dispatcher()48   pw::async::Dispatcher& pw_dispatcher() { return pw_dispatcher_; }
heap_dispatcher()49   pw::async::HeapDispatcher& heap_dispatcher() { return heap_dispatcher_; }
50 
51   // Sends the given packet over this FakeController's command channel endpoint.
52   // Returns the result of the write operation on the command channel.
53   bool SendCommandChannelPacket(const ByteBuffer& packet);
54 
55   // Sends the given packet over this FakeController's ACL data channel
56   // endpoint.
57   // Returns the result of the write operation on the channel.
58   bool SendACLDataChannelPacket(const ByteBuffer& packet);
59 
60   // Sends the given packet over this ControllerTestDouble's SCO data channel
61   // endpoint.
62   // Returns the result of the write operation on the channel.
63   bool SendScoDataChannelPacket(const ByteBuffer& packet);
64 
65   // Wrapper around SignalError() to support old test code.
Stop()66   void Stop() { SignalError(pw::Status::Aborted()); }
67 
SignalError(pw::Status status)68   void SignalError(pw::Status status) {
69     if (error_cb_) {
70       error_cb_(status);
71     }
72   }
73 
74   // This only has an effect *before* Transport has been initialized.
set_features(FeaturesBits features)75   void set_features(FeaturesBits features) { features_ = features; }
76 
set_encode_vendor_command_cb(EncodeVendorCommandFunction cb)77   void set_encode_vendor_command_cb(EncodeVendorCommandFunction cb) {
78     encode_vendor_command_cb_ = std::move(cb);
79   }
80 
set_configure_sco_cb(ConfigureScoFunction cb)81   void set_configure_sco_cb(ConfigureScoFunction cb) {
82     configure_sco_cb_ = std::move(cb);
83   }
84 
set_reset_sco_cb(ResetScoFunction cb)85   void set_reset_sco_cb(ResetScoFunction cb) { reset_sco_cb_ = std::move(cb); }
86 
87   // Controller overrides:
SetEventFunction(DataFunction func)88   void SetEventFunction(DataFunction func) override {
89     event_cb_ = std::move(func);
90   }
91 
SetReceiveAclFunction(DataFunction func)92   void SetReceiveAclFunction(DataFunction func) override {
93     acl_cb_ = std::move(func);
94   }
95 
SetReceiveScoFunction(DataFunction func)96   void SetReceiveScoFunction(DataFunction func) override {
97     sco_cb_ = std::move(func);
98   }
99 
100   void Initialize(PwStatusCallback complete_callback,
101                   PwStatusCallback error_callback) override;
102 
103   void Close(PwStatusCallback callback) override;
104 
105   void ConfigureSco(ScoCodingFormat coding_format,
106                     ScoEncoding encoding,
107                     ScoSampleRate sample_rate,
108                     pw::Callback<void(pw::Status)> callback) override;
109 
110   void ResetSco(pw::Callback<void(pw::Status)> callback) override;
111 
GetFeatures(pw::Callback<void (FeaturesBits)> callback)112   void GetFeatures(pw::Callback<void(FeaturesBits)> callback) override {
113     callback(features_);
114   }
115 
EncodeVendorCommand(pw::bluetooth::VendorCommandParameters parameters,pw::Callback<void (pw::Result<pw::span<const std::byte>>)> callback)116   void EncodeVendorCommand(
117       pw::bluetooth::VendorCommandParameters parameters,
118       pw::Callback<void(pw::Result<pw::span<const std::byte>>)> callback)
119       override {
120     if (encode_vendor_command_cb_) {
121       encode_vendor_command_cb_(parameters, std::move(callback));
122     }
123   }
124 
125  private:
126   FeaturesBits features_{0};
127   EncodeVendorCommandFunction encode_vendor_command_cb_;
128   ConfigureScoFunction configure_sco_cb_;
129   ResetScoFunction reset_sco_cb_;
130 
131   // Send inbound packets to the host stack:
132   fit::function<void(pw::span<const std::byte>)> event_cb_;
133   DataFunction acl_cb_;
134   DataFunction sco_cb_;
135 
136   PwStatusCallback error_cb_;
137 
138   pw::async::Dispatcher& pw_dispatcher_;
139   pw::async::HeapDispatcher heap_dispatcher_;
140   WeakSelf<ControllerTestDoubleBase> weak_self_{this};
141   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ControllerTestDoubleBase);
142 };
143 
144 }  // namespace bt::testing
145