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 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test_double_base.h"
16
17 namespace bt::testing {
18
ControllerTestDoubleBase(pw::async::Dispatcher & pw_dispatcher)19 ControllerTestDoubleBase::ControllerTestDoubleBase(
20 pw::async::Dispatcher& pw_dispatcher)
21 : pw_dispatcher_(pw_dispatcher), heap_dispatcher_(pw_dispatcher) {}
22
~ControllerTestDoubleBase()23 ControllerTestDoubleBase::~ControllerTestDoubleBase() {
24 // When this destructor gets called any subclass state will be undefined. If
25 // Stop() has not been called before reaching this point this can cause
26 // runtime errors when our event loop handlers attempt to invoke the pure
27 // virtual methods of this class.
28 }
29
SendCommandChannelPacket(const ByteBuffer & packet)30 bool ControllerTestDoubleBase::SendCommandChannelPacket(
31 const ByteBuffer& packet) {
32 if (!event_cb_) {
33 return false;
34 }
35
36 // Post packet to simulate async behavior that many tests expect.
37 DynamicByteBuffer buffer(packet);
38 auto self = weak_self_.GetWeakPtr();
39 (void)heap_dispatcher().Post(
40 [self, buffer = std::move(buffer)](pw::async::Context /*ctx*/,
41 pw::Status status) {
42 if (self.is_alive() && status.ok()) {
43 self->event_cb_({reinterpret_cast<const std::byte*>(buffer.data()),
44 buffer.size()});
45 }
46 });
47 return true;
48 }
49
SendACLDataChannelPacket(const ByteBuffer & packet)50 bool ControllerTestDoubleBase::SendACLDataChannelPacket(
51 const ByteBuffer& packet) {
52 if (!acl_cb_) {
53 return false;
54 }
55
56 // Post packet to simulate async behavior that some tests expect.
57 DynamicByteBuffer buffer(packet);
58 auto self = weak_self_.GetWeakPtr();
59 (void)heap_dispatcher().Post(
60 [self, buffer = std::move(buffer)](pw::async::Context /*ctx*/,
61 pw::Status status) {
62 if (self.is_alive() && status.ok()) {
63 self->acl_cb_({reinterpret_cast<const std::byte*>(buffer.data()),
64 buffer.size()});
65 }
66 });
67 return true;
68 }
69
SendScoDataChannelPacket(const ByteBuffer & packet)70 bool ControllerTestDoubleBase::SendScoDataChannelPacket(
71 const ByteBuffer& packet) {
72 if (!sco_cb_) {
73 return false;
74 }
75
76 sco_cb_({reinterpret_cast<const std::byte*>(packet.data()), packet.size()});
77 return true;
78 }
79
SendIsoDataChannelPacket(const pw::span<const std::byte> & packet)80 bool ControllerTestDoubleBase::SendIsoDataChannelPacket(
81 const pw::span<const std::byte>& packet) {
82 if (!iso_cb_) {
83 return false;
84 }
85
86 iso_cb_(packet);
87 return true;
88 }
89
Initialize(PwStatusCallback complete_callback,PwStatusCallback error_callback)90 void ControllerTestDoubleBase::Initialize(PwStatusCallback complete_callback,
91 PwStatusCallback error_callback) {
92 error_cb_ = std::move(error_callback);
93 complete_callback(PW_STATUS_OK);
94 }
95
Close(PwStatusCallback callback)96 void ControllerTestDoubleBase::Close(PwStatusCallback callback) {
97 event_cb_ = nullptr;
98 acl_cb_ = nullptr;
99 sco_cb_ = nullptr;
100 callback(PW_STATUS_OK);
101 }
102
ConfigureSco(ScoCodingFormat coding_format,ScoEncoding encoding,ScoSampleRate sample_rate,pw::Callback<void (pw::Status)> callback)103 void ControllerTestDoubleBase::ConfigureSco(
104 ScoCodingFormat coding_format,
105 ScoEncoding encoding,
106 ScoSampleRate sample_rate,
107 pw::Callback<void(pw::Status)> callback) {
108 if (!configure_sco_cb_) {
109 return;
110 }
111
112 // Post the callback to simulate async behavior with a real controller.
113 auto callback_wrapper =
114 [dispatcher = &pw_dispatcher_,
115 cb = std::move(callback)](pw::Status cb_status) mutable {
116 (void)pw::async::HeapDispatcher(*dispatcher)
117 .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
118 pw::Status status) mutable {
119 if (status.ok()) {
120 cb(cb_status);
121 }
122 });
123 };
124 configure_sco_cb_(
125 coding_format, encoding, sample_rate, std::move(callback_wrapper));
126 }
127
ResetSco(pw::Callback<void (pw::Status)> callback)128 void ControllerTestDoubleBase::ResetSco(
129 pw::Callback<void(pw::Status)> callback) {
130 if (!reset_sco_cb_) {
131 return;
132 }
133
134 // Post the callback to simulate async behavior with a real controller.
135 auto callback_wrapper =
136 [dispatcher = &pw_dispatcher_,
137 cb = std::move(callback)](pw::Status cb_status) mutable {
138 (void)pw::async::HeapDispatcher(*dispatcher)
139 .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
140 pw::Status status) mutable {
141 if (status.ok()) {
142 cb(cb_status);
143 }
144 });
145 };
146 reset_sco_cb_(std::move(callback_wrapper));
147 }
148
149 } // namespace bt::testing
150