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 #include "pw_bluetooth_sapphire/fuchsia/host/controllers/fidl_controller.h"
16
17 #include <optional>
18
19 #include "gmock/gmock.h"
20 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/fake_vendor_server.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
22 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/loop_fixture.h"
24 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
25
26 namespace fhbt = fuchsia_hardware_bluetooth;
27
28 namespace bt::controllers {
29
30 namespace {
31
32 constexpr hci_spec::ConnectionHandle kConnectionHandle = 0x0001;
33 const StaticByteBuffer kSetAclPriorityNormalCommand(0x00);
34 const StaticByteBuffer kSetAclPrioritySourceCommand(0x01);
35 const StaticByteBuffer kSetAclPrioritySinkCommand(0x02);
36
37 } // namespace
38
39 class FidlControllerTest : public bt::testing::TestLoopFixture {
40 public:
SetUp()41 void SetUp() override {
42 auto [vendor_client_end, vendor_server_end] =
43 ::fidl::Endpoints<fhbt::Vendor>::Create();
44
45 fake_vendor_server_.emplace(std::move(vendor_server_end), dispatcher());
46 fidl_controller_.emplace(std::move(vendor_client_end), dispatcher());
47 }
48
InitializeController()49 void InitializeController() {
50 controller()->Initialize(
51 [&](pw::Status cb_complete_status) {
52 complete_status_ = cb_complete_status;
53 },
54 [&](pw::Status cb_error) { controller_error_ = cb_error; });
55 ASSERT_FALSE(complete_status_.has_value());
56 ASSERT_FALSE(controller_error_.has_value());
57 }
58
controller()59 FidlController* controller() { return &fidl_controller_.value(); }
60
hci_server()61 fidl::testing::FakeHciTransportServer* hci_server() {
62 return fake_vendor_server_->hci_server();
63 }
64
vendor_server()65 fidl::testing::FakeVendorServer* vendor_server() {
66 return &fake_vendor_server_.value();
67 }
68
complete_status() const69 std::optional<pw::Status> complete_status() const { return complete_status_; }
70
controller_error() const71 std::optional<pw::Status> controller_error() const {
72 return controller_error_;
73 }
74
75 private:
76 std::optional<pw::Status> complete_status_;
77 std::optional<pw::Status> controller_error_;
78 std::optional<fidl::testing::FakeVendorServer> fake_vendor_server_;
79 std::optional<FidlController> fidl_controller_;
80 };
81
TEST_F(FidlControllerTest,SendAndReceiveAclPackets)82 TEST_F(FidlControllerTest, SendAndReceiveAclPackets) {
83 RETURN_IF_FATAL(InitializeController());
84 RunLoopUntilIdle();
85 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
86
87 const StaticByteBuffer acl_packet_0(0x00, 0x01, 0x02, 0x03);
88 controller()->SendAclData(acl_packet_0.subspan());
89 RunLoopUntilIdle();
90 ASSERT_EQ(hci_server()->acl_packets_received().size(), 1u);
91 EXPECT_THAT(hci_server()->acl_packets_received()[0], BufferEq(acl_packet_0));
92
93 const StaticByteBuffer acl_packet_1(0x04, 0x05, 0x06, 0x07);
94 controller()->SendAclData(acl_packet_1.subspan());
95 RunLoopUntilIdle();
96 ASSERT_EQ(hci_server()->acl_packets_received().size(), 2u);
97 EXPECT_THAT(hci_server()->acl_packets_received()[1], BufferEq(acl_packet_1));
98
99 std::vector<DynamicByteBuffer> received_acl;
100 controller()->SetReceiveAclFunction([&](pw::span<const std::byte> buffer) {
101 received_acl.emplace_back(BufferView(buffer.data(), buffer.size()));
102 });
103
104 hci_server()->SendAcl(acl_packet_0.view());
105 RunLoopUntilIdle();
106 ASSERT_EQ(received_acl.size(), 1u);
107 EXPECT_THAT(received_acl[0], BufferEq(acl_packet_0));
108 EXPECT_EQ(hci_server()->acks_received(), 1u);
109
110 hci_server()->SendAcl(acl_packet_1.view());
111 RunLoopUntilIdle();
112 ASSERT_EQ(received_acl.size(), 2u);
113 EXPECT_THAT(received_acl[1], BufferEq(acl_packet_1));
114 EXPECT_EQ(hci_server()->acks_received(), 2u);
115
116 std::optional<pw::Status> close_status;
117 controller()->Close([&](pw::Status status) { close_status = status; });
118 ASSERT_TRUE(close_status.has_value());
119 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
120 }
121
TEST_F(FidlControllerTest,SendCommandsAndReceiveEvents)122 TEST_F(FidlControllerTest, SendCommandsAndReceiveEvents) {
123 RETURN_IF_FATAL(InitializeController());
124 RunLoopUntilIdle();
125 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
126
127 const StaticByteBuffer packet_0(0x00, 0x01, 0x02, 0x03);
128 controller()->SendCommand(packet_0.subspan());
129 RunLoopUntilIdle();
130 ASSERT_EQ(hci_server()->commands_received().size(), 1u);
131 EXPECT_THAT(hci_server()->commands_received()[0], BufferEq(packet_0));
132
133 const StaticByteBuffer packet_1(0x04, 0x05, 0x06, 0x07);
134 controller()->SendCommand(packet_1.subspan());
135 RunLoopUntilIdle();
136 ASSERT_EQ(hci_server()->commands_received().size(), 2u);
137 EXPECT_THAT(hci_server()->commands_received()[1], BufferEq(packet_1));
138
139 std::vector<DynamicByteBuffer> events;
140 controller()->SetEventFunction([&](pw::span<const std::byte> buffer) {
141 events.emplace_back(BufferView(buffer.data(), buffer.size()));
142 });
143
144 hci_server()->SendEvent(packet_1.view());
145 RunLoopUntilIdle();
146 ASSERT_EQ(events.size(), 1u);
147 EXPECT_THAT(events[0], BufferEq(packet_1));
148 EXPECT_EQ(hci_server()->acks_received(), 1u);
149
150 hci_server()->SendEvent(packet_1.view());
151 RunLoopUntilIdle();
152 ASSERT_EQ(events.size(), 2u);
153 EXPECT_THAT(events[1], BufferEq(packet_1));
154 EXPECT_EQ(hci_server()->acks_received(), 2u);
155
156 std::optional<pw::Status> close_status;
157 controller()->Close([&](pw::Status status) { close_status = status; });
158 ASSERT_TRUE(close_status.has_value());
159 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
160 }
161
TEST_F(FidlControllerTest,SendScoWhenNotConfigured)162 TEST_F(FidlControllerTest, SendScoWhenNotConfigured) {
163 RETURN_IF_FATAL(InitializeController());
164 RunLoopUntilIdle();
165 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
166
167 const StaticByteBuffer packet_0(0x00, 0x01, 0x02, 0x03);
168 controller()->SendScoData(packet_0.subspan());
169 RunLoopUntilIdle();
170 ASSERT_EQ(hci_server()->sco_packets_received().size(), 0u);
171 ASSERT_THAT(controller_error(), ::testing::Optional(PW_STATUS_UNKNOWN));
172 }
173
TEST_F(FidlControllerTest,SendAndReceiveSco)174 TEST_F(FidlControllerTest, SendAndReceiveSco) {
175 RETURN_IF_FATAL(InitializeController());
176 RunLoopUntilIdle();
177 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
178
179 int controller_cb_count = 0;
180 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kCvsd,
181 pw::bluetooth::Controller::ScoEncoding::k8Bits,
182 pw::bluetooth::Controller::ScoSampleRate::k8Khz,
183 [&controller_cb_count](pw::Status status) {
184 controller_cb_count++;
185 EXPECT_EQ(status, PW_STATUS_OK);
186 });
187 EXPECT_EQ(controller_cb_count, 1);
188
189 const StaticByteBuffer packet_0(0x00, 0x01, 0x02, 0x03);
190 controller()->SendScoData(packet_0.subspan());
191 RunLoopUntilIdle();
192 ASSERT_EQ(hci_server()->sco_packets_received().size(), 1u);
193 EXPECT_THAT(hci_server()->sco_packets_received()[0], BufferEq(packet_0));
194
195 const StaticByteBuffer packet_1(0x04, 0x05, 0x06, 0x07);
196 controller()->SendScoData(packet_1.subspan());
197 RunLoopUntilIdle();
198 ASSERT_EQ(hci_server()->sco_packets_received().size(), 2u);
199 EXPECT_THAT(hci_server()->sco_packets_received()[1], BufferEq(packet_1));
200
201 std::vector<DynamicByteBuffer> received_sco;
202 controller()->SetReceiveScoFunction([&](pw::span<const std::byte> buffer) {
203 received_sco.emplace_back(BufferView(buffer.data(), buffer.size()));
204 });
205
206 hci_server()->SendSco(packet_1.view());
207 RunLoopUntilIdle();
208 ASSERT_EQ(received_sco.size(), 1u);
209 EXPECT_THAT(received_sco[0], BufferEq(packet_1));
210 EXPECT_EQ(hci_server()->sco_acks_received(), 1u);
211 EXPECT_EQ(hci_server()->acks_received(), 0u);
212
213 hci_server()->SendSco(packet_1.view());
214 RunLoopUntilIdle();
215 ASSERT_EQ(received_sco.size(), 2u);
216 EXPECT_THAT(received_sco[1], BufferEq(packet_1));
217 EXPECT_EQ(hci_server()->sco_acks_received(), 2u);
218
219 std::optional<pw::Status> close_status;
220 controller()->Close([&](pw::Status status) { close_status = status; });
221 ASSERT_TRUE(close_status.has_value());
222 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
223 }
224
TEST_F(FidlControllerTest,SendAndReceiveIso)225 TEST_F(FidlControllerTest, SendAndReceiveIso) {
226 RETURN_IF_FATAL(InitializeController());
227 RunLoopUntilIdle();
228 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
229
230 const StaticByteBuffer iso_packet_0(0x00, 0x01, 0x02, 0x03);
231 controller()->SendIsoData(iso_packet_0.subspan());
232 RunLoopUntilIdle();
233 ASSERT_EQ(hci_server()->iso_packets_received().size(), 1u);
234 EXPECT_THAT(hci_server()->iso_packets_received()[0], BufferEq(iso_packet_0));
235
236 const StaticByteBuffer iso_packet_1(0x04, 0x05, 0x06, 0x07);
237 controller()->SendIsoData(iso_packet_1.subspan());
238 RunLoopUntilIdle();
239 ASSERT_EQ(hci_server()->iso_packets_received().size(), 2u);
240 EXPECT_THAT(hci_server()->iso_packets_received()[1], BufferEq(iso_packet_1));
241
242 std::vector<DynamicByteBuffer> received_iso;
243 controller()->SetReceiveIsoFunction([&](pw::span<const std::byte> buffer) {
244 received_iso.emplace_back(BufferView(buffer.data(), buffer.size()));
245 });
246
247 hci_server()->SendIso(iso_packet_0.view());
248 RunLoopUntilIdle();
249 ASSERT_EQ(received_iso.size(), 1u);
250 EXPECT_THAT(received_iso[0], BufferEq(iso_packet_0));
251 EXPECT_EQ(hci_server()->acks_received(), 1u);
252
253 hci_server()->SendIso(iso_packet_1.view());
254 RunLoopUntilIdle();
255 ASSERT_EQ(received_iso.size(), 2u);
256 EXPECT_THAT(received_iso[1], BufferEq(iso_packet_1));
257 EXPECT_EQ(hci_server()->acks_received(), 2u);
258
259 std::optional<pw::Status> close_status;
260 controller()->Close([&](pw::Status status) { close_status = status; });
261 ASSERT_TRUE(close_status.has_value());
262 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
263 }
264
TEST_F(FidlControllerTest,ConfigureScoWithFormatCvsdEncoding8BitsSampleRate8Khz)265 TEST_F(FidlControllerTest,
266 ConfigureScoWithFormatCvsdEncoding8BitsSampleRate8Khz) {
267 RETURN_IF_FATAL(InitializeController());
268 RunLoopUntilIdle();
269 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
270
271 int device_cb_count = 0;
272 hci_server()->set_check_configure_sco(
273 [&device_cb_count](fhbt::ScoCodingFormat format,
274 fhbt::ScoEncoding encoding,
275 fhbt::ScoSampleRate rate) mutable {
276 device_cb_count++;
277 EXPECT_EQ(format, fhbt::ScoCodingFormat::kCvsd);
278 EXPECT_EQ(encoding, fhbt::ScoEncoding::kBits8);
279 EXPECT_EQ(rate, fhbt::ScoSampleRate::kKhz8);
280 });
281
282 int controller_cb_count = 0;
283 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kCvsd,
284 pw::bluetooth::Controller::ScoEncoding::k8Bits,
285 pw::bluetooth::Controller::ScoSampleRate::k8Khz,
286 [&controller_cb_count](pw::Status status) {
287 controller_cb_count++;
288 EXPECT_EQ(status, PW_STATUS_OK);
289 });
290
291 EXPECT_EQ(device_cb_count, 0);
292 EXPECT_EQ(controller_cb_count, 1);
293 RunLoopUntilIdle();
294 EXPECT_EQ(controller_cb_count, 1);
295 EXPECT_EQ(device_cb_count, 1);
296 }
297
TEST_F(FidlControllerTest,ConfigureScoWithFormatCvsdEncoding16BitsSampleRate8Khz)298 TEST_F(FidlControllerTest,
299 ConfigureScoWithFormatCvsdEncoding16BitsSampleRate8Khz) {
300 RETURN_IF_FATAL(InitializeController());
301 RunLoopUntilIdle();
302 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
303
304 hci_server()->set_check_configure_sco([](fhbt::ScoCodingFormat format,
305 fhbt::ScoEncoding encoding,
306 fhbt::ScoSampleRate rate) {
307 EXPECT_EQ(format, fhbt::ScoCodingFormat::kCvsd);
308 EXPECT_EQ(encoding, fhbt::ScoEncoding::kBits16);
309 EXPECT_EQ(rate, fhbt::ScoSampleRate::kKhz8);
310 });
311
312 int config_cb_count = 0;
313 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kCvsd,
314 pw::bluetooth::Controller::ScoEncoding::k16Bits,
315 pw::bluetooth::Controller::ScoSampleRate::k8Khz,
316 [&](pw::Status status) {
317 config_cb_count++;
318 EXPECT_EQ(status, PW_STATUS_OK);
319 });
320 RunLoopUntilIdle();
321 EXPECT_EQ(config_cb_count, 1);
322 }
323
TEST_F(FidlControllerTest,ConfigureScoWithFormatCvsdEncoding16BitsSampleRate16Khz)324 TEST_F(FidlControllerTest,
325 ConfigureScoWithFormatCvsdEncoding16BitsSampleRate16Khz) {
326 RETURN_IF_FATAL(InitializeController());
327 RunLoopUntilIdle();
328 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
329
330 hci_server()->set_check_configure_sco([](fhbt::ScoCodingFormat format,
331 fhbt::ScoEncoding encoding,
332 fhbt::ScoSampleRate rate) {
333 EXPECT_EQ(format, fhbt::ScoCodingFormat::kCvsd);
334 EXPECT_EQ(encoding, fhbt::ScoEncoding::kBits16);
335 EXPECT_EQ(rate, fhbt::ScoSampleRate::kKhz16);
336 });
337
338 int config_cb_count = 0;
339 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kCvsd,
340 pw::bluetooth::Controller::ScoEncoding::k16Bits,
341 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
342 [&](pw::Status status) {
343 config_cb_count++;
344 EXPECT_EQ(status, PW_STATUS_OK);
345 });
346 RunLoopUntilIdle();
347 EXPECT_EQ(config_cb_count, 1);
348 }
349
TEST_F(FidlControllerTest,ConfigureScoWithFormatMsbcEncoding16BitsSampleRate16Khz)350 TEST_F(FidlControllerTest,
351 ConfigureScoWithFormatMsbcEncoding16BitsSampleRate16Khz) {
352 RETURN_IF_FATAL(InitializeController());
353 RunLoopUntilIdle();
354 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
355
356 hci_server()->set_check_configure_sco([](fhbt::ScoCodingFormat format,
357 fhbt::ScoEncoding encoding,
358 fhbt::ScoSampleRate rate) {
359 EXPECT_EQ(format, fhbt::ScoCodingFormat::kMsbc);
360 EXPECT_EQ(encoding, fhbt::ScoEncoding::kBits16);
361 EXPECT_EQ(rate, fhbt::ScoSampleRate::kKhz16);
362 });
363
364 int config_cb_count = 0;
365 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
366 pw::bluetooth::Controller::ScoEncoding::k16Bits,
367 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
368 [&](pw::Status status) {
369 config_cb_count++;
370 EXPECT_EQ(status, PW_STATUS_OK);
371 });
372 RunLoopUntilIdle();
373 EXPECT_EQ(config_cb_count, 1);
374 }
375
TEST_F(FidlControllerTest,ConfigureAndResetScoTwice)376 TEST_F(FidlControllerTest, ConfigureAndResetScoTwice) {
377 RETURN_IF_FATAL(InitializeController());
378 RunLoopUntilIdle();
379 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
380
381 int device_cb_count = 0;
382 hci_server()->set_reset_sco_callback(
383 [&device_cb_count]() { device_cb_count++; });
384
385 int config_cb_count_0 = 0;
386 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
387 pw::bluetooth::Controller::ScoEncoding::k16Bits,
388 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
389 [&](pw::Status status) {
390 config_cb_count_0++;
391 EXPECT_EQ(status, PW_STATUS_OK);
392 });
393 EXPECT_EQ(config_cb_count_0, 1);
394
395 int reset_cb_count_0 = 0;
396 controller()->ResetSco([&](pw::Status status) {
397 reset_cb_count_0++;
398 EXPECT_EQ(status, PW_STATUS_OK);
399 });
400
401 EXPECT_EQ(device_cb_count, 0);
402 EXPECT_EQ(reset_cb_count_0, 0);
403 RunLoopUntilIdle();
404 EXPECT_EQ(device_cb_count, 1);
405 EXPECT_EQ(reset_cb_count_0, 1);
406
407 int config_cb_count_1 = 0;
408 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
409 pw::bluetooth::Controller::ScoEncoding::k16Bits,
410 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
411 [&](pw::Status status) {
412 config_cb_count_1++;
413 EXPECT_EQ(status, PW_STATUS_OK) << status.str();
414 });
415 EXPECT_EQ(config_cb_count_1, 1);
416
417 int reset_cb_count_1 = 0;
418 controller()->ResetSco([&](pw::Status status) {
419 reset_cb_count_1++;
420 EXPECT_EQ(status, PW_STATUS_OK);
421 });
422
423 EXPECT_EQ(reset_cb_count_1, 0);
424 RunLoopUntilIdle();
425 EXPECT_EQ(device_cb_count, 2);
426 EXPECT_EQ(reset_cb_count_0, 1);
427 EXPECT_EQ(reset_cb_count_1, 1);
428 }
429
TEST_F(FidlControllerTest,CloseUnbindsHciProtocol)430 TEST_F(FidlControllerTest, CloseUnbindsHciProtocol) {
431 RETURN_IF_FATAL(InitializeController());
432 RunLoopUntilIdle();
433 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
434
435 std::optional<pw::Status> close_status;
436 controller()->Close([&](pw::Status status) { close_status = status; });
437 RunLoopUntilIdle();
438 ASSERT_TRUE(close_status.has_value());
439 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
440 EXPECT_FALSE(hci_server()->bound());
441 }
442
TEST_F(FidlControllerTest,HciServerClosesProtocol)443 TEST_F(FidlControllerTest, HciServerClosesProtocol) {
444 RETURN_IF_FATAL(InitializeController());
445 RunLoopUntilIdle();
446 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
447
448 hci_server()->Unbind();
449 RunLoopUntilIdle();
450 ASSERT_THAT(controller_error(),
451 ::testing::Optional(pw::Status::Unavailable()));
452 }
453
TEST_F(FidlControllerTest,VendorGetFeatures)454 TEST_F(FidlControllerTest, VendorGetFeatures) {
455 RETURN_IF_FATAL(InitializeController());
456 RunLoopUntilIdle();
457 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
458
459 std::optional<FidlController::FeaturesBits> features;
460 controller()->GetFeatures(
461 [&](FidlController::FeaturesBits bits) { features = bits; });
462 RunLoopUntilIdle();
463 ASSERT_TRUE(features.has_value());
464 EXPECT_TRUE(*features & FidlController::FeaturesBits::kSetAclPriorityCommand);
465
466 std::optional<pw::Status> close_status;
467 controller()->Close([&](pw::Status status) { close_status = status; });
468 ASSERT_TRUE(close_status.has_value());
469 EXPECT_EQ(close_status.value(), PW_STATUS_OK);
470 }
471
TEST_F(FidlControllerTest,VendorEncodeSetAclPriorityCommandNormal)472 TEST_F(FidlControllerTest, VendorEncodeSetAclPriorityCommandNormal) {
473 RETURN_IF_FATAL(InitializeController());
474 RunLoopUntilIdle();
475 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
476
477 pw::bluetooth::SetAclPriorityCommandParameters params;
478 params.connection_handle = kConnectionHandle;
479 params.priority = pw::bluetooth::AclPriority::kNormal;
480
481 std::optional<DynamicByteBuffer> buffer;
482 controller()->EncodeVendorCommand(
483 params, [&](pw::Result<pw::span<const std::byte>> result) {
484 ASSERT_TRUE(result.ok());
485 buffer.emplace(
486 BufferView(result.value().data(), result.value().size()));
487 });
488 RunLoopUntilIdle();
489 ASSERT_TRUE(buffer);
490 EXPECT_THAT(*buffer, BufferEq(kSetAclPriorityNormalCommand));
491 }
492
TEST_F(FidlControllerTest,VendorEncodeSetAclPriorityCommandSink)493 TEST_F(FidlControllerTest, VendorEncodeSetAclPriorityCommandSink) {
494 RETURN_IF_FATAL(InitializeController());
495 RunLoopUntilIdle();
496 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
497
498 pw::bluetooth::SetAclPriorityCommandParameters params;
499 params.connection_handle = kConnectionHandle;
500 params.priority = pw::bluetooth::AclPriority::kSink;
501
502 std::optional<DynamicByteBuffer> buffer;
503 controller()->EncodeVendorCommand(
504 params, [&](pw::Result<pw::span<const std::byte>> result) {
505 ASSERT_TRUE(result.ok());
506 buffer.emplace(
507 BufferView(result.value().data(), result.value().size()));
508 });
509 RunLoopUntilIdle();
510 ASSERT_TRUE(buffer);
511 EXPECT_THAT(*buffer, BufferEq(kSetAclPrioritySinkCommand));
512 }
513
TEST_F(FidlControllerTest,VendorEncodeSetAclPriorityCommandSource)514 TEST_F(FidlControllerTest, VendorEncodeSetAclPriorityCommandSource) {
515 RETURN_IF_FATAL(InitializeController());
516 RunLoopUntilIdle();
517 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
518
519 pw::bluetooth::SetAclPriorityCommandParameters params;
520 params.connection_handle = kConnectionHandle;
521 params.priority = pw::bluetooth::AclPriority::kSource;
522
523 std::optional<DynamicByteBuffer> buffer;
524 controller()->EncodeVendorCommand(
525 params, [&](pw::Result<pw::span<const std::byte>> result) {
526 ASSERT_TRUE(result.ok());
527 buffer.emplace(
528 BufferView(result.value().data(), result.value().size()));
529 });
530 RunLoopUntilIdle();
531 ASSERT_TRUE(buffer);
532 EXPECT_THAT(*buffer, BufferEq(kSetAclPrioritySourceCommand));
533 }
534
TEST_F(FidlControllerTest,VendorServerClosesChannelBeforeOpenHci)535 TEST_F(FidlControllerTest, VendorServerClosesChannelBeforeOpenHci) {
536 RETURN_IF_FATAL(InitializeController());
537 ASSERT_THAT(complete_status(), std::nullopt);
538 ASSERT_THAT(controller_error(), std::nullopt);
539
540 vendor_server()->Unbind();
541 RunLoopUntilIdle();
542 ASSERT_THAT(complete_status(),
543 ::testing::Optional(pw::Status::Unavailable()));
544 ASSERT_THAT(controller_error(), std::nullopt);
545 }
546
TEST_F(FidlControllerTest,VendorServerClosesProtocolBeforeInitialize)547 TEST_F(FidlControllerTest, VendorServerClosesProtocolBeforeInitialize) {
548 vendor_server()->Unbind();
549 RunLoopUntilIdle();
550
551 RETURN_IF_FATAL(InitializeController());
552 RunLoopUntilIdle();
553 ASSERT_THAT(complete_status(),
554 ::testing::Optional(pw::Status::Unavailable()));
555 ASSERT_THAT(controller_error(), std::nullopt);
556 }
557
TEST_F(FidlControllerTest,VendorOpenHciError)558 TEST_F(FidlControllerTest, VendorOpenHciError) {
559 // Make OpenHci() return error during controller initialization
560 vendor_server()->set_open_hci_error(true);
561
562 RETURN_IF_FATAL(InitializeController());
563 RunLoopUntilIdle();
564 ASSERT_THAT(complete_status(), ::testing::Optional(pw::Status::Internal()));
565 ASSERT_THAT(controller_error(), std::nullopt);
566 }
567
TEST_F(FidlControllerTest,VendorServerClosesProtocol)568 TEST_F(FidlControllerTest, VendorServerClosesProtocol) {
569 RETURN_IF_FATAL(InitializeController());
570 RunLoopUntilIdle();
571 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
572
573 vendor_server()->Unbind();
574 RunLoopUntilIdle();
575 ASSERT_THAT(controller_error(),
576 ::testing::Optional(pw::Status::Unavailable()));
577 }
578
579 // Attempting to send a command once the HciTransport protocol has been closed
580 // from the server end may trigger the driver to terminate. Verify that a clean
581 // shutdown will still occur.
TEST_F(FidlControllerTest,EventClosesDriver)582 TEST_F(FidlControllerTest, EventClosesDriver) {
583 RETURN_IF_FATAL(InitializeController());
584 RunLoopUntilIdle();
585 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
586
587 const StaticByteBuffer kCommandPacket(0x00, 0x01, 0x02, 0x03);
588 const StaticByteBuffer kEventPacket(0x04, 0x05, 0x06, 0x07);
589 controller()->SetEventFunction([&](pw::span<const std::byte> /* buffer */) {
590 hci_server()->Unbind();
591 controller()->SendCommand(kCommandPacket.subspan());
592 });
593 hci_server()->SendEvent(kEventPacket.view());
594 RunLoopUntilIdle();
595 }
596
TEST_F(FidlControllerTest,ScoServerClosesProtocolUnexpectedly)597 TEST_F(FidlControllerTest, ScoServerClosesProtocolUnexpectedly) {
598 RETURN_IF_FATAL(InitializeController());
599 RunLoopUntilIdle();
600 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
601
602 int config_cb_count = 0;
603 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
604 pw::bluetooth::Controller::ScoEncoding::k16Bits,
605 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
606 [&](pw::Status status) {
607 config_cb_count++;
608 EXPECT_EQ(status, PW_STATUS_OK);
609 });
610 RunLoopUntilIdle();
611 EXPECT_EQ(config_cb_count, 1);
612
613 EXPECT_TRUE(hci_server()->UnbindSco());
614 RunLoopUntilIdle();
615 EXPECT_THAT(controller_error(), ::testing::Optional(pw::Status::Unknown()));
616 }
617
TEST_F(FidlControllerTest,ConfigureScoAlreadyConfigured)618 TEST_F(FidlControllerTest, ConfigureScoAlreadyConfigured) {
619 RETURN_IF_FATAL(InitializeController());
620 RunLoopUntilIdle();
621 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
622
623 int config_cb_count_0 = 0;
624 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
625 pw::bluetooth::Controller::ScoEncoding::k16Bits,
626 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
627 [&](pw::Status status) {
628 config_cb_count_0++;
629 EXPECT_EQ(status, PW_STATUS_OK);
630 });
631 int config_cb_count_1 = 0;
632 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
633 pw::bluetooth::Controller::ScoEncoding::k16Bits,
634 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
635 [&](pw::Status status) {
636 config_cb_count_1++;
637 EXPECT_EQ(status, PW_STATUS_ALREADY_EXISTS);
638 });
639 EXPECT_EQ(config_cb_count_0, 1);
640 EXPECT_EQ(config_cb_count_1, 1);
641 RunLoopUntilIdle();
642 EXPECT_EQ(config_cb_count_0, 1);
643 EXPECT_EQ(config_cb_count_1, 1);
644 }
645
TEST_F(FidlControllerTest,ResetScoWhenNotConfiguredFails)646 TEST_F(FidlControllerTest, ResetScoWhenNotConfiguredFails) {
647 RETURN_IF_FATAL(InitializeController());
648 RunLoopUntilIdle();
649 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
650
651 int device_cb_count = 0;
652 hci_server()->set_reset_sco_callback(
653 [&device_cb_count]() { device_cb_count++; });
654
655 int reset_cb_count = 0;
656 controller()->ResetSco([&](pw::Status status) {
657 reset_cb_count++;
658 EXPECT_EQ(status, PW_STATUS_FAILED_PRECONDITION);
659 });
660
661 EXPECT_EQ(device_cb_count, 0);
662 EXPECT_EQ(reset_cb_count, 1);
663 RunLoopUntilIdle();
664 EXPECT_EQ(device_cb_count, 0);
665 EXPECT_EQ(reset_cb_count, 1);
666 }
667
TEST_F(FidlControllerTest,ResetScoAlreadyPending)668 TEST_F(FidlControllerTest, ResetScoAlreadyPending) {
669 RETURN_IF_FATAL(InitializeController());
670 RunLoopUntilIdle();
671 ASSERT_THAT(complete_status(), ::testing::Optional(PW_STATUS_OK));
672
673 int device_cb_count = 0;
674 hci_server()->set_reset_sco_callback(
675 [&device_cb_count]() { device_cb_count++; });
676
677 int config_cb_count_0 = 0;
678 controller()->ConfigureSco(pw::bluetooth::Controller::ScoCodingFormat::kMsbc,
679 pw::bluetooth::Controller::ScoEncoding::k16Bits,
680 pw::bluetooth::Controller::ScoSampleRate::k16Khz,
681 [&](pw::Status status) {
682 config_cb_count_0++;
683 EXPECT_EQ(status, PW_STATUS_OK);
684 });
685 EXPECT_EQ(config_cb_count_0, 1);
686
687 int reset_cb_count_0 = 0;
688 controller()->ResetSco([&](pw::Status status) {
689 reset_cb_count_0++;
690 EXPECT_EQ(status, PW_STATUS_OK);
691 });
692 int reset_cb_count_1 = 0;
693 controller()->ResetSco([&](pw::Status status) {
694 reset_cb_count_1++;
695 EXPECT_EQ(status, PW_STATUS_ALREADY_EXISTS);
696 });
697
698 EXPECT_EQ(device_cb_count, 0);
699 EXPECT_EQ(reset_cb_count_0, 0);
700 EXPECT_EQ(reset_cb_count_1, 1);
701 RunLoopUntilIdle();
702 EXPECT_EQ(device_cb_count, 1);
703 EXPECT_EQ(reset_cb_count_0, 1);
704 EXPECT_EQ(reset_cb_count_1, 1);
705 }
706
707 } // namespace bt::controllers
708