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