• 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 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
16 
17 #include <pw_bluetooth/hci_android.emb.h>
18 #include <pw_bluetooth/hci_commands.emb.h>
19 
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/inspect.h"
24 #include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
25 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
27 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
28 
29 namespace bt::hci {
30 namespace {
31 
32 using namespace inspect::testing;
33 
34 using bt::LowerBits;
35 using bt::UpperBits;
36 using EventCallbackResult = CommandChannel::EventCallbackResult;
37 
38 constexpr pw::chrono::SystemClock::duration kCommandTimeout =
39     std::chrono::seconds(12);
40 
41 using TestingBase =
42     bt::testing::FakeDispatcherControllerTest<bt::testing::MockController>;
43 
44 // A reference counted object used to verify that HCI command completion and
45 // status callbacks are properly cleaned up after the end of a transaction.
46 class TestCallbackObject {
47  public:
TestCallbackObject(fit::closure deletion_callback)48   explicit TestCallbackObject(fit::closure deletion_callback)
49       : deletion_cb_(std::move(deletion_callback)) {}
50 
~TestCallbackObject()51   virtual ~TestCallbackObject() { deletion_cb_(); }
52 
53  private:
54   fit::closure deletion_cb_;
55 };
56 
57 class CommandChannelTest : public TestingBase {
58  public:
59   CommandChannelTest() = default;
60   ~CommandChannelTest() override = default;
61 
heap_dispatcher()62   pw::async::HeapDispatcher heap_dispatcher() { return heap_dispatcher_; }
63 
64   inspect::Inspector inspector_;
65 
66  private:
67   pw::async::HeapDispatcher heap_dispatcher_{dispatcher()};
68 };
69 
MakeReadRemoteSupportedFeatures(uint16_t connection_handle)70 EmbossCommandPacket MakeReadRemoteSupportedFeatures(
71     uint16_t connection_handle) {
72   auto packet = EmbossCommandPacket::New<
73       pw::bluetooth::emboss::ReadRemoteSupportedFeaturesCommandWriter>(
74       hci_spec::kReadRemoteSupportedFeatures);
75   packet.view_t().connection_handle().Write(connection_handle);
76   return packet;
77 }
78 
TEST_F(CommandChannelTest,SingleRequestResponse)79 TEST_F(CommandChannelTest, SingleRequestResponse) {
80   // Set up expectations:
81   // clang-format off
82   // HCI_Reset
83   StaticByteBuffer req(
84       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
85       0x00                                   // parameter_total_size
86       );
87   // HCI_CommandComplete
88  StaticByteBuffer rsp(
89       hci_spec::kCommandCompleteEventCode,
90       0x04,  // parameter_total_size (4 byte payload)
91       0x01,  // num_hci_command_packets (1 can be sent)
92       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
93       pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE);
94   // clang-format on
95   EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp);
96 
97   // Send a HCI_Reset command. We attach an instance of TestCallbackObject to
98   // the callbacks to verify that it gets cleaned up as expected.
99   bool test_obj_deleted = false;
100   auto test_obj = std::make_shared<TestCallbackObject>(
101       [&test_obj_deleted] { test_obj_deleted = true; });
102 
103   auto reset =
104       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
105           hci_spec::kReset);
106   CommandChannel::TransactionId id = cmd_channel()->SendCommand(
107       std::move(reset),
108       [&id, test_obj](CommandChannel::TransactionId callback_id,
109                       const EventPacket& event) {
110         EXPECT_EQ(id, callback_id);
111         EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
112         EXPECT_EQ(4, event.view().header().parameter_total_size);
113         EXPECT_EQ(1,
114                   event.view()
115                       .payload<hci_spec::CommandCompleteEventParams>()
116                       .num_hci_command_packets);
117         EXPECT_EQ(hci_spec::kReset,
118                   le16toh(event.view()
119                               .payload<hci_spec::CommandCompleteEventParams>()
120                               .command_opcode));
121         EXPECT_EQ(pw::bluetooth::emboss::StatusCode::HARDWARE_FAILURE,
122                   event.return_params<hci_spec::SimpleReturnParams>()->status);
123       });
124 
125   test_obj = nullptr;
126   EXPECT_FALSE(test_obj_deleted);
127   RunUntilIdle();
128 
129   // Make sure that the I/O thread is no longer holding on to |test_obj|.
130   TearDown();
131 
132   EXPECT_TRUE(test_obj_deleted);
133 }
134 
TEST_F(CommandChannelTest,SingleAsynchronousRequest)135 TEST_F(CommandChannelTest, SingleAsynchronousRequest) {
136   // Set up expectations:
137   // clang-format off
138   // HCI_Inquiry (general, unlimited, 1s)
139  StaticByteBuffer req(
140       LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry),  // HCI_Inquiry opcode
141       0x05,                                      // parameter_total_size
142       0x33, 0x8B, 0x9E,                          // General Inquiry
143       0x01,                                      // 1.28s
144       0x00                                       // Unlimited responses
145       );
146   // HCI_CommandStatus
147   auto rsp0 = StaticByteBuffer(
148        hci_spec::kCommandStatusEventCode,
149       0x04,  // parameter_total_size (4 byte payload)
150       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x01, // status, num_hci_command_packets (1 can be sent)
151       LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry)  // HCI_Inquiry opcode
152       );
153   // HCI_InquiryComplete
154   auto rsp1 = StaticByteBuffer(
155       hci_spec::kInquiryCompleteEventCode,
156       0x01,  // parameter_total_size (1 byte payload)
157       pw::bluetooth::emboss::StatusCode::SUCCESS);
158   // clang-format on
159   EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp0, &rsp1);
160 
161   // Send HCI_Inquiry
162   CommandChannel::TransactionId id;
163   int cb_count = 0;
164   auto cb = [&cb_count, &id](CommandChannel::TransactionId callback_id,
165                              const EventPacket& event) {
166     cb_count++;
167     EXPECT_EQ(callback_id, id);
168     if (cb_count == 1) {
169       ASSERT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
170       const auto params = event.params<hci_spec::CommandStatusEventParams>();
171       EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
172       EXPECT_EQ(hci_spec::kInquiry, params.command_opcode);
173     } else {
174       EXPECT_EQ(hci_spec::kInquiryCompleteEventCode, event.event_code());
175       EXPECT_EQ(fit::ok(), event.ToResult());
176     }
177   };
178 
179   auto packet = hci::EmbossCommandPacket::New<
180       pw::bluetooth::emboss::InquiryCommandWriter>(hci_spec::kInquiry);
181   auto view = packet.view_t();
182   view.lap().Write(pw::bluetooth::emboss::InquiryAccessCode::GIAC);
183   view.inquiry_length().Write(1);
184   view.num_responses().Write(0);
185 
186   id = cmd_channel()->SendCommand(
187       std::move(packet), cb, hci_spec::kInquiryCompleteEventCode);
188   RunUntilIdle();
189   EXPECT_EQ(2, cb_count);
190 }
191 
TEST_F(CommandChannelTest,SingleRequestWithStatusResponse)192 TEST_F(CommandChannelTest, SingleRequestWithStatusResponse) {
193   // Set up expectations
194   // clang-format off
195   // HCI_Reset for the sake of testing
196   auto req = StaticByteBuffer(
197       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
198       0x00                                   // parameter_total_size
199       );
200   // HCI_CommandStatus
201   auto rsp = StaticByteBuffer(
202        hci_spec::kCommandStatusEventCode,
203       0x04,  // parameter_total_size (4 byte payload)
204       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x01, // status, num_hci_command_packets (1 can be sent)
205       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
206       );
207   // clang-format on
208   EXPECT_CMD_PACKET_OUT(test_device(), req, &rsp);
209 
210   // Send HCI_Reset
211   CommandChannel::TransactionId id;
212   auto complete_cb = [&id](CommandChannel::TransactionId callback_id,
213                            const EventPacket& event) {
214     EXPECT_EQ(callback_id, id);
215     EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
216     EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS,
217               event.params<hci_spec::CommandStatusEventParams>().status);
218     EXPECT_EQ(1,
219               event.view()
220                   .payload<hci_spec::CommandStatusEventParams>()
221                   .num_hci_command_packets);
222     EXPECT_EQ(
223         hci_spec::kReset,
224         le16toh(
225             event.params<hci_spec::CommandStatusEventParams>().command_opcode));
226   };
227 
228   auto reset =
229       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
230           hci_spec::kReset);
231   id = cmd_channel()->SendCommand(
232       std::move(reset), complete_cb, hci_spec::kCommandStatusEventCode);
233   RunUntilIdle();
234 }
235 
236 // Tests:
237 //  - Only one HCI command sent until a status is received.
238 //  - Receiving a status update with a new number of packets available works.
TEST_F(CommandChannelTest,OneSentUntilStatus)239 TEST_F(CommandChannelTest, OneSentUntilStatus) {
240   // Set up expectations
241   // clang-format off
242   // HCI_Reset for the sake of testing
243   auto req1 = StaticByteBuffer(
244       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
245       0x00                                   // parameter_total_size
246       );
247   auto rsp1 = StaticByteBuffer(
248       hci_spec::kCommandCompleteEventCode,
249       0x03,  // parameter_total_size (4 byte payload)
250       0x00,  // num_hci_command_packets (None can be sent)
251       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
252       );
253   auto req2 = StaticByteBuffer(
254       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
255       0x00                                   // parameter_total_size
256       );
257   auto rsp2 = StaticByteBuffer(
258       hci_spec::kCommandCompleteEventCode,
259       0x03,  // parameter_total_size (4 byte payload)
260       0x01,  // num_hci_command_packets (1 can be sent)
261       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_InquiryCancel opcode
262       );
263   auto rsp_commandsavail = StaticByteBuffer(
264        hci_spec::kCommandStatusEventCode,
265       0x04,  // parameter_total_size (3 byte payload)
266       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x01, // status, num_hci_command_packets (1 can be sent)
267       0x00, 0x00 // No associated opcode.
268       );
269   // clang-format on
270   EXPECT_CMD_PACKET_OUT(test_device(), req1, &rsp1);
271   EXPECT_CMD_PACKET_OUT(test_device(), req2, &rsp2);
272 
273   size_t cb_event_count = 0u;
274   size_t transaction_count = 0u;
275 
276   test_device()->SetTransactionCallback(
277       [&transaction_count]() { transaction_count++; });
278 
279   auto cb = [&cb_event_count](CommandChannel::TransactionId,
280                               const EventPacket& event) {
281     EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
282     hci_spec::OpCode expected_opcode;
283     if (cb_event_count == 0u) {
284       expected_opcode = hci_spec::kReset;
285     } else {
286       expected_opcode = hci_spec::kInquiryCancel;
287     }
288     EXPECT_EQ(expected_opcode,
289               le16toh(event.params<hci_spec::CommandCompleteEventParams>()
290                           .command_opcode));
291     cb_event_count++;
292   };
293 
294   auto reset =
295       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
296           hci_spec::kReset);
297   [[maybe_unused]] auto reset_id =
298       cmd_channel()->SendCommand(std::move(reset), cb);
299   auto inquiry = CommandPacket::New(hci_spec::kInquiryCancel);
300   [[maybe_unused]] auto inquiry_id =
301       cmd_channel()->SendCommand(std::move(inquiry), cb);
302 
303   RunUntilIdle();
304 
305   EXPECT_EQ(1u, transaction_count);
306   EXPECT_EQ(1u, cb_event_count);
307 
308   test_device()->SendCommandChannelPacket(rsp_commandsavail);
309 
310   RunUntilIdle();
311 
312   EXPECT_EQ(2u, transaction_count);
313   EXPECT_EQ(2u, cb_event_count);
314 }
315 
316 // Tests:
317 //  - Different opcodes can be sent concurrently
318 //  - Same opcodes are queued until a status opcode is sent.
TEST_F(CommandChannelTest,QueuedCommands)319 TEST_F(CommandChannelTest, QueuedCommands) {
320   // Set up expectations
321   // clang-format off
322   // HCI_Reset for the sake of testing
323   auto req_reset = StaticByteBuffer(
324       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
325       0x00                                   // parameter_total_size
326       );
327   auto rsp_reset = StaticByteBuffer(
328       hci_spec::kCommandCompleteEventCode,
329       0x03,  // parameter_total_size (4 byte payload)
330       0xFF,  // num_hci_command_packets (255 can be sent)
331       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
332       );
333   auto req_inqcancel = StaticByteBuffer(
334       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
335       0x00                                   // parameter_total_size
336       );
337   auto rsp_inqcancel = StaticByteBuffer(
338       hci_spec::kCommandCompleteEventCode,
339       0x03,  // parameter_total_size (4 byte payload)
340       0xFF,  // num_hci_command_packets (255 can be sent)
341       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_Reset opcode
342       );
343   auto rsp_commandsavail = StaticByteBuffer(
344        hci_spec::kCommandStatusEventCode,
345       0x04,  // parameter_total_size (3 byte payload)
346       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA, // status, num_hci_command_packets (250 can be sent)
347       0x00, 0x00 // No associated opcode.
348       );
349   // clang-format on
350 
351   // We handle our own responses to make sure commands are queued.
352   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
353   EXPECT_CMD_PACKET_OUT(test_device(), req_inqcancel, );
354   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_reset);
355 
356   size_t transaction_count = 0u;
357   size_t reset_count = 0u;
358   size_t cancel_count = 0u;
359 
360   test_device()->SetTransactionCallback(
361       [&transaction_count]() { transaction_count++; });
362 
363   auto cb = [&reset_count, &cancel_count](CommandChannel::TransactionId id,
364                                           const EventPacket& event) {
365     EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
366     auto opcode = le16toh(
367         event.params<hci_spec::CommandCompleteEventParams>().command_opcode);
368     if (opcode == hci_spec::kReset) {
369       reset_count++;
370     } else if (opcode == hci_spec::kInquiryCancel) {
371       cancel_count++;
372     } else {
373       EXPECT_TRUE(false) << "Unexpected opcode in command callback!";
374     }
375   };
376 
377   // CommandChannel only one can be sent - update num_hci_command_packets
378   test_device()->SendCommandChannelPacket(rsp_commandsavail);
379 
380   auto reset =
381       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
382           hci_spec::kReset);
383   cmd_channel()->SendCommand(std::move(reset), cb);
384   auto inquiry_cancel = hci::EmbossCommandPacket::New<
385       pw::bluetooth::emboss::InquiryCancelCommandWriter>(
386       hci_spec::kInquiryCancel);
387   cmd_channel()->SendCommand(std::move(inquiry_cancel), cb);
388   reset =
389       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
390           hci_spec::kReset);
391   cmd_channel()->SendCommand(std::move(reset), cb);
392 
393   RunUntilIdle();
394 
395   // Different opcodes can be sent without a reply
396   EXPECT_EQ(2u, transaction_count);
397 
398   // Even if we get a response to one, the duplicate opcode is still queued.
399   test_device()->SendCommandChannelPacket(rsp_inqcancel);
400   RunUntilIdle();
401 
402   EXPECT_EQ(2u, transaction_count);
403   EXPECT_EQ(1u, cancel_count);
404   EXPECT_EQ(0u, reset_count);
405 
406   // Once we get a reset back, the second can be sent (and replied to)
407   test_device()->SendCommandChannelPacket(rsp_reset);
408   RunUntilIdle();
409 
410   EXPECT_EQ(3u, transaction_count);
411   EXPECT_EQ(1u, cancel_count);
412   EXPECT_EQ(2u, reset_count);
413 }
414 
415 // Tests:
416 //  - Asynchronous commands are handled correctly (two callbacks, one for
417 //    status, one for complete)
418 //  - Asynchronous commands with the same event result are queued even if they
419 //    have different opcodes.
420 //  - Can't register an event handler when an asynchronous command is waiting.
TEST_F(CommandChannelTest,AsynchronousCommands)421 TEST_F(CommandChannelTest, AsynchronousCommands) {
422   constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
423   // Set up expectations
424   // clang-format off
425   // Using HCI_Reset for testing.
426   auto req_reset = StaticByteBuffer(
427       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
428       0x00                                   // parameter_total_size
429       );
430   auto rsp_resetstatus = StaticByteBuffer(
431        hci_spec::kCommandStatusEventCode,
432       0x04,  // parameter_total_size (4 byte payload)
433       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA, // status, num_hci_command_packets (250 can be sent)
434       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
435       );
436   auto req_inqcancel = StaticByteBuffer(
437       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel),  // HCI_InquiryCancel opcode
438       0x00                                   // parameter_total_size
439       );
440   auto rsp_inqstatus = StaticByteBuffer(
441        hci_spec::kCommandStatusEventCode,
442       0x04,  // parameter_total_size (4 byte payload)
443       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA, // status, num_hci_command_packets (250 can be sent)
444       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel)  // HCI_Reset opcode
445       );
446   auto rsp_bogocomplete = StaticByteBuffer(
447       kTestEventCode0,
448       0x00 // parameter_total_size (no payload)
449       );
450   // clang-format on
451 
452   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
453   EXPECT_CMD_PACKET_OUT(test_device(), req_inqcancel, &rsp_inqstatus);
454 
455   CommandChannel::TransactionId id1, id2;
456   size_t cb_count = 0u;
457 
458   auto cb = [&id1, &id2, &cb_count, kTestEventCode0](
459                 CommandChannel::TransactionId callback_id,
460                 const EventPacket& event) {
461     if (cb_count < 2) {
462       EXPECT_EQ(id1, callback_id);
463     } else {
464       EXPECT_EQ(id2, callback_id);
465     }
466     if ((cb_count % 2) == 0) {
467       EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
468       auto params = event.params<hci_spec::CommandStatusEventParams>();
469       EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
470     } else if ((cb_count % 2) == 1) {
471       EXPECT_EQ(kTestEventCode0, event.event_code());
472     }
473     cb_count++;
474   };
475 
476   hci::EmbossCommandPacket packet =
477       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
478           hci_spec::kReset);
479   id1 = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);
480 
481   RunUntilIdle();
482 
483   // Should have received the Status but not the result.
484   EXPECT_EQ(1u, cb_count);
485 
486   // Setting another event up with different opcode will still queue the command
487   // because we don't want to have two commands waiting on an event.
488   packet = hci::EmbossCommandPacket::New<
489       pw::bluetooth::emboss::InquiryCancelCommandWriter>(
490       hci_spec::kInquiryCancel);
491   id2 = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);
492   RunUntilIdle();
493 
494   EXPECT_EQ(1u, cb_count);
495 
496   // Sending the complete will release the queue and send the next command.
497   test_device()->SendCommandChannelPacket(rsp_bogocomplete);
498   RunUntilIdle();
499 
500   EXPECT_EQ(3u, cb_count);
501 
502   // Should not be able to register an event handler now, we're still waiting on
503   // the asynchronous command.
504   auto event_id0 = cmd_channel()->AddEventHandler(
505       kTestEventCode0,
506       [](const EventPacket&) { return EventCallbackResult::kContinue; });
507   EXPECT_EQ(0u, event_id0);
508 
509   // Finish out the commands.
510   test_device()->SendCommandChannelPacket(rsp_bogocomplete);
511   RunUntilIdle();
512 
513   EXPECT_EQ(4u, cb_count);
514 }
515 
516 // Tests:
517 //  - Updating to say no commands can be sent works. (commands are queued)
518 //  - Can't add an event handler once a SendCommand() succeeds watiing on
519 //    the same event code. (even if they are queued)
TEST_F(CommandChannelTest,AsyncQueueWhenBlocked)520 TEST_F(CommandChannelTest, AsyncQueueWhenBlocked) {
521   constexpr hci_spec::EventCode kTestEventCode0 = 0xF0;
522   // Set up expectations
523   // clang-format off
524   // Using HCI_Reset for testing.
525   auto req_reset = StaticByteBuffer(
526       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
527       0x00                                   // parameter_total_size
528       );
529   auto rsp_resetstatus = StaticByteBuffer(
530        hci_spec::kCommandStatusEventCode,
531       0x04,  // parameter_total_size (4 byte payload)
532       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA, // status, num_hci_command_packets (250 can be sent)
533       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
534       );
535   auto rsp_bogocomplete = StaticByteBuffer(
536       kTestEventCode0,
537       0x00 // parameter_total_size (no payload)
538       );
539   auto rsp_nocommandsavail = StaticByteBuffer(
540        hci_spec::kCommandStatusEventCode,
541       0x04,  // parameter_total_size (3 byte payload)
542       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x00, // status, num_hci_command_packets (none can be sent)
543       0x00, 0x00 // No associated opcode.
544       );
545   auto rsp_commandsavail = StaticByteBuffer(
546        hci_spec::kCommandStatusEventCode,
547       0x04,  // parameter_total_size (3 byte payload)
548       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x01, // status, num_hci_command_packets (one can be sent)
549       0x00, 0x00 // No associated opcode.
550       );
551   // clang-format on
552 
553   size_t transaction_count = 0u;
554 
555   test_device()->SetTransactionCallback(
556       [&transaction_count]() { transaction_count++; });
557 
558   EXPECT_CMD_PACKET_OUT(
559       test_device(), req_reset, &rsp_resetstatus, &rsp_bogocomplete);
560 
561   test_device()->SendCommandChannelPacket(rsp_nocommandsavail);
562 
563   RunUntilIdle();
564 
565   CommandChannel::TransactionId id;
566   size_t cb_count = 0;
567   auto cb = [&cb_count, &id, kTestEventCode0](
568                 CommandChannel::TransactionId callback_id,
569                 const EventPacket& event) {
570     cb_count++;
571     EXPECT_EQ(callback_id, id);
572     if (cb_count == 1) {
573       ASSERT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
574       const auto params = event.params<hci_spec::CommandStatusEventParams>();
575       EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
576       EXPECT_EQ(hci_spec::kReset, params.command_opcode);
577     } else {
578       EXPECT_EQ(kTestEventCode0, event.event_code());
579     }
580   };
581 
582   auto packet =
583       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
584           hci_spec::kReset);
585   id = cmd_channel()->SendCommand(std::move(packet), cb, kTestEventCode0);
586 
587   RunUntilIdle();
588 
589   ASSERT_NE(0u, id);
590   ASSERT_EQ(0u, transaction_count);
591 
592   // This returns invalid because an async command is registered.
593   auto invalid_id = cmd_channel()->AddEventHandler(
594       kTestEventCode0,
595       [](const EventPacket&) { return EventCallbackResult::kContinue; });
596 
597   RunUntilIdle();
598 
599   ASSERT_EQ(0u, invalid_id);
600 
601   // Commands become available and the whole transaction finishes.
602   test_device()->SendCommandChannelPacket(rsp_commandsavail);
603 
604   RunUntilIdle();
605 
606   ASSERT_EQ(1u, transaction_count);
607   ASSERT_EQ(2u, cb_count);
608 }
609 
610 // Tests:
611 //  - Events are routed to the event handler.
612 //  - Can't queue a command on the same event that is already in an event
613 //  handler.
TEST_F(CommandChannelTest,EventHandlerBasic)614 TEST_F(CommandChannelTest, EventHandlerBasic) {
615   constexpr hci_spec::EventCode kTestEventCode0 = 0xFD;
616   constexpr hci_spec::EventCode kTestEventCode1 = 0xFE;
617   StaticByteBuffer cmd_status(
618       hci_spec::kCommandStatusEventCode, 0x04, 0x00, 0x01, 0x00, 0x00);
619   auto cmd_complete = StaticByteBuffer(
620       hci_spec::kCommandCompleteEventCode, 0x03, 0x01, 0x00, 0x00);
621   auto event0 = StaticByteBuffer(kTestEventCode0, 0x00);
622   auto event1 = StaticByteBuffer(kTestEventCode1, 0x00);
623 
624   int event_count0 = 0;
625   auto event_cb0 = [&event_count0, kTestEventCode0](const EventPacket& event) {
626     event_count0++;
627     EXPECT_EQ(kTestEventCode0, event.event_code());
628     return EventCallbackResult::kContinue;
629   };
630 
631   int event_count1 = 0;
632   auto event_cb1 = [&event_count1, kTestEventCode0](const EventPacket& event) {
633     event_count1++;
634     EXPECT_EQ(kTestEventCode0, event.event_code());
635     return EventCallbackResult::kContinue;
636   };
637 
638   int event_count2 = 0;
639   auto event_cb2 = [&event_count2, kTestEventCode1](const EventPacket& event) {
640     event_count2++;
641     EXPECT_EQ(kTestEventCode1, event.event_code());
642     return EventCallbackResult::kContinue;
643   };
644   auto id0 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb0);
645   EXPECT_NE(0u, id0);
646 
647   // Can register a handler for the same event code more than once.
648   auto id1 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb1);
649   EXPECT_NE(0u, id1);
650   EXPECT_NE(id0, id1);
651 
652   // Add a handler for a different event code.
653   auto id2 = cmd_channel()->AddEventHandler(kTestEventCode1, event_cb2);
654   EXPECT_NE(0u, id2);
655 
656   auto reset =
657       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
658           hci_spec::kReset);
659   auto transaction_id = cmd_channel()->SendCommand(
660       std::move(reset), [](auto, const auto&) {}, kTestEventCode0);
661 
662   EXPECT_EQ(0u, transaction_id);
663 
664   test_device()->SendCommandChannelPacket(cmd_status);
665   test_device()->SendCommandChannelPacket(cmd_complete);
666   test_device()->SendCommandChannelPacket(event1);
667   test_device()->SendCommandChannelPacket(event0);
668   test_device()->SendCommandChannelPacket(cmd_complete);
669   test_device()->SendCommandChannelPacket(event0);
670   test_device()->SendCommandChannelPacket(event0);
671   test_device()->SendCommandChannelPacket(cmd_status);
672   test_device()->SendCommandChannelPacket(event1);
673 
674   RunUntilIdle();
675 
676   EXPECT_EQ(3, event_count0);
677   EXPECT_EQ(3, event_count1);
678   EXPECT_EQ(2, event_count2);
679 
680   event_count0 = 0;
681   event_count1 = 0;
682   event_count2 = 0;
683 
684   // Remove the first event handler.
685   cmd_channel()->RemoveEventHandler(id0);
686   test_device()->SendCommandChannelPacket(event0);
687   test_device()->SendCommandChannelPacket(event0);
688   test_device()->SendCommandChannelPacket(event0);
689   test_device()->SendCommandChannelPacket(event1);
690   test_device()->SendCommandChannelPacket(event0);
691   test_device()->SendCommandChannelPacket(event0);
692   test_device()->SendCommandChannelPacket(event0);
693   test_device()->SendCommandChannelPacket(event0);
694   test_device()->SendCommandChannelPacket(event1);
695 
696   RunUntilIdle();
697 
698   EXPECT_EQ(0, event_count0);
699   EXPECT_EQ(7, event_count1);
700   EXPECT_EQ(2, event_count2);
701 
702   event_count0 = 0;
703   event_count1 = 0;
704   event_count2 = 0;
705 
706   // Remove the second event handler.
707   cmd_channel()->RemoveEventHandler(id1);
708   test_device()->SendCommandChannelPacket(event0);
709   test_device()->SendCommandChannelPacket(event0);
710   test_device()->SendCommandChannelPacket(event1);
711   test_device()->SendCommandChannelPacket(event0);
712   test_device()->SendCommandChannelPacket(event1);
713   test_device()->SendCommandChannelPacket(event1);
714 
715   RunUntilIdle();
716 
717   EXPECT_EQ(0, event_count0);
718   EXPECT_EQ(0, event_count1);
719   EXPECT_EQ(3, event_count2);
720 }
721 
722 // Tests:
723 //  - can't send a command that masks an event handler.
724 //  - can send a command without a callback.
TEST_F(CommandChannelTest,EventHandlerEventWhileTransactionPending)725 TEST_F(CommandChannelTest, EventHandlerEventWhileTransactionPending) {
726   // clang-format off
727   // HCI_Reset
728   auto req = StaticByteBuffer(
729       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset),  // HCI_Reset opcode
730       0x00                                   // parameter_total_size
731       );
732 
733   auto req_complete = StaticByteBuffer(
734       hci_spec::kCommandCompleteEventCode,
735       0x03,  // parameter_total_size (3 byte payload)
736       0x01, // num_hci_command_packets (1 can be sent)
737       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
738       );
739   // clang-format on
740 
741   constexpr hci_spec::EventCode kTestEventCode = 0xFE;
742   auto event = StaticByteBuffer(kTestEventCode, 0x01, 0x00);
743 
744   // We will send the HCI_Reset command with kTestEventCode as the completion
745   // event. The event handler we register below should only get invoked once and
746   // after the pending transaction completes.
747   EXPECT_CMD_PACKET_OUT(test_device(), req, &req_complete, &event, &event);
748 
749   int event_count = 0;
750   auto event_cb = [&event_count, kTestEventCode](const EventPacket& event) {
751     event_count++;
752     EXPECT_EQ(kTestEventCode, event.event_code());
753     EXPECT_EQ(1u, event.view().header().parameter_total_size);
754     EXPECT_EQ(1u, event.view().payload_size());
755     return EventCallbackResult::kContinue;
756   };
757 
758   cmd_channel()->AddEventHandler(kTestEventCode, event_cb);
759 
760   auto reset =
761       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
762           hci_spec::kReset);
763   CommandChannel::TransactionId id =
764       cmd_channel()->SendCommand(std::move(reset), nullptr, kTestEventCode);
765   EXPECT_EQ(0u, id);
766 
767   reset =
768       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
769           hci_spec::kReset);
770   id = cmd_channel()->SendCommand(std::move(reset), nullptr);
771   EXPECT_NE(0u, id);
772 
773   RunUntilIdle();
774 
775   EXPECT_EQ(2, event_count);
776 }
777 
778 // Tests:
779 //  - Calling RemoveQueuedCommand on a synchronous command that has already been
780 //  sent to the
781 //    controller returns false.
782 //  - The command still completes and notifies the callback.
TEST_F(CommandChannelTest,RemoveQueuedSyncCommandPendingStatus)783 TEST_F(CommandChannelTest, RemoveQueuedSyncCommandPendingStatus) {
784   auto req_reset =
785       StaticByteBuffer(LowerBits(hci_spec::kReset),
786                        UpperBits(hci_spec::kReset),  // HCI_Reset opcode
787                        0x00                          // parameter_total_size
788       );
789   auto rsp_reset =
790       StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
791                        0x03,  // parameter_total_size (3 byte payload)
792                        0xFF,  // num_hci_command_packets (255 can be sent)
793                        LowerBits(hci_spec::kReset),
794                        UpperBits(hci_spec::kReset)  // HCI_Reset opcode
795       );
796   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
797 
798   int transaction_count = 0u;
799   test_device()->SetTransactionCallback(
800       [&transaction_count]() { transaction_count++; });
801 
802   auto cmd =
803       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
804           hci_spec::kReset);
805   int cmd_cb_count = 0;
806   auto cmd_cb = [&cmd_cb_count](auto, auto&) { cmd_cb_count++; };
807   auto cmd_id = cmd_channel()->SendCommand(std::move(cmd), std::move(cmd_cb));
808   EXPECT_NE(0u, cmd_id);
809 
810   RunUntilIdle();
811 
812   EXPECT_EQ(1, transaction_count);
813   EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));
814   test_device()->SendCommandChannelPacket(rsp_reset);
815 
816   RunUntilIdle();
817 
818   EXPECT_EQ(1, transaction_count);
819   EXPECT_EQ(1, cmd_cb_count);
820 }
821 
822 // Tests:
823 //  - Remove a synchronous command that is queued up behind another command with
824 //  the same opcode.
825 //  - The first command (after removal) does not receive the update event for
826 //  the second command.
TEST_F(CommandChannelTest,RemoveQueuedQueuedSyncCommand)827 TEST_F(CommandChannelTest, RemoveQueuedQueuedSyncCommand) {
828   using namespace std::placeholders;
829   auto req_reset =
830       StaticByteBuffer(LowerBits(hci_spec::kReset),
831                        UpperBits(hci_spec::kReset),  // HCI_Reset opcode
832                        0x00                          // parameter_total_size
833       );
834   auto rsp_reset =
835       StaticByteBuffer(hci_spec::kCommandCompleteEventCode,
836                        0x03,  // parameter_total_size (4 byte payload)
837                        0xFF,  // num_hci_command_packets (255 can be sent)
838                        LowerBits(hci_spec::kReset),
839                        UpperBits(hci_spec::kReset)  // HCI_Reset opcode
840       );
841   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
842 
843   int transaction_count = 0u;
844   test_device()->SetTransactionCallback(
845       [&transaction_count]() { transaction_count++; });
846 
847   auto event_cb = [](CommandChannel::TransactionId id,
848                      const EventPacket& event,
849                      int* event_count) {
850     EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
851     (*event_count)++;
852   };
853 
854   // Send two reset commands so that the second one is queued up.
855   auto reset =
856       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
857           hci_spec::kReset);
858   int event_count0 = 0;
859   auto id0 = cmd_channel()->SendCommand(
860       std::move(reset), std::bind(event_cb, _1, _2, &event_count0));
861   EXPECT_NE(0u, id0);
862   reset =
863       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
864           hci_spec::kReset);
865   int event_count1 = 0;
866   auto id1 = cmd_channel()->SendCommand(
867       std::move(reset), std::bind(event_cb, _1, _2, &event_count1));
868   EXPECT_NE(0u, id1);
869 
870   RunUntilIdle();
871 
872   EXPECT_EQ(1, transaction_count);
873   EXPECT_TRUE(cmd_channel()->RemoveQueuedCommand(id1));
874 
875   RunUntilIdle();
876 
877   EXPECT_EQ(0, event_count0);
878   test_device()->SendCommandChannelPacket(rsp_reset);
879 
880   RunUntilIdle();
881 
882   // Only one command should have been sent.
883   EXPECT_EQ(1, transaction_count);
884   // The queued (then canceled) command should never have gotten an event.
885   EXPECT_EQ(0, event_count1);
886   // The sent command should have gotten one event (CommandComplete).
887   EXPECT_EQ(1, event_count0);
888 }
889 
890 // Read Remote Supported Features
891 const StaticByteBuffer kReadRemoteSupportedFeaturesCmd(
892     LowerBits(hci_spec::kReadRemoteSupportedFeatures),
893     UpperBits(hci_spec::kReadRemoteSupportedFeatures),
894     0x02,  // parameter_total_size
895     0x01,
896     0x00  // connection_handle
897 );
898 
899 // Command Status for Read Remote Supported Features
900 const auto kReadRemoteSupportedFeaturesRsp = StaticByteBuffer(
901     hci_spec::kCommandStatusEventCode,
902     0x04,  // parameter_total_size (4 byte payload)
903     pw::bluetooth::emboss::StatusCode::SUCCESS,  // status
904     0xFF,                                        // num_hci_command_packets
905     LowerBits(hci_spec::kReadRemoteSupportedFeatures),
906     UpperBits(hci_spec::kReadRemoteSupportedFeatures)  // opcode
907 );
908 
909 // Read Remote Supported Features Complete
910 const auto kReadRemoteSupportedFeaturesComplete = StaticByteBuffer(
911     hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode,
912     0x0B,  // parameter_total_size (11 bytes)
913     pw::bluetooth::emboss::StatusCode::SUCCESS,  // status
914     0x01,
915     0x00,  // connection_handle
916     0xFF,
917     0x00,
918     0x00,
919     0x00,
920     0x02,
921     0x00,
922     0x00,
923     0x80  // lmp_features
924           // Set: 3 slot packets, 5 slot packets, Encryption, Timing Accuracy,
925           // Role Switch, Hold Mode, Sniff Mode, LE Supported, Extended Features
926 );
927 
928 // Tests:
929 //  - Remove an asynchronous command that is queued up behind another command
930 //  with the same opcode.
931 //  - The first command (after removal) does not receive the update event for
932 //  the second command.
TEST_F(CommandChannelTest,RemoveQueuedQueuedAsyncCommand)933 TEST_F(CommandChannelTest, RemoveQueuedQueuedAsyncCommand) {
934   using namespace std::placeholders;
935   EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd, );
936 
937   int transaction_count = 0u;
938   test_device()->SetTransactionCallback(
939       [&transaction_count]() { transaction_count++; });
940 
941   auto event_cb = [](CommandChannel::TransactionId id,
942                      const EventPacket& event,
943                      int* event_count) { (*event_count)++; };
944 
945   // Send two read commands so that the second one is queued up.
946   auto packet = MakeReadRemoteSupportedFeatures(0x0001);
947   int event_count0 = 0;
948   auto id0 = cmd_channel()->SendCommand(
949       std::move(packet),
950       std::bind(event_cb, _1, _2, &event_count0),
951       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
952   EXPECT_NE(0u, id0);
953   packet = MakeReadRemoteSupportedFeatures(0x0001);
954   int event_count1 = 0;
955   auto id1 = cmd_channel()->SendCommand(
956       std::move(packet),
957       std::bind(event_cb, _1, _2, &event_count1),
958       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
959   EXPECT_NE(0u, id1);
960 
961   RunUntilIdle();
962 
963   EXPECT_EQ(1, transaction_count);
964   EXPECT_TRUE(cmd_channel()->RemoveQueuedCommand(id1));
965 
966   RunUntilIdle();
967 
968   EXPECT_EQ(0, event_count0);
969   test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesRsp);
970   test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);
971 
972   RunUntilIdle();
973 
974   // Only one command should have been sent.
975   EXPECT_EQ(1, transaction_count);
976   // The queued (then canceled) command should never have gotten an event.
977   EXPECT_EQ(0, event_count1);
978   // The sent command should have gotten two events (Command Status, Read Remote
979   // Supported Features Complete).
980   EXPECT_EQ(2, event_count0);
981 }
982 
983 // Tests:
984 //  - Calling RemoveQueuedCommand on an asynchronous command that has received
985 //  both Command Status
986 //    and command completion events returns false and has no effect.
TEST_F(CommandChannelTest,RemoveQueuedCompletedAsyncCommand)987 TEST_F(CommandChannelTest, RemoveQueuedCompletedAsyncCommand) {
988   EXPECT_CMD_PACKET_OUT(test_device(),
989                         kReadRemoteSupportedFeaturesCmd,
990                         &kReadRemoteSupportedFeaturesRsp,
991                         &kReadRemoteSupportedFeaturesComplete);
992 
993   int transaction_count = 0;
994   test_device()->SetTransactionCallback(
995       [&transaction_count] { transaction_count++; });
996 
997   int event_count = 0;
998   auto event_cb = [&event_count](CommandChannel::TransactionId id,
999                                  const EventPacket& event) { event_count++; };
1000 
1001   auto packet = MakeReadRemoteSupportedFeatures(0x0001);
1002   auto id = cmd_channel()->SendCommand(
1003       std::move(packet),
1004       std::move(event_cb),
1005       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
1006   EXPECT_NE(0u, id);
1007 
1008   RunUntilIdle();
1009 
1010   EXPECT_EQ(2, event_count);
1011   EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(id));
1012 
1013   RunUntilIdle();
1014 
1015   // Only one command should have been sent.
1016   EXPECT_EQ(1, transaction_count);
1017   // The sent command should have received CommandStatus and InquiryComplete.
1018   EXPECT_EQ(2, event_count);
1019 }
1020 
1021 // Tests:
1022 //  - Calling RemoveQueuedCommand on an asynchronous command that has already
1023 //  been sent to the
1024 //    controller returns false.
1025 //  - The command still notifies the callback for update and completion events.
TEST_F(CommandChannelTest,RemoveQueuedAsyncCommandPendingUpdate)1026 TEST_F(CommandChannelTest, RemoveQueuedAsyncCommandPendingUpdate) {
1027   EXPECT_CMD_PACKET_OUT(test_device(), kReadRemoteSupportedFeaturesCmd, );
1028 
1029   int transaction_count = 0;
1030   test_device()->SetTransactionCallback(
1031       [&transaction_count] { transaction_count++; });
1032 
1033   CommandChannel::TransactionId cmd_id;
1034   int cmd_events = 0;
1035   auto cmd_cb = [&cmd_id, &cmd_events](CommandChannel::TransactionId id,
1036                                        const EventPacket& event) {
1037     EXPECT_EQ(cmd_id, id);
1038     if (cmd_events == 0) {
1039       EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1040     }
1041     cmd_events++;
1042   };
1043 
1044   auto cmd_packet = MakeReadRemoteSupportedFeatures(0x0001);
1045   cmd_id = cmd_channel()->SendCommand(
1046       std::move(cmd_packet),
1047       std::move(cmd_cb),
1048       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
1049   EXPECT_NE(0u, cmd_id);
1050 
1051   RunUntilIdle();
1052 
1053   EXPECT_EQ(0, cmd_events);
1054   EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));
1055 
1056   RunUntilIdle();
1057 
1058   test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesRsp);
1059   test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);
1060 
1061   RunUntilIdle();
1062 
1063   EXPECT_EQ(1, transaction_count);
1064   // The command should have gotten update and complete events.
1065   EXPECT_EQ(2, cmd_events);
1066 }
1067 
1068 // Tests:
1069 //  - Calling RemoveQueuedCommand on an asynchronous command that has already
1070 //  been sent to the
1071 //    controller and gotten Command Status returns false.
1072 //  - The command still notifies the callback for completion event.
TEST_F(CommandChannelTest,RemoveQueuedAsyncCommandPendingCompletion)1073 TEST_F(CommandChannelTest, RemoveQueuedAsyncCommandPendingCompletion) {
1074   EXPECT_CMD_PACKET_OUT(test_device(),
1075                         kReadRemoteSupportedFeaturesCmd,
1076                         &kReadRemoteSupportedFeaturesRsp);
1077 
1078   int transaction_count = 0;
1079   test_device()->SetTransactionCallback(
1080       [&transaction_count] { transaction_count++; });
1081 
1082   CommandChannel::TransactionId cmd_id;
1083   int cmd_events = 0;
1084   auto cmd_cb = [&cmd_id, &cmd_events](CommandChannel::TransactionId id,
1085                                        const EventPacket& event) {
1086     EXPECT_EQ(cmd_id, id);
1087     if (cmd_events == 0) {
1088       EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1089     }
1090     cmd_events++;
1091   };
1092 
1093   auto cmd_packet = MakeReadRemoteSupportedFeatures(0x0001);
1094   cmd_id = cmd_channel()->SendCommand(
1095       std::move(cmd_packet),
1096       std::move(cmd_cb),
1097       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
1098   EXPECT_NE(0u, cmd_id);
1099 
1100   RunUntilIdle();
1101 
1102   EXPECT_EQ(1, cmd_events);
1103   EXPECT_FALSE(cmd_channel()->RemoveQueuedCommand(cmd_id));
1104 
1105   RunUntilIdle();
1106 
1107   test_device()->SendCommandChannelPacket(kReadRemoteSupportedFeaturesComplete);
1108 
1109   RunUntilIdle();
1110 
1111   EXPECT_EQ(1, transaction_count);
1112   // The command should have gotten update and complete events.
1113   EXPECT_EQ(2, cmd_events);
1114 }
1115 
TEST_F(CommandChannelTest,VendorEventHandler)1116 TEST_F(CommandChannelTest, VendorEventHandler) {
1117   constexpr hci_spec::EventCode kTestSubeventCode0 = 0x10;
1118   constexpr hci_spec::EventCode kTestSubeventCode1 = 0x12;
1119   StaticByteBuffer vendor_event_bytes0(
1120       hci_spec::kVendorDebugEventCode, 0x01, kTestSubeventCode0);
1121   auto vendor_event_bytes1 = StaticByteBuffer(
1122       hci_spec::kVendorDebugEventCode, 0x01, kTestSubeventCode1);
1123 
1124   int event_count0 = 0;
1125   auto event_cb0 = [&event_count0,
1126                     kTestSubeventCode0](const EmbossEventPacket& event) {
1127     event_count0++;
1128     EXPECT_EQ(hci_spec::kVendorDebugEventCode, event.event_code());
1129     EXPECT_EQ(kTestSubeventCode0,
1130               event.view<pw::bluetooth::emboss::VendorDebugEventView>()
1131                   .subevent_code()
1132                   .Read());
1133     return EventCallbackResult::kContinue;
1134   };
1135 
1136   int event_count1 = 0;
1137   auto event_cb1 = [&event_count1,
1138                     kTestSubeventCode1](const EmbossEventPacket& event) {
1139     event_count1++;
1140     EXPECT_EQ(hci_spec::kVendorDebugEventCode, event.event_code());
1141     EXPECT_EQ(kTestSubeventCode1,
1142               event.view<pw::bluetooth::emboss::VendorDebugEventView>()
1143                   .subevent_code()
1144                   .Read());
1145     return EventCallbackResult::kContinue;
1146   };
1147 
1148   auto id0 =
1149       cmd_channel()->AddVendorEventHandler(kTestSubeventCode0, event_cb0);
1150   EXPECT_NE(0u, id0);
1151 
1152   // Can register a handler for the same event code more than once.
1153   auto id1 =
1154       cmd_channel()->AddVendorEventHandler(kTestSubeventCode0, event_cb0);
1155   EXPECT_NE(0u, id1);
1156   EXPECT_NE(id0, id1);
1157 
1158   // Add a handler for a different event code.
1159   auto id2 =
1160       cmd_channel()->AddVendorEventHandler(kTestSubeventCode1, event_cb1);
1161   EXPECT_NE(0u, id2);
1162 
1163   test_device()->SendCommandChannelPacket(vendor_event_bytes0);
1164   RunUntilIdle();
1165   EXPECT_EQ(2, event_count0);
1166   EXPECT_EQ(0, event_count1);
1167 
1168   test_device()->SendCommandChannelPacket(vendor_event_bytes0);
1169   RunUntilIdle();
1170   EXPECT_EQ(4, event_count0);
1171   EXPECT_EQ(0, event_count1);
1172 
1173   test_device()->SendCommandChannelPacket(vendor_event_bytes1);
1174   RunUntilIdle();
1175   EXPECT_EQ(4, event_count0);
1176   EXPECT_EQ(1, event_count1);
1177 
1178   // Remove the first event handler.
1179   cmd_channel()->RemoveEventHandler(id0);
1180   test_device()->SendCommandChannelPacket(vendor_event_bytes0);
1181   test_device()->SendCommandChannelPacket(vendor_event_bytes1);
1182   RunUntilIdle();
1183   EXPECT_EQ(5, event_count0);
1184   EXPECT_EQ(2, event_count1);
1185 }
1186 
TEST_F(CommandChannelTest,LEMetaEventHandler)1187 TEST_F(CommandChannelTest, LEMetaEventHandler) {
1188   constexpr hci_spec::EventCode kTestSubeventCode0 = 0xFE;
1189   constexpr hci_spec::EventCode kTestSubeventCode1 = 0xFF;
1190   auto le_meta_event_bytes0 =
1191       StaticByteBuffer(hci_spec::kLEMetaEventCode, 0x01, kTestSubeventCode0);
1192   auto le_meta_event_bytes1 =
1193       StaticByteBuffer(hci_spec::kLEMetaEventCode, 0x01, kTestSubeventCode1);
1194 
1195   int event_count0 = 0;
1196   auto event_cb0 = [&event_count0,
1197                     kTestSubeventCode0](const EventPacket& event) {
1198     event_count0++;
1199     EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
1200     EXPECT_EQ(kTestSubeventCode0,
1201               event.params<hci_spec::LEMetaEventParams>().subevent_code);
1202     return EventCallbackResult::kContinue;
1203   };
1204 
1205   int event_count1 = 0;
1206   auto event_cb1 = [&event_count1,
1207                     kTestSubeventCode1](const EventPacket& event) {
1208     event_count1++;
1209     EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
1210     EXPECT_EQ(kTestSubeventCode1,
1211               event.params<hci_spec::LEMetaEventParams>().subevent_code);
1212     return EventCallbackResult::kContinue;
1213   };
1214 
1215   auto id0 =
1216       cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode0, event_cb0);
1217   EXPECT_NE(0u, id0);
1218 
1219   // Can register a handler for the same event code more than once.
1220   auto id1 =
1221       cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode0, event_cb0);
1222   EXPECT_NE(0u, id1);
1223   EXPECT_NE(id0, id1);
1224 
1225   // Add a handler for a different event code.
1226   auto id2 =
1227       cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode1, event_cb1);
1228   EXPECT_NE(0u, id2);
1229 
1230   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
1231   RunUntilIdle();
1232   EXPECT_EQ(2, event_count0);
1233   EXPECT_EQ(0, event_count1);
1234 
1235   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
1236   RunUntilIdle();
1237   EXPECT_EQ(4, event_count0);
1238   EXPECT_EQ(0, event_count1);
1239 
1240   test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
1241   RunUntilIdle();
1242   EXPECT_EQ(4, event_count0);
1243   EXPECT_EQ(1, event_count1);
1244 
1245   // Remove the first event handler.
1246   cmd_channel()->RemoveEventHandler(id0);
1247   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
1248   test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
1249   RunUntilIdle();
1250   EXPECT_EQ(5, event_count0);
1251   EXPECT_EQ(2, event_count1);
1252 }
1253 
TEST_F(CommandChannelTest,EventHandlerIdsDontCollide)1254 TEST_F(CommandChannelTest, EventHandlerIdsDontCollide) {
1255   // Add a LE Meta event handler and a event handler and make sure that IDs are
1256   // generated correctly across the two methods.
1257   EXPECT_EQ(1u,
1258             cmd_channel()->AddLEMetaEventHandler(
1259                 hci_spec::kLEConnectionCompleteSubeventCode,
1260                 [](const EmbossEventPacket&) {
1261                   return EventCallbackResult::kContinue;
1262                 }));
1263   EXPECT_EQ(
1264       2u,
1265       cmd_channel()->AddEventHandler(
1266           hci_spec::kDisconnectionCompleteEventCode,
1267           [](const EventPacket&) { return EventCallbackResult::kContinue; }));
1268 }
1269 
1270 // Tests:
1271 //  - Can't register an event handler for CommandStatus or CommandComplete
TEST_F(CommandChannelTest,EventHandlerRestrictions)1272 TEST_F(CommandChannelTest, EventHandlerRestrictions) {
1273   auto id0 = cmd_channel()->AddEventHandler(
1274       hci_spec::kCommandStatusEventCode,
1275       [](const EventPacket&) { return EventCallbackResult::kContinue; });
1276   EXPECT_EQ(0u, id0);
1277   id0 = cmd_channel()->AddEventHandler(
1278       hci_spec::kCommandCompleteEventCode,
1279       [](const EventPacket&) { return EventCallbackResult::kContinue; });
1280   EXPECT_EQ(0u, id0);
1281 }
1282 
1283 // Tests that an asynchronous command with a completion event code does not
1284 // remove an existing handler for colliding LE meta subevent code.
TEST_F(CommandChannelTest,AsyncEventHandlersAndLeMetaEventHandlersDoNotInterfere)1285 TEST_F(CommandChannelTest,
1286        AsyncEventHandlersAndLeMetaEventHandlersDoNotInterfere) {
1287   // Set up expectations for the asynchronous command and its corresponding
1288   // command status event.
1289   // clang-format off
1290   auto cmd = StaticByteBuffer(
1291       LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry),  // HCI_Inquiry opcode
1292       0x00                                       // parameter_total_size
1293   );
1294   auto cmd_status = StaticByteBuffer(
1295        hci_spec::kCommandStatusEventCode,
1296       0x04,  // parameter_total_size (4 byte payload)
1297       pw::bluetooth::emboss::StatusCode::SUCCESS, 0x01, // status, num_hci_command_packets (1 can be sent)
1298       LowerBits(hci_spec::kInquiry), UpperBits(hci_spec::kInquiry)  // HCI_Inquiry opcode
1299   );
1300   // clang-format on
1301 
1302   EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status);
1303 
1304   constexpr hci_spec::EventCode kTestEventCode = 0x01;
1305 
1306   // Add LE event handler for kTestEventCode
1307   int le_event_count = 0;
1308   auto le_event_cb = [&](const EventPacket& event) {
1309     EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
1310     EXPECT_EQ(kTestEventCode,
1311               event.params<hci_spec::LEMetaEventParams>().subevent_code);
1312     le_event_count++;
1313     return EventCallbackResult::kContinue;
1314   };
1315   cmd_channel()->AddLEMetaEventHandler(
1316       hci_spec::kLEConnectionCompleteSubeventCode, std::move(le_event_cb));
1317 
1318   // Initiate the async transaction with kTestEventCode as its completion code
1319   // (we use hci_spec::kInquiry as a test opcode).
1320   int async_cmd_cb_count = 0;
1321   auto async_cmd_cb = [&](auto id, const EventPacket& event) {
1322     if (async_cmd_cb_count == 0) {
1323       EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1324     } else {
1325       EXPECT_EQ(kTestEventCode, event.event_code());
1326     }
1327     async_cmd_cb_count++;
1328   };
1329 
1330   auto packet =
1331       EmbossCommandPacket::New<pw::bluetooth::emboss::InquiryCommandView>(
1332           hci_spec::kInquiry,
1333           pw::bluetooth::emboss::CommandHeader::IntrinsicSizeInBytes());
1334   cmd_channel()->SendCommand(
1335       std::move(packet), std::move(async_cmd_cb), kTestEventCode);
1336 
1337   // clang-format off
1338   auto event_bytes = StaticByteBuffer(
1339       kTestEventCode,
1340       0x01,  // parameter_total_size
1341       pw::bluetooth::emboss::StatusCode::SUCCESS);
1342   auto le_event_bytes = StaticByteBuffer(
1343       hci_spec::kLEMetaEventCode,
1344       0x01,  // parameter_total_size
1345       kTestEventCode);
1346   // clang-format on
1347 
1348   // Send a spurious LE event before processing the Command Status event. This
1349   // should get routed to the correct event handler.
1350   test_device()->SendCommandChannelPacket(le_event_bytes);
1351 
1352   // Process the async command expectation.
1353   RunUntilIdle();
1354 
1355   // End the asynchronous transaction. This should NOT unregister the LE event
1356   // handler.
1357   test_device()->SendCommandChannelPacket(event_bytes);
1358 
1359   // Send more LE events. These should get routed to the LE event handler.
1360   test_device()->SendCommandChannelPacket(le_event_bytes);
1361   test_device()->SendCommandChannelPacket(le_event_bytes);
1362 
1363   RunUntilIdle();
1364 
1365   // Should have received 3 LE events.
1366   EXPECT_EQ(3, le_event_count);
1367 
1368   // The async command handler should have been called twice: once for Command
1369   // Status and once for the completion event.
1370   EXPECT_EQ(2, async_cmd_cb_count);
1371 }
1372 
TEST_F(CommandChannelTest,TransportClosedCallback)1373 TEST_F(CommandChannelTest, TransportClosedCallback) {
1374   bool error_cb_called = false;
1375   auto error_cb = [&error_cb_called] { error_cb_called = true; };
1376   transport()->SetTransportErrorCallback(error_cb);
1377 
1378   (void)heap_dispatcher().Post(
1379       [this](pw::async::Context /*ctx*/, pw::Status status) {
1380         if (status.ok()) {
1381           test_device()->Stop();
1382         }
1383       });
1384   RunUntilIdle();
1385   EXPECT_TRUE(error_cb_called);
1386 }
1387 
TEST_F(CommandChannelTest,CommandTimeoutCallback)1388 TEST_F(CommandChannelTest, CommandTimeoutCallback) {
1389   auto req_reset =
1390       StaticByteBuffer(LowerBits(hci_spec::kReset),
1391                        UpperBits(hci_spec::kReset),  // HCI_Reset opcode
1392                        0x00                          // parameter_total_size
1393       );
1394 
1395   // Expect the HCI_Reset command but dont send a reply back to make the command
1396   // time out.
1397   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
1398 
1399   size_t timeout_cb_count = 0;
1400   auto timeout_cb = [&] { timeout_cb_count++; };
1401   cmd_channel()->set_channel_timeout_cb(timeout_cb);
1402 
1403   size_t cmd_cb_count = 0;
1404   auto cb = [&](auto, auto&) { cmd_cb_count++; };
1405 
1406   auto packet =
1407       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1408           hci_spec::kReset);
1409   CommandChannel::TransactionId id1 =
1410       cmd_channel()->SendCommand(std::move(packet), cb);
1411   ASSERT_NE(0u, id1);
1412 
1413   packet =
1414       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1415           hci_spec::kReset);
1416   CommandChannel::TransactionId id2 =
1417       cmd_channel()->SendCommand(std::move(packet), cb);
1418   ASSERT_NE(0u, id2);
1419 
1420   // Run the loop until the command timeout task gets scheduled.
1421   RunUntilIdle();
1422   EXPECT_EQ(0u, timeout_cb_count);
1423   EXPECT_EQ(0u, cmd_cb_count);
1424 
1425   RunFor(kCommandTimeout);
1426 
1427   EXPECT_EQ(1u, timeout_cb_count);
1428   EXPECT_EQ(0u, cmd_cb_count);
1429 
1430   DeleteTransport();
1431   EXPECT_EQ(0u, cmd_cb_count);
1432 }
1433 
TEST_F(CommandChannelTest,DestroyChannelInTimeoutCallback)1434 TEST_F(CommandChannelTest, DestroyChannelInTimeoutCallback) {
1435   auto req_reset =
1436       StaticByteBuffer(LowerBits(hci_spec::kReset),
1437                        UpperBits(hci_spec::kReset),  // HCI_Reset opcode
1438                        0x00                          // parameter_total_size
1439       );
1440 
1441   // Expect the HCI_Reset command but dont send a reply back to make the command
1442   // time out.
1443   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, );
1444 
1445   size_t timeout_cb_count = 0;
1446   auto timeout_cb = [&] {
1447     timeout_cb_count++;
1448     DeleteTransport();
1449   };
1450   cmd_channel()->set_channel_timeout_cb(timeout_cb);
1451 
1452   size_t cmd_cb_count = 0;
1453   auto cb = [&](auto, auto&) { cmd_cb_count++; };
1454 
1455   auto packet =
1456       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1457           hci_spec::kReset);
1458   CommandChannel::TransactionId id1 =
1459       cmd_channel()->SendCommand(std::move(packet), cb);
1460   ASSERT_NE(0u, id1);
1461 
1462   packet =
1463       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1464           hci_spec::kReset);
1465   CommandChannel::TransactionId id2 =
1466       cmd_channel()->SendCommand(std::move(packet), cb);
1467   ASSERT_NE(0u, id2);
1468 
1469   RunFor(kCommandTimeout);
1470   EXPECT_EQ(1u, timeout_cb_count);
1471 }
1472 
TEST_F(CommandChannelTest,CommandsAndEventsIgnoredAfterCommandTimeout)1473 TEST_F(CommandChannelTest, CommandsAndEventsIgnoredAfterCommandTimeout) {
1474   size_t timeout_cb_count = 0;
1475   auto timeout_cb = [&] { timeout_cb_count++; };
1476   cmd_channel()->set_channel_timeout_cb(timeout_cb);
1477 
1478   size_t cmd_cb_count = 0;
1479   auto cb = [&](auto, auto&) { cmd_cb_count++; };
1480 
1481   // Expect the HCI_Reset command but dont send a reply back to make the command
1482   // time out.
1483   auto req_reset =
1484       StaticByteBuffer(LowerBits(hci_spec::kReset),
1485                        UpperBits(hci_spec::kReset),  // HCI_Reset opcode
1486                        0x00                          // parameter_total_size
1487       );
1488   EXPECT_CMD_PACKET_OUT(test_device(), req_reset);
1489   auto packet =
1490       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1491           hci_spec::kReset);
1492   CommandChannel::TransactionId id1 =
1493       cmd_channel()->SendCommand(std::move(packet), cb);
1494   ASSERT_NE(0u, id1);
1495 
1496   // Run the loop until the command timeout task gets scheduled.
1497   RunUntilIdle();
1498   EXPECT_EQ(0u, timeout_cb_count);
1499   RunFor(kCommandTimeout);
1500   EXPECT_EQ(1u, timeout_cb_count);
1501   EXPECT_EQ(0u, cmd_cb_count);
1502 
1503   // Additional commands should be ignored.
1504   packet =
1505       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1506           hci_spec::kReset);
1507   CommandChannel::TransactionId id2 =
1508       cmd_channel()->SendCommand(std::move(packet), cb);
1509   EXPECT_EQ(0u, id2);
1510   // No command should be sent.
1511   RunUntilIdle();
1512 
1513   // Events should be ignored.
1514   test_device()->SendCommandChannelPacket(bt::testing::CommandCompletePacket(
1515       hci_spec::kReset, pw::bluetooth::emboss::StatusCode::SUCCESS));
1516   RunUntilIdle();
1517   EXPECT_EQ(0u, cmd_cb_count);
1518 }
1519 
1520 // Tests:
1521 //  - Asynchronous commands should be able to schedule another asynchronous
1522 //    command in their callback.
TEST_F(CommandChannelTest,AsynchronousCommandChaining)1523 TEST_F(CommandChannelTest, AsynchronousCommandChaining) {
1524   constexpr size_t kExpectedCallbacksPerCommand = 2;
1525   constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
1526   // Set up expectations
1527   // clang-format off
1528   // Using HCI_Reset for testing.
1529   auto req_reset = StaticByteBuffer(
1530       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset), // HCI_Reset opcode
1531       0x00                                  // parameter_total_size (no payload)
1532       );
1533   auto rsp_resetstatus = StaticByteBuffer(
1534        hci_spec::kCommandStatusEventCode,
1535       0x04,                        // parameter_total_size (4 byte payload)
1536       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA,  // status, num_hci_command_packets (250)
1537       LowerBits(hci_spec::kReset), UpperBits(hci_spec::kReset)  // HCI_Reset opcode
1538   );
1539   auto req_inqcancel = StaticByteBuffer(
1540       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel), // HCI_InquiryCancel
1541       0x00                        // parameter_total_size (no payload)
1542   );
1543   auto rsp_inqstatus = StaticByteBuffer(
1544        hci_spec::kCommandStatusEventCode,
1545       0x04,                        // parameter_total_size (4 byte payload)
1546       pw::bluetooth::emboss::StatusCode::SUCCESS, 0xFA,  // status, num_hci_command_packets (250)
1547       LowerBits(hci_spec::kInquiryCancel), UpperBits(hci_spec::kInquiryCancel) // HCI_InquiryCanacel
1548   );
1549   auto rsp_bogocomplete = StaticByteBuffer(
1550       kTestEventCode0,
1551       0x00 // parameter_total_size (no payload)
1552       );
1553   // clang-format on
1554 
1555   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
1556   EXPECT_CMD_PACKET_OUT(test_device(), req_reset, &rsp_resetstatus);
1557 
1558   CommandChannel::TransactionId id1, id2;
1559   CommandChannel::CommandCallback cb;
1560   size_t cb_count = 0u;
1561 
1562   cb = [&cb,
1563         cmd_channel = cmd_channel(),
1564         &id1,
1565         &id2,
1566         &cb_count,
1567         kTestEventCode0](CommandChannel::TransactionId callback_id,
1568                          const EventPacket& event) {
1569     if (cb_count < kExpectedCallbacksPerCommand) {
1570       EXPECT_EQ(id1, callback_id);
1571     } else {
1572       EXPECT_EQ(id2, callback_id);
1573     }
1574     if ((cb_count % 2) == 0) {
1575       // First event from each command - CommandStatus
1576       EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1577       auto params = event.params<hci_spec::CommandStatusEventParams>();
1578       EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
1579     } else {
1580       // Second event from each command - completion event
1581       EXPECT_EQ(kTestEventCode0, event.event_code());
1582       if (cb_count < 2) {
1583         // Add the second command when the first one completes.
1584         auto packet = hci::EmbossCommandPacket::New<
1585             pw::bluetooth::emboss::ResetCommandWriter>(hci_spec::kReset);
1586         id2 = cmd_channel->SendCommand(
1587             std::move(packet), cb.share(), kTestEventCode0);
1588       }
1589     }
1590     cb_count++;
1591   };
1592 
1593   auto packet =
1594       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1595           hci_spec::kReset);
1596   id1 = cmd_channel()->SendCommand(
1597       std::move(packet), cb.share(), kTestEventCode0);
1598 
1599   RunUntilIdle();
1600 
1601   // Should have received the Status but not the result.
1602   EXPECT_EQ(1u, cb_count);
1603 
1604   // Sending the complete will finish the command and add the next command.
1605   test_device()->SendCommandChannelPacket(rsp_bogocomplete);
1606   RunUntilIdle();
1607 
1608   EXPECT_EQ(3u, cb_count);
1609 
1610   // Finish out the command.
1611   test_device()->SendCommandChannelPacket(rsp_bogocomplete);
1612   RunUntilIdle();
1613 
1614   EXPECT_EQ(4u, cb_count);
1615 }
1616 
1617 // Tests:
1618 //  - Commands that are exclusive of other commands cannot run together, and
1619 //    instead wait until the exclusive commands finish.
1620 //  - Exclusive Commands in the queue still get started in order
1621 //  - Commands that aren't exclusive run as normal even when an exclusive one is
1622 //    waiting.
TEST_F(CommandChannelTest,ExclusiveCommands)1623 TEST_F(CommandChannelTest, ExclusiveCommands) {
1624   constexpr hci_spec::EventCode kExclOneCompleteEvent = 0xFE;
1625   constexpr hci_spec::EventCode kExclTwoCompleteEvent = 0xFD;
1626   constexpr hci_spec::OpCode kExclusiveOne = hci_spec::DefineOpCode(0x01, 0x01);
1627   constexpr hci_spec::OpCode kExclusiveTwo = hci_spec::DefineOpCode(0x01, 0x02);
1628   constexpr hci_spec::OpCode kNonExclusive = hci_spec::DefineOpCode(0x01, 0x03);
1629 
1630   // Set up expectations
1631   //  - kExclusiveOne can't run at the same time as kExclusiveTwo, and
1632   //  vice-versa.
1633   //  - kExclusiveOne finishes with kExclOneCompleteEvent
1634   //  - kExclusiveTwo finishes with kExclTwoCompleteEvent
1635   //  - kNonExclusive can run whenever it wants.
1636   //  - For testing, we omit the payloads of all commands.
1637   auto excl_one_cmd = StaticByteBuffer(
1638       LowerBits(kExclusiveOne), UpperBits(kExclusiveOne), 0x00  // (no payload)
1639   );
1640   auto rsp_excl_one_status =
1641       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
1642                        0x04,  // parameter_total_size (4 byte payload)
1643                        pw::bluetooth::emboss::StatusCode::SUCCESS,
1644                        0xFA,  // status, num_hci_command_packets (250)
1645                        LowerBits(kExclusiveOne),
1646                        UpperBits(kExclusiveOne)  // HCI opcode
1647       );
1648   auto rsp_one_complete = StaticByteBuffer(
1649       kExclOneCompleteEvent, 0x00  // parameter_total_size (no payload)
1650   );
1651 
1652   auto excl_two_cmd = StaticByteBuffer(
1653       LowerBits(kExclusiveTwo), UpperBits(kExclusiveTwo), 0x00  // (no payload)
1654   );
1655   auto rsp_excl_two_status =
1656       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
1657                        0x04,  // parameter_total_size (4 byte payload)
1658                        pw::bluetooth::emboss::StatusCode::SUCCESS,
1659                        0xFA,  // status, num_hci_command_packets (250)
1660                        LowerBits(kExclusiveTwo),
1661                        UpperBits(kExclusiveTwo)  // HCI opcode
1662       );
1663   auto rsp_two_complete = StaticByteBuffer(
1664       kExclTwoCompleteEvent, 0x00  // parameter_total_size (no payload)
1665   );
1666 
1667   auto nonexclusive_cmd =
1668       StaticByteBuffer(LowerBits(kNonExclusive),
1669                        UpperBits(kNonExclusive),  // HCI opcode
1670                        0x00  // parameter_total_size (no payload)
1671       );
1672   auto nonexclusive_complete = StaticByteBuffer(
1673       hci_spec::kCommandCompleteEventCode,
1674       0x04,  // parameter_total_size (4 byte payload)
1675       0xFA,  // num_hci_command_packets (250)
1676       LowerBits(kNonExclusive),
1677       UpperBits(kNonExclusive),                   // HCI opcode
1678       pw::bluetooth::emboss::StatusCode::SUCCESS  // Command succeeded
1679   );
1680 
1681   CommandChannel::TransactionId id1, id2, id3;
1682   CommandChannel::CommandCallback exclusive_cb;
1683   size_t exclusive_cb_count = 0u;
1684 
1685   size_t nonexclusive_cb_count = 0;
1686   CommandChannel::CommandCallback nonexclusive_cb =
1687       [&nonexclusive_cb_count](auto callback_id, const EventPacket& event) {
1688         EXPECT_EQ(hci_spec::kCommandCompleteEventCode, event.event_code());
1689         nonexclusive_cb_count++;
1690       };
1691 
1692   exclusive_cb = [&exclusive_cb,
1693                   &nonexclusive_cb,
1694                   cmd_channel = cmd_channel(),
1695                   &id1,
1696                   &id2,
1697                   &id3,
1698                   &exclusive_cb_count,
1699                   kExclOneCompleteEvent,
1700                   kExclTwoCompleteEvent](
1701                      CommandChannel::TransactionId callback_id,
1702                      const EventPacket& event) {
1703     // Expected event -> Action in response
1704     // 0. Status for kExclusiveOne -> Send a kExclusiveTwo
1705     // 1. Complete for kExclusiveOne -> Send Another kExclusiveOne and
1706     // kNonExclusive
1707     // 2. Status for kExclusiveTwo -> Nothing
1708     // 3. Complete for kExclusiveTwo -> Nothing
1709     // 4. Status for kExclusiveOne -> Nothing
1710     // 5. Complete for kExclusiveOne -> Nothing
1711     switch (exclusive_cb_count) {
1712       case 0: {
1713         // Status for kExclusiveOne -> Send kExclusiveTwo (queued)
1714         EXPECT_EQ(id1, callback_id);
1715         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1716         auto params = event.params<hci_spec::CommandStatusEventParams>();
1717         EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
1718         auto packet = CommandPacket::New(kExclusiveTwo);
1719         id2 = cmd_channel->SendExclusiveCommand(std::move(packet),
1720                                                 exclusive_cb.share(),
1721                                                 kExclTwoCompleteEvent,
1722                                                 {kExclusiveOne});
1723         std::cout << "queued Exclusive Two: " << id2 << std::endl;
1724         break;
1725       }
1726       case 1: {
1727         // Complete for kExclusiveOne -> Resend kExclusiveOne
1728         EXPECT_EQ(id1, callback_id);
1729         EXPECT_EQ(kExclOneCompleteEvent, event.event_code());
1730         // Add the second command when the first one completes.
1731         auto packet = CommandPacket::New(kExclusiveOne);
1732         id3 = cmd_channel->SendExclusiveCommand(std::move(packet),
1733                                                 exclusive_cb.share(),
1734                                                 kExclOneCompleteEvent,
1735                                                 {kExclusiveTwo});
1736         std::cout << "queued Second Exclusive One: " << id3 << std::endl;
1737         packet = CommandPacket::New(kNonExclusive);
1738         cmd_channel->SendCommand(std::move(packet), nonexclusive_cb.share());
1739 
1740         break;
1741       }
1742       case 2: {  // Status for kExclusiveTwo
1743         EXPECT_EQ(id2, callback_id);
1744         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1745         auto params = event.params<hci_spec::CommandStatusEventParams>();
1746         EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
1747         break;
1748       }
1749       case 3: {  // Complete for kExclusiveTwo
1750         EXPECT_EQ(id2, callback_id);
1751         EXPECT_EQ(kExclTwoCompleteEvent, event.event_code());
1752         break;
1753       }
1754       case 4: {  // Status for Second kExclusiveOne
1755         EXPECT_EQ(id3, callback_id);
1756         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1757         auto params = event.params<hci_spec::CommandStatusEventParams>();
1758         EXPECT_EQ(pw::bluetooth::emboss::StatusCode::SUCCESS, params.status);
1759         break;
1760       }
1761       case 5: {  // Complete for Second kExclusiveOne
1762         EXPECT_EQ(id3, callback_id);
1763         EXPECT_EQ(kExclOneCompleteEvent, event.event_code());
1764         break;
1765       }
1766       default: {
1767         ASSERT_TRUE(false);  // Should never be called more than 6 times.
1768         break;
1769       }
1770     }
1771     exclusive_cb_count++;
1772   };
1773 
1774   EXPECT_CMD_PACKET_OUT(test_device(), excl_one_cmd, &rsp_excl_one_status);
1775   EXPECT_CMD_PACKET_OUT(
1776       test_device(), nonexclusive_cmd, &nonexclusive_complete);
1777   id1 = cmd_channel()->SendExclusiveCommand(CommandPacket::New(kExclusiveOne),
1778                                             exclusive_cb.share(),
1779                                             kExclOneCompleteEvent,
1780                                             {kExclusiveTwo});
1781   cmd_channel()->SendCommand(CommandPacket::New(kNonExclusive),
1782                              nonexclusive_cb.share());
1783   RunUntilIdle();
1784   // Should have received the ExclusiveOne status but not the complete.
1785   // ExclusiveTwo should be queued.
1786   EXPECT_EQ(1u, exclusive_cb_count);
1787   // NonExclusive should be completed.
1788   EXPECT_EQ(1u, nonexclusive_cb_count);
1789 
1790   // Sending the ExclusiveOne complete will send the ExclusiveTwo command, queue
1791   // another ExclusiveOne command, and send a NonExclusive command.
1792   EXPECT_CMD_PACKET_OUT(test_device(), excl_two_cmd, &rsp_excl_two_status);
1793   EXPECT_CMD_PACKET_OUT(
1794       test_device(), nonexclusive_cmd, &nonexclusive_complete);
1795   test_device()->SendCommandChannelPacket(rsp_one_complete);
1796   RunUntilIdle();
1797   EXPECT_EQ(3u,
1798             exclusive_cb_count);  // +2: rsp_one_complete, rsp_excl_two_status
1799   EXPECT_EQ(2u, nonexclusive_cb_count);  // +1: nonexclusive_complete
1800 
1801   // Complete ExclusiveTwo and send a NonExclusive. The queued ExclusiveOne
1802   // should be sent.
1803   EXPECT_CMD_PACKET_OUT(
1804       test_device(), nonexclusive_cmd, &nonexclusive_complete);
1805   EXPECT_CMD_PACKET_OUT(test_device(), excl_one_cmd, &rsp_excl_one_status);
1806   test_device()->SendCommandChannelPacket(rsp_two_complete);
1807   cmd_channel()->SendCommand(CommandPacket::New(kNonExclusive),
1808                              nonexclusive_cb.share());
1809   RunUntilIdle();
1810   EXPECT_EQ(5u,
1811             exclusive_cb_count);  // +2: rsp_two_complete, rsp_excl_one_status
1812   EXPECT_EQ(3u, nonexclusive_cb_count);  // +1: nonexclusive_complete
1813 
1814   // Finish the second ExclusiveOne
1815   test_device()->SendCommandChannelPacket(rsp_one_complete);
1816   RunUntilIdle();
1817   EXPECT_EQ(6u, exclusive_cb_count);  // +1: rsp_one_complete
1818   EXPECT_EQ(3u, nonexclusive_cb_count);
1819 }
1820 
TEST_F(CommandChannelTest,SendCommandFailsIfEventHandlerInstalled)1821 TEST_F(CommandChannelTest, SendCommandFailsIfEventHandlerInstalled) {
1822   constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
1823 
1824   // Register event handler for kTestEventCode0.
1825   auto id0 = cmd_channel()->AddEventHandler(
1826       kTestEventCode0,
1827       [](const EventPacket& event) { return EventCallbackResult::kContinue; });
1828   EXPECT_NE(0u, id0);
1829 
1830   // Try to send a command for kTestEventCode0. SendCommand should fail for a
1831   // code already registered with "AddEventHandler".
1832   auto reset =
1833       hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
1834           hci_spec::kReset);
1835   auto transaction_id = cmd_channel()->SendCommand(
1836       std::move(reset), [](auto, const auto&) {}, kTestEventCode0);
1837   EXPECT_EQ(0u, transaction_id);
1838 }
1839 
TEST_F(CommandChannelTest,EventHandlerResults)1840 TEST_F(CommandChannelTest, EventHandlerResults) {
1841   constexpr hci_spec::EventCode kTestEventCode0 = 0xFE;
1842 
1843   int event_count = 0;
1844   auto event_cb = [&event_count, kTestEventCode0](const EventPacket& event) {
1845     event_count++;
1846     EXPECT_EQ(kTestEventCode0, event.event_code());
1847 
1848     if (event_count == 1) {
1849       return EventCallbackResult::kContinue;
1850     }
1851 
1852     return EventCallbackResult::kRemove;
1853   };
1854 
1855   EXPECT_NE(cmd_channel()->AddEventHandler(kTestEventCode0, event_cb), 0u);
1856 
1857   // Send three requests, and process the callbacks immediately. The second
1858   // callback returns "remove" before the third event callback has been called.
1859   auto event0 = StaticByteBuffer(kTestEventCode0, 0x00);
1860   test_device()->SendCommandChannelPacket(event0);
1861   test_device()->SendCommandChannelPacket(event0);
1862   test_device()->SendCommandChannelPacket(event0);
1863   RunUntilIdle();
1864   EXPECT_EQ(2, event_count);
1865 }
1866 
TEST_F(CommandChannelTest,SendCommandWithLEMetaEventSubeventRsp)1867 TEST_F(CommandChannelTest, SendCommandWithLEMetaEventSubeventRsp) {
1868   constexpr hci_spec::OpCode kOpCode = hci_spec::kLEReadRemoteFeatures;
1869   constexpr hci_spec::EventCode kSubeventCode =
1870       hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;
1871 
1872   auto cmd = StaticByteBuffer(LowerBits(kOpCode),
1873                               UpperBits(kOpCode),
1874                               // parameter total size (0 byte payload)
1875                               0x00);
1876 
1877   auto cmd_status_event =
1878       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
1879                        // parameter total size (4 byte payload)
1880                        0x04,
1881                        // status, num_hci_command_packets (250)
1882                        pw::bluetooth::emboss::StatusCode::SUCCESS,
1883                        0xFA,
1884                        // HCI opcode
1885                        LowerBits(kOpCode),
1886                        UpperBits(kOpCode));
1887   auto cmd_complete_subevent =
1888       StaticByteBuffer(hci_spec::kLEMetaEventCode,
1889                        0x01,  // parameter total size (1 byte payload)
1890                        kSubeventCode);
1891 
1892   EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status_event);
1893 
1894   auto cmd_packet = CommandPacket::New(kOpCode);
1895 
1896   size_t event_count = 0;
1897   auto event_cb = [&event_count](auto, const EventPacket& event) {
1898     switch (event_count) {
1899       case 0: {
1900         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
1901         break;
1902       }
1903       case 1: {
1904         EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
1905         break;
1906       }
1907       default: {
1908         FAIL();
1909       }
1910     }
1911     event_count++;
1912   };
1913   auto id = cmd_channel()->SendLeAsyncCommand(
1914       std::move(cmd_packet), std::move(event_cb), kSubeventCode);
1915   EXPECT_NE(0u, id);
1916 
1917   RunUntilIdle();
1918   EXPECT_EQ(1u, event_count);
1919 
1920   // Handler should be removed when subevent received.
1921   test_device()->SendCommandChannelPacket(cmd_complete_subevent);
1922   RunUntilIdle();
1923   EXPECT_EQ(2u, event_count);
1924 
1925   // This seconod complete event should be ignored because the handler should
1926   // have been removed.
1927   test_device()->SendCommandChannelPacket(cmd_complete_subevent);
1928   RunUntilIdle();
1929   EXPECT_EQ(2u, event_count);
1930 }
1931 
TEST_F(CommandChannelTest,SendingLECommandAfterAddingLEMetaEventHandlerFailsForSameSubeventCodeAndSucceedsForDifferentSubeventCode)1932 TEST_F(
1933     CommandChannelTest,
1934     SendingLECommandAfterAddingLEMetaEventHandlerFailsForSameSubeventCodeAndSucceedsForDifferentSubeventCode) {
1935   constexpr hci_spec::EventCode kSubeventCode =
1936       hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;
1937   constexpr hci_spec::OpCode kOpCode =
1938       hci_spec::kLEReadRemoteFeatures;  // LE Read Remote Features
1939 
1940   EXPECT_NE(0u,
1941             cmd_channel()->AddLEMetaEventHandler(
1942                 kSubeventCode, [](const EmbossEventPacket&) {
1943                   return EventCallbackResult::kContinue;
1944                 }));
1945   EXPECT_EQ(0u,
1946             cmd_channel()->SendLeAsyncCommand(
1947                 CommandPacket::New(kOpCode),
1948                 [](auto, const auto&) {},
1949                 kSubeventCode));
1950 
1951   auto cmd = StaticByteBuffer(LowerBits(kOpCode),
1952                               UpperBits(kOpCode),
1953                               // parameter total size (0 byte payload)
1954                               0x00);
1955   EXPECT_CMD_PACKET_OUT(test_device(), std::move(cmd), );
1956   EXPECT_NE(0u,
1957             cmd_channel()->SendLeAsyncCommand(
1958                 CommandPacket::New(kOpCode),
1959                 [](auto, const auto&) {},
1960                 kSubeventCode + 1));
1961   RunUntilIdle();
1962 }
1963 
TEST_F(CommandChannelTest,SendingSecondLECommandWithSameSubeventShouldWaitForFirstToComplete)1964 TEST_F(CommandChannelTest,
1965        SendingSecondLECommandWithSameSubeventShouldWaitForFirstToComplete) {
1966   // Commands have different op codes but same subevent code so that second
1967   // command is not blocked because of matching op codes (which would not test
1968   // LE command handling).
1969   constexpr hci_spec::OpCode kOpCode0 = hci_spec::kLEReadRemoteFeatures;
1970   constexpr hci_spec::OpCode kOpCode1 = hci_spec::kLEReadBufferSizeV1;
1971   constexpr hci_spec::EventCode kSubeventCode =
1972       hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;
1973 
1974   auto cmd0 = StaticByteBuffer(LowerBits(kOpCode0),
1975                                UpperBits(kOpCode0),
1976                                // parameter total size (0 byte payload)
1977                                0x00);
1978   auto cmd0_status_event =
1979       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
1980                        // parameter total size (4 byte payload)
1981                        0x04,
1982                        // status, num_hci_command_packets (250)
1983                        pw::bluetooth::emboss::StatusCode::SUCCESS,
1984                        0xFA,
1985                        // HCI opcode
1986                        LowerBits(kOpCode0),
1987                        UpperBits(kOpCode0));
1988   auto cmd1 = StaticByteBuffer(LowerBits(kOpCode1),
1989                                UpperBits(kOpCode1),
1990                                // parameter total size (0 byte payload)
1991                                0x00);
1992   auto cmd1_status_event =
1993       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
1994                        // parameter total size (4 byte payload)
1995                        0x04,
1996                        // status, num_hci_command_packets (250)
1997                        pw::bluetooth::emboss::StatusCode::SUCCESS,
1998                        0xFA,
1999                        // HCI opcode
2000                        LowerBits(kOpCode1),
2001                        UpperBits(kOpCode1));
2002 
2003   auto cmd_complete_subevent =
2004       StaticByteBuffer(hci_spec::kLEMetaEventCode,
2005                        0x01,  // parameter total size (1 byte payload)
2006                        kSubeventCode);
2007 
2008   EXPECT_CMD_PACKET_OUT(test_device(), cmd0, &cmd0_status_event);
2009 
2010   size_t event_count_0 = 0;
2011   auto event_cb_0 = [&event_count_0](auto, const EventPacket& event) {
2012     switch (event_count_0) {
2013       case 0: {
2014         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
2015         break;
2016       }
2017       case 1: {
2018         EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
2019         break;
2020       }
2021       default: {
2022         FAIL();
2023       }
2024     }
2025     event_count_0++;
2026   };
2027   auto id_0 = cmd_channel()->SendLeAsyncCommand(
2028       CommandPacket::New(kOpCode0), std::move(event_cb_0), kSubeventCode);
2029   EXPECT_NE(0u, id_0);
2030 
2031   RunUntilIdle();
2032   EXPECT_EQ(1u, event_count_0);
2033 
2034   size_t event_count_1 = 0;
2035   auto event_cb_1 = [&event_count_1](auto, const EventPacket& event) {
2036     switch (event_count_1) {
2037       case 0: {
2038         EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
2039         break;
2040       }
2041       case 1: {
2042         EXPECT_EQ(hci_spec::kLEMetaEventCode, event.event_code());
2043         break;
2044       }
2045       default: {
2046         FAIL();
2047       }
2048     }
2049     event_count_1++;
2050   };
2051   // Command should be queued and not sent until after first complete event
2052   // received.
2053   auto id_1 = cmd_channel()->SendLeAsyncCommand(
2054       CommandPacket::New(kOpCode1), std::move(event_cb_1), kSubeventCode);
2055   EXPECT_NE(0u, id_1);
2056   RunUntilIdle();
2057   EXPECT_EQ(0u, event_count_1);
2058 
2059   // When first command complete event is received, second command should be
2060   // sent.
2061   EXPECT_CMD_PACKET_OUT(test_device(), cmd1, &cmd1_status_event);
2062   test_device()->SendCommandChannelPacket(cmd_complete_subevent);
2063   RunUntilIdle();
2064   EXPECT_EQ(2u, event_count_0);
2065   EXPECT_EQ(1u, event_count_1);
2066 
2067   // Second complete event should be received by second command event handler
2068   // only.
2069   test_device()->SendCommandChannelPacket(cmd_complete_subevent);
2070   RunUntilIdle();
2071   EXPECT_EQ(2u, event_count_0);
2072   EXPECT_EQ(2u, event_count_1);
2073 }
2074 
TEST_F(CommandChannelTest,RegisteringLEMetaEventHandlerWhileLECommandPendingFailsForSameSubeventAndSucceedsForDifferentSubevent)2075 TEST_F(
2076     CommandChannelTest,
2077     RegisteringLEMetaEventHandlerWhileLECommandPendingFailsForSameSubeventAndSucceedsForDifferentSubevent) {
2078   constexpr hci_spec::OpCode kOpCode = hci_spec::kLEReadRemoteFeatures;
2079   constexpr hci_spec::EventCode kSubeventCode =
2080       hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode;
2081 
2082   auto cmd = StaticByteBuffer(LowerBits(kOpCode),
2083                               UpperBits(kOpCode),
2084                               // parameter total size (0 byte payload)
2085                               0x00);
2086 
2087   auto cmd_status_event =
2088       StaticByteBuffer(hci_spec::kCommandStatusEventCode,
2089                        // parameter total size (4 byte payload)
2090                        0x04,
2091                        // status, num_hci_command_packets (250)
2092                        pw::bluetooth::emboss::StatusCode::SUCCESS,
2093                        0xFA,
2094                        // HCI opcode
2095                        LowerBits(kOpCode),
2096                        UpperBits(kOpCode));
2097 
2098   EXPECT_CMD_PACKET_OUT(test_device(), cmd, &cmd_status_event);
2099 
2100   size_t event_count = 0;
2101   auto event_cb = [&event_count](auto, const EventPacket& event) {
2102     EXPECT_EQ(hci_spec::kCommandStatusEventCode, event.event_code());
2103     event_count++;
2104   };
2105   auto id = cmd_channel()->SendLeAsyncCommand(
2106       CommandPacket::New(kOpCode), std::move(event_cb), kSubeventCode);
2107   EXPECT_NE(0u, id);
2108   RunUntilIdle();
2109   EXPECT_EQ(1u, event_count);
2110 
2111   // Async LE command for subevent is already pending, so registering event
2112   // handler should fail by returning 0.
2113   id = cmd_channel()->AddLEMetaEventHandler(
2114       kSubeventCode,
2115       [](const EmbossEventPacket&) { return EventCallbackResult::kContinue; });
2116   EXPECT_EQ(0u, id);
2117 
2118   // Registering event handler for different subevent code should succeed.
2119   id = cmd_channel()->AddLEMetaEventHandler(
2120       kSubeventCode + 1,
2121       [](const EmbossEventPacket&) { return EventCallbackResult::kContinue; });
2122   EXPECT_NE(0u, id);
2123 }
2124 
2125 #ifndef NINSPECT
TEST_F(CommandChannelTest,InspectHierarchy)2126 TEST_F(CommandChannelTest, InspectHierarchy) {
2127   cmd_channel()->AttachInspect(inspector_.GetRoot(), "command_channel");
2128 
2129   auto command_channel_matcher = AllOf(NodeMatches(AllOf(
2130       NameMatches("command_channel"),
2131       PropertyList(UnorderedElementsAre(UintIs("allowed_command_packets", 1),
2132                                         UintIs("next_event_handler_id", 1),
2133                                         UintIs("next_transaction_id", 1))))));
2134 
2135   EXPECT_THAT(inspect::ReadFromVmo(inspector_.DuplicateVmo()).value(),
2136               ChildrenMatch(ElementsAre(command_channel_matcher)));
2137 }
2138 #endif  // NINSPECT
2139 
2140 }  // namespace
2141 }  // namespace bt::hci
2142