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
Initialize(PwStatusCallback complete_callback,PwStatusCallback error_callback)80 void ControllerTestDoubleBase::Initialize(PwStatusCallback complete_callback,
81 PwStatusCallback error_callback) {
82 error_cb_ = std::move(error_callback);
83 complete_callback(PW_STATUS_OK);
84 }
85
Close(PwStatusCallback callback)86 void ControllerTestDoubleBase::Close(PwStatusCallback callback) {
87 event_cb_ = nullptr;
88 acl_cb_ = nullptr;
89 sco_cb_ = nullptr;
90 callback(PW_STATUS_OK);
91 }
92
ConfigureSco(ScoCodingFormat coding_format,ScoEncoding encoding,ScoSampleRate sample_rate,pw::Callback<void (pw::Status)> callback)93 void ControllerTestDoubleBase::ConfigureSco(
94 ScoCodingFormat coding_format,
95 ScoEncoding encoding,
96 ScoSampleRate sample_rate,
97 pw::Callback<void(pw::Status)> callback) {
98 if (!configure_sco_cb_) {
99 return;
100 }
101
102 // Post the callback to simulate async behavior with a real controller.
103 auto callback_wrapper =
104 [dispatcher = &pw_dispatcher_,
105 cb = std::move(callback)](pw::Status cb_status) mutable {
106 (void)pw::async::HeapDispatcher(*dispatcher)
107 .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
108 pw::Status status) mutable {
109 if (status.ok()) {
110 cb(cb_status);
111 }
112 });
113 };
114 configure_sco_cb_(
115 coding_format, encoding, sample_rate, std::move(callback_wrapper));
116 }
117
ResetSco(pw::Callback<void (pw::Status)> callback)118 void ControllerTestDoubleBase::ResetSco(
119 pw::Callback<void(pw::Status)> callback) {
120 if (!reset_sco_cb_) {
121 return;
122 }
123
124 // Post the callback to simulate async behavior with a real controller.
125 auto callback_wrapper =
126 [dispatcher = &pw_dispatcher_,
127 cb = std::move(callback)](pw::Status cb_status) mutable {
128 (void)pw::async::HeapDispatcher(*dispatcher)
129 .Post([cb_status, cb = std::move(cb)](pw::async::Context /*ctx*/,
130 pw::Status status) mutable {
131 if (status.ok()) {
132 cb(cb_status);
133 }
134 });
135 };
136 reset_sco_cb_(std::move(callback_wrapper));
137 }
138
139 } // namespace bt::testing
140