• 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/testing/fake_controller.h"
16 
17 #include <pw_assert/check.h>
18 #include <pw_bytes/endian.h>
19 
20 #include <cstddef>
21 #include <cstdint>
22 
23 #include "pw_bluetooth/hci_android.emb.h"
24 #include "pw_bluetooth/hci_data.emb.h"
25 #include "pw_bluetooth/hci_events.emb.h"
26 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
27 #include "pw_bluetooth_sapphire/internal/host/common/packet_view.h"
28 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
29 #include "pw_bluetooth_sapphire/internal/host/hci-spec/defaults.h"
30 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
31 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
32 #include "pw_bluetooth_sapphire/internal/host/hci-spec/vendor_protocol.h"
33 
34 namespace bt::testing {
35 namespace {
36 
37 template <typename NUM_TYPE, typename ENUM_TYPE>
SetBit(NUM_TYPE * num_type,ENUM_TYPE bit)38 void SetBit(NUM_TYPE* num_type, ENUM_TYPE bit) {
39   *num_type |= static_cast<NUM_TYPE>(bit);
40 }
41 
42 template <typename NUM_TYPE, typename ENUM_TYPE>
UnsetBit(NUM_TYPE * num_type,ENUM_TYPE bit)43 void UnsetBit(NUM_TYPE* num_type, ENUM_TYPE bit) {
44   *num_type &= ~static_cast<NUM_TYPE>(bit);
45 }
46 
47 template <typename NUM_TYPE, typename ENUM_TYPE>
CheckBit(NUM_TYPE num_type,ENUM_TYPE bit)48 bool CheckBit(NUM_TYPE num_type, ENUM_TYPE bit) {
49   return (num_type & static_cast<NUM_TYPE>(bit));
50 }
51 
52 }  // namespace
53 
54 namespace android_hci = hci_spec::vendor::android;
55 namespace android_emb = pw::bluetooth::vendor::android_hci;
56 namespace pwemb = pw::bluetooth::emboss;
57 
ApplyDualModeDefaults()58 void FakeController::Settings::ApplyDualModeDefaults() {
59   le_connection_delay = std::chrono::seconds(0);
60   hci_version = pwemb::CoreSpecificationVersion::V5_0;
61   num_hci_command_packets = 250;
62   event_mask = 0;
63   le_event_mask = 0;
64   bd_addr = DeviceAddress();
65   lmp_features_page0 = 0;
66   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kLESupportedHost);
67   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kSimultaneousLEAndBREDR);
68   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kExtendedFeatures);
69   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kRSSIwithInquiryResults);
70   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kExtendedInquiryResponse);
71   SetBit(&lmp_features_page0,
72          hci_spec::LMPFeature::kSecureSimplePairingControllerSupport);
73   lmp_features_page1 = 0;
74   SetBit(&lmp_features_page1,
75          hci_spec::LMPFeature::kSecureSimplePairingHostSupport);
76   lmp_features_page2 = 0;
77   le_features = 0;
78   le_supported_states = 0;
79   std::memset(supported_commands, 0, sizeof(supported_commands));
80   AddBREDRSupportedCommands();
81   AddLESupportedCommands();
82   acl_data_packet_length = 512;
83   total_num_acl_data_packets = 1;
84   le_acl_data_packet_length = 512;
85   le_total_num_acl_data_packets = 1;
86   // Must be 0x01-0xFF, even if not supported
87   synchronous_data_packet_length = 1;
88   total_num_synchronous_data_packets = 0;
89   iso_data_packet_length = 512;
90   total_num_iso_data_packets = 1;
91   android_extension_settings.SetToZeros();
92 }
93 
ApplyLEOnlyDefaults()94 void FakeController::Settings::ApplyLEOnlyDefaults() {
95   ApplyDualModeDefaults();
96 
97   UnsetBit(&lmp_features_page0, hci_spec::LMPFeature::kSimultaneousLEAndBREDR);
98   SetBit(&lmp_features_page0, hci_spec::LMPFeature::kBREDRNotSupported);
99   std::memset(supported_commands, 0, sizeof(supported_commands));
100 
101   AddLESupportedCommands();
102 }
103 
AddBREDRSupportedCommands()104 void FakeController::Settings::AddBREDRSupportedCommands() {
105   auto view = SupportedCommandsView();
106   view.create_connection().Write(true);
107   view.create_connection_cancel().Write(true);
108   view.disconnect().Write(true);
109   view.write_local_name().Write(true);
110   view.read_local_name().Write(true);
111   view.read_scan_enable().Write(true);
112   view.write_scan_enable().Write(true);
113   view.read_page_scan_activity().Write(true);
114   view.write_page_scan_activity().Write(true);
115   view.write_class_of_device().Write(true);
116   view.write_synchronous_flow_control_enable().Write(true);
117   view.read_inquiry_mode().Write(true);
118   view.write_inquiry_mode().Write(true);
119   view.read_page_scan_type().Write(true);
120   view.write_page_scan_type().Write(true);
121   view.read_buffer_size().Write(true);
122   view.read_simple_pairing_mode().Write(true);
123   view.write_simple_pairing_mode().Write(true);
124   view.write_extended_inquiry_response().Write(true);
125   view.write_secure_connections_host_support().Write(true);
126 }
127 
AddLESupportedCommands()128 void FakeController::Settings::AddLESupportedCommands() {
129   auto view = SupportedCommandsView();
130   view.disconnect().Write(true);
131   view.set_event_mask().Write(true);
132   view.reset().Write(true);
133   view.read_local_version_information().Write(true);
134   view.read_local_supported_features().Write(true);
135   view.read_local_extended_features().Write(true);
136   view.write_le_host_support().Write(true);
137   view.le_set_event_mask().Write(true);
138   view.le_read_buffer_size_v1().Write(true);
139   view.le_read_local_supported_features().Write(true);
140   view.le_set_random_address().Write(true);
141   view.le_set_advertising_parameters().Write(true);
142   view.le_set_advertising_data().Write(true);
143   view.le_set_scan_response_data().Write(true);
144   view.le_set_advertising_enable().Write(true);
145   view.le_create_connection().Write(true);
146   view.le_create_connection_cancel().Write(true);
147   view.le_connection_update().Write(true);
148   view.le_read_remote_features().Write(true);
149   view.le_start_encryption().Write(true);
150   view.le_read_buffer_size_v2().Write(true);
151   view.read_local_supported_controller_delay().Write(true);
152 }
153 
ApplyLegacyLEConfig()154 void FakeController::Settings::ApplyLegacyLEConfig() {
155   ApplyLEOnlyDefaults();
156 
157   hci_version = pwemb::CoreSpecificationVersion::V4_2;
158 
159   auto view = pwemb::MakeSupportedCommandsView(supported_commands,
160                                                sizeof(supported_commands));
161   view.le_set_scan_parameters().Write(true);
162   view.le_set_scan_enable().Write(true);
163 }
164 
ApplyExtendedLEConfig()165 void FakeController::Settings::ApplyExtendedLEConfig() {
166   ApplyLEOnlyDefaults();
167 
168   SetBit(&le_features, hci_spec::LESupportedFeature::kLEExtendedAdvertising);
169 
170   auto view = SupportedCommandsView();
171   view.le_set_advertising_set_random_address().Write(true);
172   view.le_set_extended_advertising_parameters().Write(true);
173   view.le_set_extended_advertising_data().Write(true);
174   view.le_set_extended_scan_response_data().Write(true);
175   view.le_set_extended_advertising_enable().Write(true);
176   view.le_read_maximum_advertising_data_length().Write(true);
177   view.le_read_number_of_supported_advertising_sets().Write(true);
178   view.le_remove_advertising_set().Write(true);
179   view.le_clear_advertising_sets().Write(true);
180 }
181 
ApplyAndroidVendorExtensionDefaults()182 void FakeController::Settings::ApplyAndroidVendorExtensionDefaults() {
183   // Settings for the android vendor extensions component within the Fake
184   // Controller. These settings correspond to the vendor capabilities returned
185   // by the controller. See hci_vendor.emb LEGetVendorCapabilities for more
186   // information.
187   auto view = android_extension_settings.view();
188   view.status().Write(pwemb::StatusCode::SUCCESS);
189   view.max_advt_instances().Write(3);
190   view.version_supported().major_number().Write(0);
191   view.version_supported().minor_number().Write(55);
192 }
193 
is_event_unmasked(hci_spec::LEEventMask event) const194 bool FakeController::Settings::is_event_unmasked(
195     hci_spec::LEEventMask event) const {
196   return le_event_mask | static_cast<uint64_t>(event);
197 }
198 
SetDefaultCommandStatus(hci_spec::OpCode opcode,pwemb::StatusCode status)199 void FakeController::SetDefaultCommandStatus(hci_spec::OpCode opcode,
200                                              pwemb::StatusCode status) {
201   default_command_status_map_[opcode] = status;
202 }
203 
ClearDefaultCommandStatus(hci_spec::OpCode opcode)204 void FakeController::ClearDefaultCommandStatus(hci_spec::OpCode opcode) {
205   default_command_status_map_.erase(opcode);
206 }
207 
SetDefaultResponseStatus(hci_spec::OpCode opcode,pwemb::StatusCode status)208 void FakeController::SetDefaultResponseStatus(hci_spec::OpCode opcode,
209                                               pwemb::StatusCode status) {
210   PW_DCHECK(status != pwemb::StatusCode::SUCCESS);
211   default_status_map_[opcode] = status;
212 }
213 
ClearDefaultResponseStatus(hci_spec::OpCode opcode)214 void FakeController::ClearDefaultResponseStatus(hci_spec::OpCode opcode) {
215   default_status_map_.erase(opcode);
216 }
217 
AddPeer(std::unique_ptr<FakePeer> peer)218 bool FakeController::AddPeer(std::unique_ptr<FakePeer> peer) {
219   PW_DCHECK(peer);
220 
221   if (peers_.count(peer->address()) != 0u) {
222     return false;
223   }
224 
225   peer->set_controller(this);
226 
227   // If a scan is enabled then send an advertising report for the peer that just
228   // got registered if it supports advertising.
229   if (peer->send_advertising_report()) {
230     SendAdvertisingReport(*peer);
231     SendScanResponseReport(*peer);
232   }
233 
234   peers_[peer->address()] = std::move(peer);
235   return true;
236 }
237 
RemovePeer(const DeviceAddress & address)238 void FakeController::RemovePeer(const DeviceAddress& address) {
239   peers_.erase(address);
240 }
241 
FindPeer(const DeviceAddress & address)242 FakePeer* FakeController::FindPeer(const DeviceAddress& address) {
243   auto iter = peers_.find(address);
244   return (iter == peers_.end()) ? nullptr : iter->second.get();
245 }
246 
SendCommand(pw::span<const std::byte> command)247 void FakeController::SendCommand(pw::span<const std::byte> command) {
248   PW_CHECK(command.size() >= sizeof(hci_spec::CommandHeader));
249 
250   // Post the packet to simulate async HCI behavior.
251   (void)heap_dispatcher().Post(
252       [self = GetWeakPtr(), command = DynamicByteBuffer(BufferView(command))](
253           pw::async::Context /*ctx*/, pw::Status status) {
254         if (!self.is_alive() || !status.ok()) {
255           return;
256         }
257         const size_t payload_size =
258             command.size() - sizeof(hci_spec::CommandHeader);
259         PacketView<hci_spec::CommandHeader> packet_view(&command, payload_size);
260         self->OnCommandPacketReceived(packet_view);
261       });
262 }
263 
FindByConnHandle(hci_spec::ConnectionHandle handle)264 FakePeer* FakeController::FindByConnHandle(hci_spec::ConnectionHandle handle) {
265   for (auto& [addr, peer] : peers_) {
266     if (peer->HasLink(handle)) {
267       return peer.get();
268     }
269   }
270   return nullptr;
271 }
272 
NextL2CAPCommandId()273 uint8_t FakeController::NextL2CAPCommandId() {
274   // TODO(armansito): Guard against overflow?
275   return next_le_sig_id_++;
276 }
277 
RespondWithCommandComplete(pwemb::OpCode opcode,pwemb::StatusCode status)278 void FakeController::RespondWithCommandComplete(pwemb::OpCode opcode,
279                                                 pwemb::StatusCode status) {
280   auto packet = hci::EventPacket::New<pwemb::SimpleCommandCompleteEventWriter>(
281       hci_spec::kCommandCompleteEventCode);
282   auto view = packet.view_t();
283   view.status().Write(status);
284   RespondWithCommandComplete(opcode, &packet);
285 }
286 
RespondWithCommandComplete(pwemb::OpCode opcode,hci::EventPacket * packet)287 void FakeController::RespondWithCommandComplete(pwemb::OpCode opcode,
288                                                 hci::EventPacket* packet) {
289   auto header = packet->template view<pwemb::CommandCompleteEventWriter>();
290 
291   header.num_hci_command_packets().Write(settings_.num_hci_command_packets);
292   header.command_opcode().Write(opcode);
293 
294   SendEvent(hci_spec::kCommandCompleteEventCode, packet);
295 }
296 
RespondWithCommandStatus(pwemb::OpCode opcode,pwemb::StatusCode status)297 void FakeController::RespondWithCommandStatus(pwemb::OpCode opcode,
298                                               pwemb::StatusCode status) {
299   auto packet = hci::EventPacket::New<pwemb::CommandStatusEventWriter>(
300       hci_spec::kCommandStatusEventCode);
301   auto view = packet.view_t();
302   view.status().Write(status);
303   view.num_hci_command_packets().Write(settings_.num_hci_command_packets);
304   view.command_opcode_enum().Write(opcode);
305 
306   SendEvent(hci_spec::kCommandStatusEventCode, &packet);
307 }
308 
SendEvent(hci_spec::EventCode event_code,hci::EventPacket * packet)309 void FakeController::SendEvent(hci_spec::EventCode event_code,
310                                hci::EventPacket* packet) {
311   auto header = packet->template view<pwemb::EventHeaderWriter>();
312   uint8_t parameter_total_size = static_cast<uint8_t>(
313       packet->size() - pwemb::EventHeader::IntrinsicSizeInBytes());
314 
315   header.event_code_uint().Write(event_code);
316   header.parameter_total_size().Write(parameter_total_size);
317 
318   SendCommandChannelPacket(packet->data());
319 }
320 
SendACLPacket(hci_spec::ConnectionHandle handle,const ByteBuffer & payload)321 void FakeController::SendACLPacket(hci_spec::ConnectionHandle handle,
322                                    const ByteBuffer& payload) {
323   PW_DCHECK(payload.size() <= hci_spec::kMaxACLPayloadSize);
324 
325   DynamicByteBuffer buffer(sizeof(hci_spec::ACLDataHeader) + payload.size());
326   MutablePacketView<hci_spec::ACLDataHeader> acl(&buffer, payload.size());
327 
328   acl.mutable_header()->handle_and_flags =
329       pw::bytes::ConvertOrderTo(cpp20::endian::little, handle);
330   acl.mutable_header()->data_total_length = pw::bytes::ConvertOrderTo(
331       cpp20::endian::little, static_cast<uint16_t>(payload.size()));
332   acl.mutable_payload_data().Write(payload);
333 
334   SendACLDataChannelPacket(buffer);
335 }
336 
SendL2CAPBFrame(hci_spec::ConnectionHandle handle,l2cap::ChannelId channel_id,const ByteBuffer & payload)337 void FakeController::SendL2CAPBFrame(hci_spec::ConnectionHandle handle,
338                                      l2cap::ChannelId channel_id,
339                                      const ByteBuffer& payload) {
340   PW_DCHECK(payload.size() <=
341             hci_spec::kMaxACLPayloadSize - sizeof(l2cap::BasicHeader));
342 
343   DynamicByteBuffer buffer(sizeof(l2cap::BasicHeader) + payload.size());
344   MutablePacketView<l2cap::BasicHeader> bframe(&buffer, payload.size());
345 
346   bframe.mutable_header()->length = pw::bytes::ConvertOrderTo(
347       cpp20::endian::little, static_cast<uint16_t>(payload.size()));
348   bframe.mutable_header()->channel_id =
349       pw::bytes::ConvertOrderTo(cpp20::endian::little, channel_id);
350   bframe.mutable_payload_data().Write(payload);
351 
352   SendACLPacket(handle, buffer);
353 }
354 
SendL2CAPCFrame(hci_spec::ConnectionHandle handle,bool is_le,l2cap::CommandCode code,uint8_t id,const ByteBuffer & payload)355 void FakeController::SendL2CAPCFrame(hci_spec::ConnectionHandle handle,
356                                      bool is_le,
357                                      l2cap::CommandCode code,
358                                      uint8_t id,
359                                      const ByteBuffer& payload) {
360   DynamicByteBuffer buffer(sizeof(l2cap::CommandHeader) + payload.size());
361   MutablePacketView<l2cap::CommandHeader> cframe(&buffer, payload.size());
362 
363   cframe.mutable_header()->code = code;
364   cframe.mutable_header()->id = id;
365   cframe.mutable_header()->length = static_cast<uint16_t>(payload.size());
366   cframe.mutable_payload_data().Write(payload);
367 
368   SendL2CAPBFrame(
369       handle,
370       is_le ? l2cap::kLESignalingChannelId : l2cap::kSignalingChannelId,
371       buffer);
372 }
373 
SendNumberOfCompletedPacketsEvent(hci_spec::ConnectionHandle handle,uint16_t num)374 void FakeController::SendNumberOfCompletedPacketsEvent(
375     hci_spec::ConnectionHandle handle, uint16_t num) {
376   constexpr size_t buffer_size =
377       pwemb::NumberOfCompletedPacketsEvent::MinSizeInBytes() +
378       pwemb::NumberOfCompletedPacketsEventData::IntrinsicSizeInBytes();
379   auto event =
380       hci::EventPacket::New<pwemb::NumberOfCompletedPacketsEventWriter>(
381           hci_spec::kNumberOfCompletedPacketsEventCode, buffer_size);
382   auto view = event.view_t();
383 
384   view.num_handles().Write(1);
385   view.nocp_data()[0].connection_handle().Write(handle);
386   view.nocp_data()[0].num_completed_packets().Write(num);
387 
388   SendEvent(hci_spec::kNumberOfCompletedPacketsEventCode, &event);
389 }
390 
ConnectLowEnergy(const DeviceAddress & addr,pwemb::ConnectionRole role)391 void FakeController::ConnectLowEnergy(const DeviceAddress& addr,
392                                       pwemb::ConnectionRole role) {
393   (void)heap_dispatcher().Post(
394       [addr, role, this](pw::async::Context /*ctx*/, pw::Status status) {
395         if (!status.ok()) {
396           return;
397         }
398         FakePeer* peer = FindPeer(addr);
399         if (!peer) {
400           bt_log(WARN,
401                  "fake-hci",
402                  "no peer found with address: %s",
403                  addr.ToString().c_str());
404           return;
405         }
406 
407         // TODO(armansito): Don't worry about managing multiple links per peer
408         // until this supports Bluetooth classic.
409         if (peer->connected()) {
410           bt_log(WARN, "fake-hci", "peer already connected");
411           return;
412         }
413 
414         hci_spec::ConnectionHandle handle = ++next_conn_handle_;
415         peer->AddLink(handle);
416 
417         NotifyConnectionState(addr, handle, /*connected=*/true);
418 
419         uint16_t interval_min = hci_spec::defaults::kLEConnectionIntervalMin;
420         uint16_t interval_max = hci_spec::defaults::kLEConnectionIntervalMax;
421         uint16_t interval = interval_min + ((interval_max - interval_min) / 2);
422 
423         hci_spec::LEConnectionParameters conn_params(
424             interval, 0, hci_spec::defaults::kLESupervisionTimeout);
425         peer->set_le_params(conn_params);
426 
427         auto packet = hci::EventPacket::New<
428             pwemb::LEEnhancedConnectionCompleteSubeventV1Writer>(
429             hci_spec::kLEMetaEventCode);
430         auto view = packet.view_t();
431         view.le_meta_event().subevent_code().Write(
432             hci_spec::kLEEnhancedConnectionCompleteSubeventCode);
433         view.status().Write(pwemb::StatusCode::SUCCESS);
434         view.peer_address().CopyFrom(addr.value().view());
435         view.peer_address_type().Write(
436             DeviceAddress::DeviceAddrToLeAddr(addr.type()));
437         view.peripheral_latency().Write(conn_params.latency());
438         view.connection_interval().Write(conn_params.interval());
439         view.supervision_timeout().Write(conn_params.supervision_timeout());
440         view.role().Write(role);
441         view.connection_handle().Write(handle);
442         SendCommandChannelPacket(packet.data());
443       });
444 }
445 
SendConnectionRequest(const DeviceAddress & addr,pwemb::LinkType link_type)446 void FakeController::SendConnectionRequest(const DeviceAddress& addr,
447                                            pwemb::LinkType link_type) {
448   FakePeer* peer = FindPeer(addr);
449   PW_CHECK(peer);
450   peer->set_last_connection_request_link_type(link_type);
451 
452   bt_log(DEBUG,
453          "fake-hci",
454          "sending connection request (addr: %s, link: %s)",
455          bt_str(addr),
456          hci_spec::LinkTypeToString(link_type));
457   auto packet = hci::EventPacket::New<pwemb::ConnectionRequestEventWriter>(
458       hci_spec::kConnectionRequestEventCode);
459   packet.view_t().bd_addr().CopyFrom(addr.value().view());
460   packet.view_t().link_type().Write(link_type);
461   SendCommandChannelPacket(packet.data());
462 }
463 
L2CAPConnectionParameterUpdate(const DeviceAddress & addr,const hci_spec::LEPreferredConnectionParameters & params)464 void FakeController::L2CAPConnectionParameterUpdate(
465     const DeviceAddress& addr,
466     const hci_spec::LEPreferredConnectionParameters& params) {
467   (void)heap_dispatcher().Post([addr, params, this](pw::async::Context /*ctx*/,
468                                                     pw::Status status) {
469     if (!status.ok()) {
470       return;
471     }
472     FakePeer* peer = FindPeer(addr);
473     if (!peer) {
474       bt_log(WARN,
475              "fake-hci",
476              "no peer found with address: %s",
477              addr.ToString().c_str());
478       return;
479     }
480 
481     if (!peer->connected()) {
482       bt_log(WARN, "fake-hci", "peer not connected");
483       return;
484     }
485 
486     PW_DCHECK(!peer->logical_links().empty());
487 
488     l2cap::ConnectionParameterUpdateRequestPayload payload;
489     payload.interval_min =
490         pw::bytes::ConvertOrderTo(cpp20::endian::little, params.min_interval());
491     payload.interval_max =
492         pw::bytes::ConvertOrderTo(cpp20::endian::little, params.max_interval());
493     payload.peripheral_latency =
494         pw::bytes::ConvertOrderTo(cpp20::endian::little, params.max_latency());
495     payload.timeout_multiplier = pw::bytes::ConvertOrderTo(
496         cpp20::endian::little, params.supervision_timeout());
497 
498     // TODO(armansito): Instead of picking the first handle we should pick
499     // the handle that matches the current LE-U link.
500     SendL2CAPCFrame(*peer->logical_links().begin(),
501                     /*is_le=*/true,
502                     l2cap::kConnectionParameterUpdateRequest,
503                     NextL2CAPCommandId(),
504                     BufferView(&payload, sizeof(payload)));
505   });
506 }
507 
SendLEConnectionUpdateCompleteSubevent(hci_spec::ConnectionHandle handle,const hci_spec::LEConnectionParameters & params,pwemb::StatusCode status)508 void FakeController::SendLEConnectionUpdateCompleteSubevent(
509     hci_spec::ConnectionHandle handle,
510     const hci_spec::LEConnectionParameters& params,
511     pwemb::StatusCode status) {
512   auto packet =
513       hci::EventPacket::New<pwemb::LEConnectionUpdateCompleteSubeventWriter>(
514           hci_spec::kLEMetaEventCode);
515   auto view = packet.view_t();
516   view.le_meta_event().subevent_code().Write(
517       hci_spec::kLEConnectionUpdateCompleteSubeventCode);
518   view.status().Write(status);
519   view.connection_handle().Write(handle);
520   view.connection_interval().UncheckedWrite(params.interval());
521   view.peripheral_latency().Write(params.latency());
522   view.supervision_timeout().UncheckedWrite(params.supervision_timeout());
523   SendCommandChannelPacket(packet.data());
524 }
525 
Disconnect(const DeviceAddress & addr,pwemb::StatusCode reason)526 void FakeController::Disconnect(const DeviceAddress& addr,
527                                 pwemb::StatusCode reason) {
528   (void)heap_dispatcher().Post(
529       [this, addr, reason](pw::async::Context /*ctx*/, pw::Status status) {
530         if (!status.ok()) {
531           return;
532         }
533         FakePeer* peer = FindPeer(addr);
534         if (!peer || !peer->connected()) {
535           bt_log(WARN,
536                  "fake-hci",
537                  "no connected peer found with address: %s",
538                  addr.ToString().c_str());
539           return;
540         }
541 
542         auto links = peer->Disconnect();
543         PW_DCHECK(!peer->connected());
544         PW_DCHECK(!links.empty());
545 
546         for (auto link : links) {
547           NotifyConnectionState(addr, link, /*connected=*/false);
548           SendDisconnectionCompleteEvent(link, reason);
549         }
550       });
551 }
552 
SendDisconnectionCompleteEvent(hci_spec::ConnectionHandle handle,pwemb::StatusCode reason)553 void FakeController::SendDisconnectionCompleteEvent(
554     hci_spec::ConnectionHandle handle, pwemb::StatusCode reason) {
555   auto event = hci::EventPacket::New<pwemb::DisconnectionCompleteEventWriter>(
556       hci_spec::kDisconnectionCompleteEventCode);
557   event.view_t().status().Write(pwemb::StatusCode::SUCCESS);
558   event.view_t().connection_handle().Write(handle);
559   event.view_t().reason().Write(reason);
560   SendCommandChannelPacket(event.data());
561 }
562 
SendEncryptionChangeEvent(hci_spec::ConnectionHandle handle,pwemb::StatusCode status,pwemb::EncryptionStatus encryption_enabled)563 void FakeController::SendEncryptionChangeEvent(
564     hci_spec::ConnectionHandle handle,
565     pwemb::StatusCode status,
566     pwemb::EncryptionStatus encryption_enabled) {
567   auto response = hci::EventPacket::New<pwemb::EncryptionChangeEventV1Writer>(
568       hci_spec::kEncryptionChangeEventCode);
569   response.view_t().status().Write(status);
570   response.view_t().connection_handle().Write(handle);
571   response.view_t().encryption_enabled().Write(encryption_enabled);
572   SendCommandChannelPacket(response.data());
573 }
574 
MaybeRespondWithDefaultCommandStatus(hci_spec::OpCode opcode)575 bool FakeController::MaybeRespondWithDefaultCommandStatus(
576     hci_spec::OpCode opcode) {
577   auto iter = default_command_status_map_.find(opcode);
578   if (iter == default_command_status_map_.end()) {
579     return false;
580   }
581 
582   RespondWithCommandStatus(static_cast<pwemb::OpCode>(opcode), iter->second);
583   return true;
584 }
585 
MaybeRespondWithDefaultStatus(hci_spec::OpCode opcode)586 bool FakeController::MaybeRespondWithDefaultStatus(hci_spec::OpCode opcode) {
587   auto iter = default_status_map_.find(opcode);
588   if (iter == default_status_map_.end())
589     return false;
590 
591   bt_log(INFO,
592          "fake-hci",
593          "responding with error (command: %#.4x, status: %#.2hhx)",
594          opcode,
595          static_cast<unsigned char>(iter->second));
596   RespondWithCommandComplete(static_cast<pwemb::OpCode>(opcode), iter->second);
597   return true;
598 }
599 
SendInquiryResponses()600 void FakeController::SendInquiryResponses() {
601   // TODO(jamuraa): combine some of these into a single response event
602   for (const auto& [addr, peer] : peers_) {
603     if (!peer->supports_bredr()) {
604       continue;
605     }
606 
607     SendCommandChannelPacket(peer->CreateInquiryResponseEvent(inquiry_mode_));
608     inquiry_num_responses_left_--;
609     if (inquiry_num_responses_left_ == 0) {
610       break;
611     }
612   }
613 }
614 
SendAdvertisingReports()615 void FakeController::SendAdvertisingReports() {
616   if (!le_scan_state_.enabled || peers_.empty()) {
617     return;
618   }
619 
620   for (const auto& iter : peers_) {
621     if (iter.second->send_advertising_report()) {
622       SendAdvertisingReport(*iter.second);
623       SendScanResponseReport(*iter.second);
624     }
625   }
626 
627   // We'll send new reports for the same peers if duplicate filtering is
628   // disabled.
629   if (!le_scan_state_.filter_duplicates) {
630     (void)heap_dispatcher().Post(
631         [this](pw::async::Context /*ctx*/, pw::Status status) {
632           if (status.ok()) {
633             SendAdvertisingReports();
634           }
635         });
636   }
637 }
638 
SendAdvertisingReport(const FakePeer & peer)639 void FakeController::SendAdvertisingReport(const FakePeer& peer) {
640   if (!le_scan_state_.enabled || !peer.supports_le() ||
641       !peer.advertising_enabled()) {
642     return;
643   }
644 
645   DynamicByteBuffer buffer;
646   if (advertising_procedure() == AdvertisingProcedure::kExtended) {
647     buffer = peer.BuildExtendedAdvertisingReportEvent();
648   } else {
649     buffer = peer.BuildLegacyAdvertisingReportEvent();
650   }
651 
652   SendCommandChannelPacket(buffer);
653 }
654 
SendScanResponseReport(const FakePeer & peer)655 void FakeController::SendScanResponseReport(const FakePeer& peer) {
656   if (!le_scan_state_.enabled || !peer.supports_le() ||
657       !peer.advertising_enabled()) {
658     return;
659   }
660 
661   // We want to send scan response packets only during an active scan and if the
662   // peer is scannable.
663   bool is_active_scan = (le_scan_state_.scan_type == pwemb::LEScanType::ACTIVE);
664   bool need_scan_rsp = (is_active_scan && peer.scannable());
665 
666   if (!need_scan_rsp) {
667     return;
668   }
669 
670   DynamicByteBuffer buffer;
671   if (advertising_procedure() == AdvertisingProcedure::kExtended) {
672     buffer = peer.BuildExtendedScanResponseEvent();
673   } else {
674     buffer = peer.BuildLegacyScanResponseReportEvent();
675   }
676 
677   SendCommandChannelPacket(buffer);
678 }
679 
NotifyControllerParametersChanged()680 void FakeController::NotifyControllerParametersChanged() {
681   if (controller_parameters_cb_) {
682     controller_parameters_cb_();
683   }
684 }
685 
NotifyAdvertisingState()686 void FakeController::NotifyAdvertisingState() {
687   if (advertising_state_cb_) {
688     advertising_state_cb_();
689   }
690 }
691 
NotifyConnectionState(const DeviceAddress & addr,hci_spec::ConnectionHandle handle,bool connected,bool canceled)692 void FakeController::NotifyConnectionState(const DeviceAddress& addr,
693                                            hci_spec::ConnectionHandle handle,
694                                            bool connected,
695                                            bool canceled) {
696   if (conn_state_cb_) {
697     conn_state_cb_(addr, handle, connected, canceled);
698   }
699 }
700 
NotifyLEConnectionParameters(const DeviceAddress & addr,const hci_spec::LEConnectionParameters & params)701 void FakeController::NotifyLEConnectionParameters(
702     const DeviceAddress& addr, const hci_spec::LEConnectionParameters& params) {
703   if (le_conn_params_cb_) {
704     le_conn_params_cb_(addr, params);
705   }
706 }
707 
CaptureLEConnectParams(const pwemb::LECreateConnectionCommandView & params)708 void FakeController::CaptureLEConnectParams(
709     const pwemb::LECreateConnectionCommandView& params) {
710   le_connect_params_ = LEConnectParams();
711 
712   switch (params.initiator_filter_policy().Read()) {
713     case pwemb::GenericEnableParam::ENABLE:
714       le_connect_params_->use_filter_policy = true;
715       break;
716     case pwemb::GenericEnableParam::DISABLE:
717       le_connect_params_->use_filter_policy = false;
718       break;
719   }
720 
721   le_connect_params_->own_address_type = params.own_address_type().Read();
722   le_connect_params_->peer_address = DeviceAddress(
723       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read()),
724       DeviceAddressBytes(params.peer_address()));
725 
726   LEConnectParams::Parameters& connect_params =
727       le_connect_params_
728           ->phy_conn_params[LEConnectParams::InitiatingPHYs::kLE_1M];
729   connect_params.scan_interval = params.le_scan_interval().Read();
730   connect_params.scan_window = params.le_scan_window().Read();
731   connect_params.connection_interval_min =
732       params.connection_interval_min().Read();
733   connect_params.connection_interval_max =
734       params.connection_interval_max().Read();
735   connect_params.max_latency = params.max_latency().Read();
736   connect_params.supervision_timeout = params.supervision_timeout().Read();
737   connect_params.min_ce_length = params.min_connection_event_length().Read();
738   connect_params.max_ce_length = params.max_connection_event_length().Read();
739 }
740 
CaptureLEConnectParamsForPHY(const pwemb::LEExtendedCreateConnectionCommandV1View & params,LEConnectParams::InitiatingPHYs phy)741 void FakeController::CaptureLEConnectParamsForPHY(
742     const pwemb::LEExtendedCreateConnectionCommandV1View& params,
743     LEConnectParams::InitiatingPHYs phy) {
744   int index = static_cast<int>(phy);
745 
746   LEConnectParams::Parameters& connect_params =
747       le_connect_params_->phy_conn_params[phy];
748   connect_params.scan_interval = params.data()[index].scan_interval().Read();
749   connect_params.scan_window = params.data()[index].scan_window().Read();
750   connect_params.connection_interval_min =
751       params.data()[index].connection_interval_min().Read();
752   connect_params.connection_interval_min =
753       params.data()[index].connection_interval_max().Read();
754   connect_params.max_latency = params.data()[index].max_latency().Read();
755   connect_params.supervision_timeout =
756       params.data()[index].supervision_timeout().Read();
757   connect_params.min_ce_length =
758       params.data()[index].min_connection_event_length().Read();
759   connect_params.max_ce_length =
760       params.data()[index].max_connection_event_length().Read();
761 }
762 
CaptureLEConnectParams(const pwemb::LEExtendedCreateConnectionCommandV1View & params)763 void FakeController::CaptureLEConnectParams(
764     const pwemb::LEExtendedCreateConnectionCommandV1View& params) {
765   le_connect_params_ = LEConnectParams();
766 
767   switch (params.initiator_filter_policy().Read()) {
768     case pwemb::GenericEnableParam::ENABLE:
769       le_connect_params_->use_filter_policy = true;
770       break;
771     case pwemb::GenericEnableParam::DISABLE:
772       le_connect_params_->use_filter_policy = false;
773       break;
774   }
775 
776   le_connect_params_->own_address_type = params.own_address_type().Read();
777   le_connect_params_->peer_address = DeviceAddress(
778       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read()),
779       DeviceAddressBytes(params.peer_address()));
780 
781   CaptureLEConnectParamsForPHY(params, LEConnectParams::InitiatingPHYs::kLE_1M);
782   CaptureLEConnectParamsForPHY(params, LEConnectParams::InitiatingPHYs::kLE_2M);
783   CaptureLEConnectParamsForPHY(params,
784                                LEConnectParams::InitiatingPHYs::kLE_Coded);
785 }
786 
OnCreateConnectionCommandReceived(const pwemb::CreateConnectionCommandView & params)787 void FakeController::OnCreateConnectionCommandReceived(
788     const pwemb::CreateConnectionCommandView& params) {
789   acl_create_connection_command_count_++;
790 
791   // Cannot issue this command while a request is already pending.
792   if (bredr_connect_pending_) {
793     RespondWithCommandStatus(pwemb::OpCode::CREATE_CONNECTION,
794                              pwemb::StatusCode::COMMAND_DISALLOWED);
795     return;
796   }
797 
798   const DeviceAddress peer_address(DeviceAddress::Type::kBREDR,
799                                    DeviceAddressBytes(params.bd_addr()));
800   pwemb::StatusCode status = pwemb::StatusCode::SUCCESS;
801 
802   // Find the peer that matches the requested address.
803   FakePeer* peer = FindPeer(peer_address);
804   if (peer) {
805     if (peer->connected()) {
806       status = pwemb::StatusCode::CONNECTION_ALREADY_EXISTS;
807     } else {
808       status = peer->connect_status();
809     }
810   }
811 
812   // First send the Command Status response.
813   RespondWithCommandStatus(pwemb::OpCode::CREATE_CONNECTION, status);
814 
815   // If we just sent back an error status then the operation is complete.
816   if (status != pwemb::StatusCode::SUCCESS)
817     return;
818 
819   bredr_connect_pending_ = true;
820   pending_bredr_connect_addr_ = peer_address;
821 
822   // The procedure was initiated successfully but the peer cannot be connected
823   // because it either doesn't exist or isn't connectable.
824   if (!peer || !peer->connectable()) {
825     bt_log(INFO,
826            "fake-hci",
827            "requested peer %s cannot be connected; request will time out",
828            peer_address.ToString().c_str());
829 
830     bredr_connect_rsp_task_.Cancel();
831     bredr_connect_rsp_task_.set_function(
832         [this, peer_address](pw::async::Context /*ctx*/, pw::Status status) {
833           if (!status.ok()) {
834             return;
835           }
836           bredr_connect_pending_ = false;
837 
838           auto response =
839               hci::EventPacket::New<pwemb::ConnectionCompleteEventWriter>(
840                   hci_spec::kConnectionCompleteEventCode);
841           response.view_t().status().Write(pwemb::StatusCode::PAGE_TIMEOUT);
842           response.view_t().bd_addr().CopyFrom(peer_address.value().view());
843           SendCommandChannelPacket(response.data());
844         });
845 
846     // Default page timeout of 5.12s
847     // See Core Spec v5.0 Vol 2, Part E, Section 6.6
848     constexpr pw::chrono::SystemClock::duration default_page_timeout =
849         std::chrono::microseconds(static_cast<int64_t>(625) * 0x2000);
850     bredr_connect_rsp_task_.PostAfter(default_page_timeout);
851     return;
852   }
853 
854   if (next_conn_handle_ == 0x0FFF) {
855     // Ran out of handles
856     status = pwemb::StatusCode::CONNECTION_LIMIT_EXCEEDED;
857   } else {
858     status = peer->connect_response();
859   }
860 
861   auto response = hci::EventPacket::New<pwemb::ConnectionCompleteEventWriter>(
862       hci_spec::kConnectionCompleteEventCode);
863   response.view_t().status().Write(status);
864   response.view_t().bd_addr().CopyFrom(params.bd_addr());
865   response.view_t().link_type().Write(pwemb::LinkType::ACL);
866   response.view_t().encryption_enabled().Write(
867       pwemb::GenericEnableParam::DISABLE);
868 
869   if (status == pwemb::StatusCode::SUCCESS) {
870     hci_spec::ConnectionHandle handle = ++next_conn_handle_;
871     response.view_t().connection_handle().Write(handle);
872   }
873 
874   // Don't send a connection event if we were asked to force the request to
875   // remain pending. This is used by test cases that operate during the pending
876   // state.
877   if (peer->force_pending_connect()) {
878     return;
879   }
880 
881   bredr_connect_rsp_task_.Cancel();
882   bredr_connect_rsp_task_.set_function(
883       [response, peer, this](pw::async::Context /*ctx*/,
884                              pw::Status status) mutable {
885         if (!status.ok()) {
886           return;
887         }
888         bredr_connect_pending_ = false;
889 
890         if (response.view_t().status().Read() == pwemb::StatusCode::SUCCESS) {
891           bool notify = !peer->connected();
892           hci_spec::ConnectionHandle handle =
893               response.view_t().connection_handle().Read();
894           peer->AddLink(handle);
895           if (notify && peer->connected()) {
896             NotifyConnectionState(peer->address(), handle, /*connected=*/true);
897           }
898         }
899 
900         SendCommandChannelPacket(response.data());
901       });
902   bredr_connect_rsp_task_.Post();
903 }
904 
OnLECreateConnectionCommandReceived(const pwemb::LECreateConnectionCommandView & params)905 void FakeController::OnLECreateConnectionCommandReceived(
906     const pwemb::LECreateConnectionCommandView& params) {
907   le_create_connection_command_count_++;
908 
909   if (advertising_procedure() == AdvertisingProcedure::kExtended) {
910     RespondWithCommandStatus(pwemb::OpCode::LE_CREATE_CONNECTION,
911                              pwemb::StatusCode::COMMAND_DISALLOWED);
912     return;
913   }
914 
915   if (le_create_connection_cb_) {
916     le_create_connection_cb_(params);
917   }
918 
919   // Cannot issue this command while a request is already pending.
920   if (le_connect_pending_) {
921     RespondWithCommandStatus(pwemb::OpCode::LE_CREATE_CONNECTION,
922                              pwemb::StatusCode::COMMAND_DISALLOWED);
923     return;
924   }
925 
926   // The link is considered lost after connection_interval_max * 2. Connection
927   // events (when data pdus are transmitted) must occur at least once within
928   // that time frame.
929   if (params.max_connection_event_length().Read() >
930       2 * params.connection_interval_max().Read()) {
931     RespondWithCommandStatus(pwemb::OpCode::LE_CREATE_CONNECTION,
932                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
933     return;
934   }
935 
936   std::optional<DeviceAddress::Type> addr_type =
937       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read());
938   PW_DCHECK(addr_type && *addr_type != DeviceAddress::Type::kBREDR);
939 
940   const DeviceAddress peer_address(*addr_type,
941                                    DeviceAddressBytes(params.peer_address()));
942   pw::bluetooth::emboss::StatusCode status =
943       pw::bluetooth::emboss::StatusCode::SUCCESS;
944 
945   // Find the peer that matches the requested address.
946   FakePeer* peer = FindPeer(peer_address);
947   if (peer) {
948     if (peer->connected()) {
949       status = pwemb::StatusCode::CONNECTION_ALREADY_EXISTS;
950     } else {
951       status = peer->connect_status();
952     }
953   }
954 
955   // First send the Command Status response.
956   RespondWithCommandStatus(pwemb::OpCode::LE_CREATE_CONNECTION, status);
957 
958   // If we just sent back an error status then the operation is complete.
959   if (status != pwemb::StatusCode::SUCCESS) {
960     return;
961   }
962 
963   le_connect_pending_ = true;
964   CaptureLEConnectParams(params);
965 
966   // The procedure was initiated successfully but the peer cannot be connected
967   // because it either doesn't exist or isn't connectable.
968   if (!peer || !peer->connectable()) {
969     bt_log(INFO,
970            "fake-hci",
971            "requested fake peer cannot be connected; request will time out");
972     return;
973   }
974 
975   // Don't send a connection event if we were asked to force the request to
976   // remain pending. This is used by test cases that operate during the pending
977   // state.
978   if (peer->force_pending_connect()) {
979     return;
980   }
981 
982   if (next_conn_handle_ == 0x0FFF) {
983     // Ran out of handles
984     status = pwemb::StatusCode::CONNECTION_LIMIT_EXCEEDED;
985   } else {
986     status = peer->connect_response();
987   }
988 
989   uint16_t interval_min = params.connection_interval_min().Read();
990   uint16_t interval_max = params.connection_interval_max().Read();
991   uint16_t interval = interval_min + ((interval_max - interval_min) / 2);
992 
993   hci_spec::LEConnectionParameters conn_params(
994       interval,
995       params.max_latency().Read(),
996       params.supervision_timeout().Read());
997   peer->set_le_params(conn_params);
998 
999   bool use_enhanced_connection_complete = settings_.is_event_unmasked(
1000       hci_spec::LEEventMask::kLEEnhancedConnectionComplete);
1001   if (use_enhanced_connection_complete) {
1002     SendEnhancedConnectionCompleteEvent(status,
1003                                         params,
1004                                         interval,
1005                                         params.max_latency().Read(),
1006                                         params.supervision_timeout().Read());
1007   } else {
1008     SendConnectionCompleteEvent(status, params, interval);
1009   }
1010 }
1011 
OnLEExtendedCreateConnectionCommandReceived(const pwemb::LEExtendedCreateConnectionCommandV1View & params)1012 void FakeController::OnLEExtendedCreateConnectionCommandReceived(
1013     const pwemb::LEExtendedCreateConnectionCommandV1View& params) {
1014   if (!EnableExtendedAdvertising()) {
1015     bt_log(INFO,
1016            "fake-hci",
1017            "extended create connection command rejected, legacy advertising is "
1018            "in use");
1019     RespondWithCommandStatus(pwemb::OpCode::LE_EXTENDED_CREATE_CONNECTION_V1,
1020                              pwemb::StatusCode::COMMAND_DISALLOWED);
1021     return;
1022   }
1023 
1024   if (const auto& phys = params.initiating_phys();
1025       !phys.le_1m().Read() && !phys.le_2m().Read() && phys.le_coded().Read()) {
1026     RespondWithCommandStatus(pwemb::OpCode::LE_EXTENDED_CREATE_CONNECTION_V1,
1027                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1028   }
1029 
1030   // Cannot issue this command while a request is already pending.
1031   if (le_connect_pending_) {
1032     RespondWithCommandStatus(pwemb::OpCode::LE_EXTENDED_CREATE_CONNECTION_V1,
1033                              pwemb::StatusCode::COMMAND_DISALLOWED);
1034     return;
1035   }
1036 
1037   // The link is considered lost after connection_interval_max * 2. Connection
1038   // events (when data pdus are transmitted) must occur at least once within
1039   // that time frame.
1040   if (params.data()[0].max_connection_event_length().Read() >
1041       2 * params.data()[0].connection_interval_max().Read()) {
1042     RespondWithCommandStatus(pwemb::OpCode::LE_EXTENDED_CREATE_CONNECTION_V1,
1043                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1044     return;
1045   }
1046 
1047   DeviceAddress::Type addr_type =
1048       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read());
1049   const DeviceAddress peer_address(addr_type,
1050                                    DeviceAddressBytes(params.peer_address()));
1051 
1052   pwemb::StatusCode status = pwemb::StatusCode::SUCCESS;
1053 
1054   // Find the peer that matches the requested address.
1055   FakePeer* peer = FindPeer(peer_address);
1056   if (peer) {
1057     if (peer->connected()) {
1058       status = pwemb::StatusCode::CONNECTION_ALREADY_EXISTS;
1059     } else {
1060       status = peer->connect_status();
1061     }
1062   }
1063 
1064   // First send the Command Status response.
1065   RespondWithCommandStatus(pwemb::OpCode::LE_EXTENDED_CREATE_CONNECTION_V1,
1066                            status);
1067 
1068   // If we just sent back an error status then the operation is complete.
1069   if (status != pwemb::StatusCode::SUCCESS) {
1070     return;
1071   }
1072 
1073   le_connect_pending_ = true;
1074   CaptureLEConnectParams(params);
1075 
1076   // The procedure was initiated successfully but the peer cannot be connected
1077   // because it either doesn't exist or isn't connectable.
1078   if (!peer || !peer->connectable()) {
1079     bt_log(INFO,
1080            "fake-hci",
1081            "requested fake peer cannot be connected; request will time out");
1082     return;
1083   }
1084 
1085   // Don't send a connection event if we were asked to force the request to
1086   // remain pending. This is used by test cases that operate during the pending
1087   // state.
1088   if (peer->force_pending_connect()) {
1089     return;
1090   }
1091 
1092   if (next_conn_handle_ == 0x0FFF) {
1093     // Ran out of handles
1094     status = pwemb::StatusCode::CONNECTION_LIMIT_EXCEEDED;
1095   } else {
1096     status = peer->connect_response();
1097   }
1098 
1099   uint16_t interval_min = params.data()[0].connection_interval_min().Read();
1100   uint16_t interval_max = params.data()[0].connection_interval_max().Read();
1101   uint16_t interval = interval_min + ((interval_max - interval_min) / 2);
1102 
1103   hci_spec::LEConnectionParameters conn_params(
1104       interval,
1105       params.data()[0].max_latency().Read(),
1106       params.data()[0].supervision_timeout().Read());
1107   peer->set_le_params(conn_params);
1108 
1109   SendEnhancedConnectionCompleteEvent(
1110       status,
1111       params,
1112       interval,
1113       params.data()[0].max_latency().Read(),
1114       params.data()[0].supervision_timeout().Read());
1115 }
1116 
1117 template <typename T>
SendEnhancedConnectionCompleteEvent(pwemb::StatusCode status,const T & params,uint16_t interval,uint16_t max_latency,uint16_t supervision_timeout)1118 void FakeController::SendEnhancedConnectionCompleteEvent(
1119     pwemb::StatusCode status,
1120     const T& params,
1121     uint16_t interval,
1122     uint16_t max_latency,
1123     uint16_t supervision_timeout) {
1124   DeviceAddress::Type addr_type =
1125       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read());
1126   const DeviceAddress peer_address(addr_type,
1127                                    DeviceAddressBytes(params.peer_address()));
1128 
1129   auto packet = hci::EventPacket::New<
1130       pwemb::LEEnhancedConnectionCompleteSubeventV1Writer>(
1131       hci_spec::kLEMetaEventCode);
1132   auto view = packet.view_t();
1133   view.le_meta_event().subevent_code().Write(
1134       hci_spec::kLEEnhancedConnectionCompleteSubeventCode);
1135   view.status().Write(status);
1136   view.peer_address().CopyFrom(params.peer_address());
1137   view.peer_address_type().Write(DeviceAddress::DeviceAddrToLeAddr(addr_type));
1138   view.peripheral_latency().Write(max_latency);
1139   view.connection_interval().Write(interval);
1140   view.supervision_timeout().Write(supervision_timeout);
1141   view.role().Write(settings_.le_connection_role);
1142   view.connection_handle().Write(++next_conn_handle_);
1143 
1144   le_connect_rsp_task_.Cancel();
1145   le_connect_rsp_task_.set_function(
1146       [packet, address = peer_address, this](pw::async::Context /*ctx*/,
1147                                              pw::Status status) {
1148         auto peer = FindPeer(address);
1149         if (!peer || !status.ok()) {
1150           // The peer has been removed or dispatcher shut down; Ignore this
1151           // response
1152           return;
1153         }
1154 
1155         le_connect_pending_ = false;
1156 
1157         auto view =
1158             packet.view<pwemb::LEEnhancedConnectionCompleteSubeventV1View>();
1159         if (view.status().Read() == pwemb::StatusCode::SUCCESS) {
1160           bool not_previously_connected = !peer->connected();
1161           hci_spec::ConnectionHandle handle = view.connection_handle().Read();
1162           peer->AddLink(handle);
1163           if (not_previously_connected && peer->connected()) {
1164             NotifyConnectionState(peer->address(), handle, /*connected=*/true);
1165           }
1166         }
1167 
1168         SendCommandChannelPacket(packet.data());
1169       });
1170 
1171   le_connect_rsp_task_.PostAfter(settings_.le_connection_delay);
1172 }
1173 
SendConnectionCompleteEvent(pwemb::StatusCode status,const pwemb::LECreateConnectionCommandView & params,uint16_t interval)1174 void FakeController::SendConnectionCompleteEvent(
1175     pwemb::StatusCode status,
1176     const pwemb::LECreateConnectionCommandView& params,
1177     uint16_t interval) {
1178   DeviceAddress::Type addr_type =
1179       DeviceAddress::LeAddrToDeviceAddr(params.peer_address_type().Read());
1180   const DeviceAddress peer_address(addr_type,
1181                                    DeviceAddressBytes(params.peer_address()));
1182 
1183   auto packet =
1184       hci::EventPacket::New<pwemb::LEConnectionCompleteSubeventWriter>(
1185           hci_spec::kLEMetaEventCode);
1186   auto view = packet.view_t();
1187   view.le_meta_event().subevent_code().Write(
1188       hci_spec::kLEConnectionCompleteSubeventCode);
1189   view.status().Write(status);
1190   view.peer_address().CopyFrom(params.peer_address());
1191   view.peer_address_type().Write(
1192       DeviceAddress::DeviceAddrToLePeerAddrNoAnon(addr_type));
1193 
1194   view.peripheral_latency().CopyFrom(params.max_latency());
1195   view.connection_interval().Write(interval);
1196   view.supervision_timeout().CopyFrom(params.supervision_timeout());
1197   view.role().Write(settings_.le_connection_role);
1198   view.connection_handle().Write(++next_conn_handle_);
1199 
1200   le_connect_rsp_task_.Cancel();
1201   le_connect_rsp_task_.set_function(
1202       [packet, address = peer_address, this](pw::async::Context /*ctx*/,
1203                                              pw::Status status) {
1204         auto peer = FindPeer(address);
1205         if (!peer || !status.ok()) {
1206           // The peer has been removed or dispatcher shut down; Ignore this
1207           // response
1208           return;
1209         }
1210 
1211         le_connect_pending_ = false;
1212 
1213         auto view = packet.view<pwemb::LEConnectionCompleteSubeventView>();
1214         if (view.status().Read() == pwemb::StatusCode::SUCCESS) {
1215           bool not_previously_connected = !peer->connected();
1216           hci_spec::ConnectionHandle handle = view.connection_handle().Read();
1217           peer->AddLink(handle);
1218           if (not_previously_connected && peer->connected()) {
1219             NotifyConnectionState(peer->address(), handle, /*connected=*/true);
1220           }
1221         }
1222 
1223         SendCommandChannelPacket(packet.data());
1224       });
1225   le_connect_rsp_task_.PostAfter(settings_.le_connection_delay);
1226 }
1227 
OnLEConnectionUpdateCommandReceived(const pwemb::LEConnectionUpdateCommandView & params)1228 void FakeController::OnLEConnectionUpdateCommandReceived(
1229     const pwemb::LEConnectionUpdateCommandView& params) {
1230   hci_spec::ConnectionHandle handle = params.connection_handle().Read();
1231   FakePeer* peer = FindByConnHandle(handle);
1232   if (!peer) {
1233     RespondWithCommandStatus(pwemb::OpCode::LE_CONNECTION_UPDATE,
1234                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1235     return;
1236   }
1237 
1238   PW_DCHECK(peer->connected());
1239 
1240   uint16_t min_interval = params.connection_interval_min().UncheckedRead();
1241   uint16_t max_interval = params.connection_interval_max().UncheckedRead();
1242   uint16_t max_latency = params.max_latency().UncheckedRead();
1243   uint16_t supv_timeout = params.supervision_timeout().UncheckedRead();
1244 
1245   if (min_interval > max_interval) {
1246     RespondWithCommandStatus(pwemb::OpCode::LE_CONNECTION_UPDATE,
1247                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1248     return;
1249   }
1250 
1251   RespondWithCommandStatus(pwemb::OpCode::LE_CONNECTION_UPDATE,
1252                            pwemb::StatusCode::SUCCESS);
1253 
1254   hci_spec::LEConnectionParameters conn_params(
1255       min_interval + ((max_interval - min_interval) / 2),
1256       max_latency,
1257       supv_timeout);
1258   peer->set_le_params(conn_params);
1259 
1260   auto packet =
1261       hci::EventPacket::New<pwemb::LEConnectionUpdateCompleteSubeventWriter>(
1262           hci_spec::kLEMetaEventCode);
1263   auto view = packet.view_t();
1264   view.le_meta_event().subevent_code().Write(
1265       hci_spec::kLEConnectionUpdateCompleteSubeventCode);
1266   view.connection_handle().CopyFrom(params.connection_handle());
1267   if (peer->supports_ll_conn_update_procedure()) {
1268     view.status().Write(pwemb::StatusCode::SUCCESS);
1269     view.connection_interval().UncheckedWrite(conn_params.interval());
1270     view.peripheral_latency().CopyFrom(params.max_latency());
1271     view.supervision_timeout().UncheckedCopyFrom(params.supervision_timeout());
1272   } else {
1273     view.status().Write(pwemb::StatusCode::UNSUPPORTED_REMOTE_FEATURE);
1274   }
1275   SendCommandChannelPacket(packet.data());
1276 
1277   NotifyLEConnectionParameters(peer->address(), conn_params);
1278 }
1279 
OnDisconnectCommandReceived(const pwemb::DisconnectCommandView & params)1280 void FakeController::OnDisconnectCommandReceived(
1281     const pwemb::DisconnectCommandView& params) {
1282   hci_spec::ConnectionHandle handle = params.connection_handle().Read();
1283 
1284   // Find the peer that matches the disconnected handle.
1285   FakePeer* peer = FindByConnHandle(handle);
1286   if (!peer) {
1287     RespondWithCommandStatus(pwemb::OpCode::DISCONNECT,
1288                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1289     return;
1290   }
1291 
1292   PW_DCHECK(peer->connected());
1293 
1294   RespondWithCommandStatus(pwemb::OpCode::DISCONNECT,
1295                            pwemb::StatusCode::SUCCESS);
1296 
1297   bool notify = peer->connected();
1298   peer->RemoveLink(handle);
1299   if (notify && !peer->connected()) {
1300     NotifyConnectionState(peer->address(), handle, /*connected=*/false);
1301   }
1302 
1303   if (auto_disconnection_complete_event_enabled_) {
1304     SendDisconnectionCompleteEvent(handle);
1305   }
1306 }
1307 
OnWriteLEHostSupportCommandReceived(const pwemb::WriteLEHostSupportCommandView & params)1308 void FakeController::OnWriteLEHostSupportCommandReceived(
1309     const pwemb::WriteLEHostSupportCommandView& params) {
1310   if (params.le_supported_host().Read() == pwemb::GenericEnableParam::ENABLE) {
1311     SetBit(&settings_.lmp_features_page1,
1312            hci_spec::LMPFeature::kLESupportedHost);
1313   } else {
1314     UnsetBit(&settings_.lmp_features_page1,
1315              hci_spec::LMPFeature::kLESupportedHost);
1316   }
1317 
1318   RespondWithCommandComplete(pwemb::OpCode::WRITE_LE_HOST_SUPPORT,
1319                              pwemb::StatusCode::SUCCESS);
1320 }
1321 
OnWriteSecureConnectionsHostSupport(const pwemb::WriteSecureConnectionsHostSupportCommandView & params)1322 void FakeController::OnWriteSecureConnectionsHostSupport(
1323     const pwemb::WriteSecureConnectionsHostSupportCommandView& params) {
1324   // Core Spec Volume 4, Part E, Section 7.3.92: If the Host issues this command
1325   // while the Controller is paging, has page scanning enabled, or has an ACL
1326   // connection, the Controller shall return the error code Command Disallowed
1327   // (0x0C).
1328   bool has_acl_connection = false;
1329   for (auto& [_, peer] : peers_) {
1330     if (peer->connected()) {
1331       has_acl_connection = true;
1332       break;
1333     }
1334   }
1335   if (bredr_connect_pending_ || isBREDRPageScanEnabled() ||
1336       has_acl_connection) {
1337     RespondWithCommandComplete(
1338         pwemb::OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT,
1339         pwemb::StatusCode::COMMAND_DISALLOWED);
1340     return;
1341   }
1342 
1343   if (params.secure_connections_host_support().Read() ==
1344       pwemb::GenericEnableParam::ENABLE) {
1345     SetBit(&settings_.lmp_features_page1,
1346            hci_spec::LMPFeature::kSecureConnectionsHostSupport);
1347   } else {
1348     UnsetBit(&settings_.lmp_features_page1,
1349              hci_spec::LMPFeature::kSecureConnectionsHostSupport);
1350   }
1351 
1352   RespondWithCommandComplete(
1353       pwemb::OpCode::WRITE_SECURE_CONNECTIONS_HOST_SUPPORT,
1354       pwemb::StatusCode::SUCCESS);
1355 }
1356 
OnReset()1357 void FakeController::OnReset() {
1358   // TODO(fxbug.dev/42159137): actually do some resetting of stuff here
1359   RespondWithCommandComplete(pwemb::OpCode::RESET, pwemb::StatusCode::SUCCESS);
1360 }
1361 
OnInquiry(const pwemb::InquiryCommandView & params)1362 void FakeController::OnInquiry(const pwemb::InquiryCommandView& params) {
1363   // Confirm that LAP array is equal to either kGIAC or kLIAC.
1364   if (params.lap().Read() != pwemb::InquiryAccessCode::GIAC &&
1365       params.lap().Read() != pwemb::InquiryAccessCode::LIAC) {
1366     RespondWithCommandStatus(pwemb::OpCode::INQUIRY,
1367                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1368     return;
1369   }
1370 
1371   if (params.inquiry_length().Read() == 0x00 ||
1372       params.inquiry_length().Read() > hci_spec::kInquiryLengthMax) {
1373     RespondWithCommandStatus(pwemb::OpCode::INQUIRY,
1374                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1375     return;
1376   }
1377 
1378   inquiry_num_responses_left_ = params.num_responses().Read();
1379   if (params.num_responses().Read() == 0) {
1380     inquiry_num_responses_left_ = -1;
1381   }
1382 
1383   RespondWithCommandStatus(pwemb::OpCode::INQUIRY, pwemb::StatusCode::SUCCESS);
1384 
1385   bt_log(INFO, "fake-hci", "sending inquiry responses..");
1386   SendInquiryResponses();
1387 
1388   (void)heap_dispatcher().PostAfter(
1389       [this](pw::async::Context /*ctx*/, pw::Status status) {
1390         if (!status.ok()) {
1391           return;
1392         }
1393         auto output = hci::EventPacket::New<pwemb::InquiryCompleteEventWriter>(
1394             hci_spec::kInquiryCompleteEventCode);
1395         output.view_t().status().Write(pwemb::StatusCode::SUCCESS);
1396         SendCommandChannelPacket(output.data());
1397       },
1398       std::chrono::milliseconds(params.inquiry_length().Read()) * 1280);
1399 }
1400 
OnLESetScanEnable(const pwemb::LESetScanEnableCommandView & params)1401 void FakeController::OnLESetScanEnable(
1402     const pwemb::LESetScanEnableCommandView& params) {
1403   if (!EnableLegacyAdvertising()) {
1404     bt_log(
1405         INFO,
1406         "fake-hci",
1407         "legacy advertising command rejected, extended advertising is in use");
1408     RespondWithCommandStatus(pwemb::OpCode::LE_SET_SCAN_ENABLE,
1409                              pwemb::StatusCode::COMMAND_DISALLOWED);
1410     return;
1411   }
1412 
1413   le_scan_state_.enabled = false;
1414   if (params.le_scan_enable().Read() == pwemb::GenericEnableParam::ENABLE) {
1415     le_scan_state_.enabled = true;
1416   }
1417 
1418   le_scan_state_.filter_duplicates = false;
1419   if (params.filter_duplicates().Read() == pwemb::GenericEnableParam::ENABLE) {
1420     le_scan_state_.filter_duplicates = true;
1421   }
1422 
1423   // Post the scan state update before scheduling the HCI Command Complete
1424   // event. This guarantees that single-threaded unit tests receive the scan
1425   // state update BEFORE the HCI command sequence terminates.
1426   if (scan_state_cb_) {
1427     scan_state_cb_(le_scan_state_.enabled);
1428   }
1429 
1430   RespondWithCommandComplete(pwemb::OpCode::LE_SET_SCAN_ENABLE,
1431                              pwemb::StatusCode::SUCCESS);
1432 
1433   if (le_scan_state_.enabled) {
1434     SendAdvertisingReports();
1435   }
1436 }
1437 
OnLESetExtendedScanEnable(const pwemb::LESetExtendedScanEnableCommandView & params)1438 void FakeController::OnLESetExtendedScanEnable(
1439     const pwemb::LESetExtendedScanEnableCommandView& params) {
1440   if (!EnableExtendedAdvertising()) {
1441     bt_log(
1442         INFO,
1443         "fake-hci",
1444         "extended advertising command rejected, legacy advertising is in use");
1445     RespondWithCommandStatus(pwemb::OpCode::LE_SET_EXTENDED_SCAN_ENABLE,
1446                              pwemb::StatusCode::COMMAND_DISALLOWED);
1447     return;
1448   }
1449 
1450   le_scan_state_.enabled = false;
1451   if (params.scanning_enabled().Read() == pwemb::GenericEnableParam::ENABLE) {
1452     le_scan_state_.enabled = true;
1453   }
1454 
1455   le_scan_state_.filter_duplicates = true;
1456   if (params.filter_duplicates().Read() ==
1457       pwemb::LEExtendedDuplicateFilteringOption::DISABLED) {
1458     le_scan_state_.filter_duplicates = false;
1459   }
1460 
1461   le_scan_state_.duration = params.duration().Read();
1462   le_scan_state_.period = params.period().Read();
1463 
1464   // Post the scan state update before scheduling the HCI Command Complete
1465   // event. This guarantees that single-threaded unit tests receive the scan
1466   // state update BEFORE the HCI command sequence terminates.
1467   if (scan_state_cb_) {
1468     scan_state_cb_(le_scan_state_.enabled);
1469   }
1470 
1471   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_SCAN_ENABLE,
1472                              pwemb::StatusCode::SUCCESS);
1473 
1474   if (le_scan_state_.enabled) {
1475     SendAdvertisingReports();
1476   }
1477 }
1478 
OnLESetScanParameters(const pwemb::LESetScanParametersCommandView & params)1479 void FakeController::OnLESetScanParameters(
1480     const pwemb::LESetScanParametersCommandView& params) {
1481   if (!EnableLegacyAdvertising()) {
1482     bt_log(
1483         INFO,
1484         "fake-hci",
1485         "legacy advertising command rejected, extended advertising is in use");
1486     RespondWithCommandStatus(pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1487                              pwemb::StatusCode::COMMAND_DISALLOWED);
1488     return;
1489   }
1490 
1491   if (le_scan_state_.enabled) {
1492     RespondWithCommandComplete(pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1493                                pwemb::StatusCode::COMMAND_DISALLOWED);
1494     return;
1495   }
1496 
1497   le_scan_state_.own_address_type = params.own_address_type().Read();
1498   le_scan_state_.filter_policy = params.scanning_filter_policy().Read();
1499   le_scan_state_.scan_type = params.le_scan_type().Read();
1500   le_scan_state_.scan_interval = params.le_scan_interval().Read();
1501   le_scan_state_.scan_window = params.le_scan_window().Read();
1502 
1503   RespondWithCommandComplete(pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1504                              pwemb::StatusCode::SUCCESS);
1505 }
1506 
OnLESetExtendedScanParameters(const pwemb::LESetExtendedScanParametersCommandView & params)1507 void FakeController::OnLESetExtendedScanParameters(
1508     const pwemb::LESetExtendedScanParametersCommandView& params) {
1509   if (!EnableExtendedAdvertising()) {
1510     bt_log(
1511         INFO,
1512         "fake-hci",
1513         "extended advertising command rejected, legacy advertising is in use");
1514     RespondWithCommandStatus(pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1515                              pwemb::StatusCode::COMMAND_DISALLOWED);
1516     return;
1517   }
1518 
1519   if (le_scan_state_.enabled) {
1520     RespondWithCommandComplete(pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1521                                pwemb::StatusCode::COMMAND_DISALLOWED);
1522     return;
1523   }
1524 
1525   if (params.num_entries().Read() == 0) {
1526     RespondWithCommandComplete(
1527         pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1528         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1529     return;
1530   }
1531 
1532   le_scan_state_.own_address_type = params.own_address_type().Read();
1533   le_scan_state_.filter_policy = params.scanning_filter_policy().Read();
1534 
1535   // ExtendedLowEnergyScanner sets the same parameters for both the LE 1M and LE
1536   // Coded PHYs. We just take the parameters from the LE 1M PHY for now since we
1537   // don't support using different parameters for different PHYs.
1538   if (!params.scanning_phys().le_1m().Read()) {
1539     RespondWithCommandComplete(
1540         pwemb::OpCode::LE_SET_SCAN_PARAMETERS,
1541         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1542     return;
1543   }
1544 
1545   le_scan_state_.scan_type = params.data()[0].scan_type().Read();
1546   le_scan_state_.scan_interval = params.data()[0].scan_interval().Read();
1547   le_scan_state_.scan_window = params.data()[0].scan_window().Read();
1548   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS,
1549                              pwemb::StatusCode::SUCCESS);
1550 }
1551 
OnLESetHostFeature(const pwemb::LESetHostFeatureCommandView & params)1552 void FakeController::OnLESetHostFeature(
1553     const pwemb::LESetHostFeatureCommandView& params) {
1554   // We only support setting the CIS Host Support Bit
1555   if (params.bit_number().Read() !=
1556       static_cast<uint8_t>(hci_spec::LESupportedFeatureBitPos::
1557                                kConnectedIsochronousStreamHostSupport)) {
1558     RespondWithCommandComplete(
1559         pwemb::OpCode::LE_SET_HOST_FEATURE,
1560         pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
1561     return;
1562   }
1563   if (params.bit_value().Read() ==
1564       pw::bluetooth::emboss::GenericEnableParam::ENABLE) {
1565     SetBit(
1566         &settings_.le_features,
1567         hci_spec::LESupportedFeature::kConnectedIsochronousStreamHostSupport);
1568   } else {
1569     UnsetBit(
1570         &settings_.le_features,
1571         hci_spec::LESupportedFeature::kConnectedIsochronousStreamHostSupport);
1572   }
1573 
1574   RespondWithCommandComplete(pwemb::OpCode::LE_SET_HOST_FEATURE,
1575                              pwemb::StatusCode::SUCCESS);
1576 }
1577 
OnReadLocalExtendedFeatures(const pwemb::ReadLocalExtendedFeaturesCommandView & params)1578 void FakeController::OnReadLocalExtendedFeatures(
1579     const pwemb::ReadLocalExtendedFeaturesCommandView& params) {
1580   auto packet = hci::EventPacket::New<
1581       pwemb::ReadLocalExtendedFeaturesCommandCompleteEventWriter>(
1582       hci_spec::kCommandCompleteEventCode);
1583   auto view = packet.view_t();
1584   view.status().Write(pwemb::StatusCode::SUCCESS);
1585   view.page_number().Write(params.page_number().Read());
1586   view.max_page_number().Write(2);
1587   view.extended_lmp_features().Write(0);
1588   switch (params.page_number().Read()) {
1589     case 0:
1590       view.extended_lmp_features().Write(settings_.lmp_features_page0);
1591       break;
1592     case 1:
1593       view.extended_lmp_features().Write(settings_.lmp_features_page1);
1594       break;
1595     case 2:
1596       view.extended_lmp_features().Write(settings_.lmp_features_page2);
1597       break;
1598     default:
1599       view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1600   }
1601 
1602   RespondWithCommandComplete(pwemb::OpCode::READ_LOCAL_EXTENDED_FEATURES,
1603                              &packet);
1604 }
1605 
OnSetEventMask(const pwemb::SetEventMaskCommandView & params)1606 void FakeController::OnSetEventMask(
1607     const pwemb::SetEventMaskCommandView& params) {
1608   settings_.event_mask = params.event_mask().Read();
1609   RespondWithCommandComplete(pwemb::OpCode::SET_EVENT_MASK,
1610                              pwemb::StatusCode::SUCCESS);
1611 }
1612 
OnLESetEventMask(const pwemb::LESetEventMaskCommandView & params)1613 void FakeController::OnLESetEventMask(
1614     const pwemb::LESetEventMaskCommandView& params) {
1615   settings_.le_event_mask = params.le_event_mask().BackingStorage().ReadUInt();
1616   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EVENT_MASK,
1617                              pwemb::StatusCode::SUCCESS);
1618 }
1619 
OnLEReadBufferSizeV1()1620 void FakeController::OnLEReadBufferSizeV1() {
1621   auto packet = hci::EventPacket::New<
1622       pwemb::LEReadBufferSizeV1CommandCompleteEventWriter>(
1623       hci_spec::kCommandCompleteEventCode);
1624   auto view = packet.view_t();
1625   view.status().Write(pwemb::StatusCode::SUCCESS);
1626   view.le_acl_data_packet_length().Write(settings_.le_acl_data_packet_length);
1627   view.total_num_le_acl_data_packets().Write(
1628       settings_.le_total_num_acl_data_packets);
1629   RespondWithCommandComplete(pwemb::OpCode::LE_READ_BUFFER_SIZE_V1, &packet);
1630 }
1631 
OnLEReadBufferSizeV2()1632 void FakeController::OnLEReadBufferSizeV2() {
1633   auto packet = hci::EventPacket::New<
1634       pwemb::LEReadBufferSizeV2CommandCompleteEventWriter>(
1635       hci_spec::kCommandCompleteEventCode);
1636   auto view = packet.view_t();
1637 
1638   view.status().Write(pwemb::StatusCode::SUCCESS);
1639   view.le_acl_data_packet_length().Write(settings_.le_acl_data_packet_length);
1640   view.total_num_le_acl_data_packets().Write(
1641       settings_.le_total_num_acl_data_packets);
1642   view.iso_data_packet_length().Write(settings_.iso_data_packet_length);
1643   view.total_num_iso_data_packets().Write(settings_.total_num_iso_data_packets);
1644 
1645   RespondWithCommandComplete(pwemb::OpCode::LE_READ_BUFFER_SIZE_V2, &packet);
1646 }
1647 
OnLEReadSupportedStates()1648 void FakeController::OnLEReadSupportedStates() {
1649   auto packet = hci::EventPacket::New<
1650       pwemb::LEReadSupportedStatesCommandCompleteEventWriter>(
1651       hci_spec::kCommandCompleteEventCode);
1652   auto view = packet.view_t();
1653   view.status().Write(pwemb::StatusCode::SUCCESS);
1654   view.le_states().BackingStorage().WriteLittleEndianUInt<64>(
1655       settings_.le_supported_states);
1656   RespondWithCommandComplete(pwemb::OpCode::LE_READ_SUPPORTED_STATES, &packet);
1657 }
1658 
OnLEReadLocalSupportedFeatures()1659 void FakeController::OnLEReadLocalSupportedFeatures() {
1660   auto packet = hci::EventPacket::New<
1661       pwemb::LEReadLocalSupportedFeaturesCommandCompleteEventWriter>(
1662       hci_spec::kCommandCompleteEventCode);
1663   auto view = packet.view_t();
1664   view.status().Write(pwemb::StatusCode::SUCCESS);
1665   view.le_features().BackingStorage().WriteUInt(settings_.le_features);
1666   RespondWithCommandComplete(pwemb::OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES,
1667                              &packet);
1668 }
1669 
OnLECreateConnectionCancel()1670 void FakeController::OnLECreateConnectionCancel() {
1671   if (!le_connect_pending_) {
1672     RespondWithCommandComplete(pwemb::OpCode::LE_CREATE_CONNECTION_CANCEL,
1673                                pwemb::StatusCode::COMMAND_DISALLOWED);
1674     return;
1675   }
1676 
1677   le_connect_pending_ = false;
1678   le_connect_rsp_task_.Cancel();
1679   PW_DCHECK(le_connect_params_);
1680 
1681   NotifyConnectionState(le_connect_params_->peer_address,
1682                         0,
1683                         /*connected=*/false,
1684                         /*canceled=*/true);
1685 
1686   bool use_enhanced_connection_complete = settings_.is_event_unmasked(
1687       hci_spec::LEEventMask::kLEEnhancedConnectionComplete);
1688   if (use_enhanced_connection_complete) {
1689     auto packet = hci::EventPacket::New<
1690         pwemb::LEEnhancedConnectionCompleteSubeventV1Writer>(
1691         hci_spec::kLEMetaEventCode);
1692     auto params = packet.view_t();
1693     params.le_meta_event().subevent_code().Write(
1694         hci_spec::kLEEnhancedConnectionCompleteSubeventCode);
1695     params.status().Write(pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1696     params.peer_address().CopyFrom(
1697         le_connect_params_->peer_address.value().view());
1698     params.peer_address_type().Write(DeviceAddress::DeviceAddrToLeAddr(
1699         le_connect_params_->peer_address.type()));
1700 
1701     RespondWithCommandComplete(pwemb::OpCode::LE_CREATE_CONNECTION_CANCEL,
1702                                pwemb::StatusCode::SUCCESS);
1703     SendCommandChannelPacket(packet.data());
1704   } else {
1705     auto packet =
1706         hci::EventPacket::New<pwemb::LEConnectionCompleteSubeventWriter>(
1707             hci_spec::kLEMetaEventCode);
1708     auto params = packet.view_t();
1709     params.le_meta_event().subevent_code().Write(
1710         hci_spec::kLEConnectionCompleteSubeventCode);
1711     params.status().Write(pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1712     params.peer_address().CopyFrom(
1713         le_connect_params_->peer_address.value().view());
1714     params.peer_address_type().Write(
1715         DeviceAddress::DeviceAddrToLePeerAddrNoAnon(
1716             le_connect_params_->peer_address.type()));
1717 
1718     RespondWithCommandComplete(pwemb::OpCode::LE_CREATE_CONNECTION_CANCEL,
1719                                pwemb::StatusCode::SUCCESS);
1720     SendCommandChannelPacket(packet.data());
1721   }
1722 }
1723 
OnWriteExtendedInquiryResponse(const pwemb::WriteExtendedInquiryResponseCommandView & params)1724 void FakeController::OnWriteExtendedInquiryResponse(
1725     const pwemb::WriteExtendedInquiryResponseCommandView& params) {
1726   // As of now, we don't support FEC encoding enabled.
1727   if (params.fec_required().Read() != 0x00) {
1728     RespondWithCommandStatus(pwemb::OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE,
1729                              pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1730   }
1731 
1732   RespondWithCommandComplete(pwemb::OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE,
1733                              pwemb::StatusCode::SUCCESS);
1734 }
1735 
OnWriteSimplePairingMode(const pwemb::WriteSimplePairingModeCommandView & params)1736 void FakeController::OnWriteSimplePairingMode(
1737     const pwemb::WriteSimplePairingModeCommandView& params) {
1738   // "A host shall not set the Simple Pairing Mode to 'disabled'"
1739   // Spec 5.0 Vol 2 Part E Sec 7.3.59
1740   if (params.simple_pairing_mode().Read() !=
1741       pwemb::GenericEnableParam::ENABLE) {
1742     RespondWithCommandComplete(
1743         pwemb::OpCode::WRITE_SIMPLE_PAIRING_MODE,
1744         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1745     return;
1746   }
1747 
1748   SetBit(&settings_.lmp_features_page1,
1749          hci_spec::LMPFeature::kSecureSimplePairingHostSupport);
1750   RespondWithCommandComplete(pwemb::OpCode::WRITE_SIMPLE_PAIRING_MODE,
1751                              pwemb::StatusCode::SUCCESS);
1752 }
1753 
OnReadSimplePairingMode()1754 void FakeController::OnReadSimplePairingMode() {
1755   auto event_packet = hci::EventPacket::New<
1756       pwemb::ReadSimplePairingModeCommandCompleteEventWriter>(
1757       hci_spec::kCommandCompleteEventCode);
1758   auto view = event_packet.view_t();
1759   view.status().Write(pwemb::StatusCode::SUCCESS);
1760   if (CheckBit(settings_.lmp_features_page1,
1761                hci_spec::LMPFeature::kSecureSimplePairingHostSupport)) {
1762     view.simple_pairing_mode().Write(pwemb::GenericEnableParam::ENABLE);
1763   } else {
1764     view.simple_pairing_mode().Write(pwemb::GenericEnableParam::DISABLE);
1765   }
1766 
1767   RespondWithCommandComplete(pwemb::OpCode::READ_SIMPLE_PAIRING_MODE,
1768                              &event_packet);
1769 }
1770 
OnWritePageScanType(const pwemb::WritePageScanTypeCommandView & params)1771 void FakeController::OnWritePageScanType(
1772     const pwemb::WritePageScanTypeCommandView& params) {
1773   page_scan_type_ = params.page_scan_type().Read();
1774   RespondWithCommandComplete(pwemb::OpCode::WRITE_PAGE_SCAN_TYPE,
1775                              pwemb::StatusCode::SUCCESS);
1776 }
1777 
OnReadPageScanType()1778 void FakeController::OnReadPageScanType() {
1779   auto event_packet =
1780       hci::EventPacket::New<pwemb::ReadPageScanTypeCommandCompleteEventWriter>(
1781           hci_spec::kCommandCompleteEventCode);
1782   auto view = event_packet.view_t();
1783   view.status().Write(pwemb::StatusCode::SUCCESS);
1784   view.page_scan_type().Write(page_scan_type_);
1785   RespondWithCommandComplete(pwemb::OpCode::READ_PAGE_SCAN_TYPE, &event_packet);
1786 }
1787 
OnWriteInquiryMode(const pwemb::WriteInquiryModeCommandView & params)1788 void FakeController::OnWriteInquiryMode(
1789     const pwemb::WriteInquiryModeCommandView& params) {
1790   inquiry_mode_ = params.inquiry_mode().Read();
1791   RespondWithCommandComplete(pwemb::OpCode::WRITE_INQUIRY_MODE,
1792                              pwemb::StatusCode::SUCCESS);
1793 }
1794 
OnReadInquiryMode()1795 void FakeController::OnReadInquiryMode() {
1796   auto event_packet =
1797       hci::EventPacket::New<pwemb::ReadInquiryModeCommandCompleteEventWriter>(
1798           hci_spec::kCommandCompleteEventCode);
1799   auto view = event_packet.view_t();
1800   view.status().Write(pwemb::StatusCode::SUCCESS);
1801   view.inquiry_mode().Write(inquiry_mode_);
1802   RespondWithCommandComplete(pwemb::OpCode::READ_INQUIRY_MODE, &event_packet);
1803 }
1804 
OnWriteClassOfDevice(const pwemb::WriteClassOfDeviceCommandView & params)1805 void FakeController::OnWriteClassOfDevice(
1806     const pwemb::WriteClassOfDeviceCommandView& params) {
1807   device_class_ =
1808       DeviceClass(params.class_of_device().BackingStorage().ReadUInt());
1809   NotifyControllerParametersChanged();
1810   RespondWithCommandComplete(pwemb::OpCode::WRITE_CLASS_OF_DEVICE,
1811                              pwemb::StatusCode::SUCCESS);
1812 }
1813 
OnWritePageScanActivity(const pwemb::WritePageScanActivityCommandView & params)1814 void FakeController::OnWritePageScanActivity(
1815     const pwemb::WritePageScanActivityCommandView& params) {
1816   page_scan_interval_ = params.page_scan_interval().Read();
1817   page_scan_window_ = params.page_scan_window().Read();
1818   RespondWithCommandComplete(pwemb::OpCode::WRITE_PAGE_SCAN_ACTIVITY,
1819                              pwemb::StatusCode::SUCCESS);
1820 }
1821 
OnReadPageScanActivity()1822 void FakeController::OnReadPageScanActivity() {
1823   auto event_packet = hci::EventPacket::New<
1824       pwemb::ReadPageScanActivityCommandCompleteEventWriter>(
1825       hci_spec::kCommandCompleteEventCode);
1826   auto view = event_packet.view_t();
1827   view.status().Write(pwemb::StatusCode::SUCCESS);
1828   view.page_scan_interval().Write(page_scan_interval_);
1829   view.page_scan_window().Write(page_scan_window_);
1830   RespondWithCommandComplete(pwemb::OpCode::READ_PAGE_SCAN_ACTIVITY,
1831                              &event_packet);
1832 }
1833 
OnWriteScanEnable(const pwemb::WriteScanEnableCommandView & params)1834 void FakeController::OnWriteScanEnable(
1835     const pwemb::WriteScanEnableCommandView& params) {
1836   bredr_scan_state_ = params.scan_enable().BackingStorage().ReadUInt();
1837   RespondWithCommandComplete(pwemb::OpCode::WRITE_SCAN_ENABLE,
1838                              pwemb::StatusCode::SUCCESS);
1839 }
1840 
OnReadScanEnable()1841 void FakeController::OnReadScanEnable() {
1842   auto event_packet =
1843       hci::EventPacket::New<pwemb::ReadScanEnableCommandCompleteEventWriter>(
1844           hci_spec::kCommandCompleteEventCode);
1845   auto view = event_packet.view_t();
1846   view.status().Write(pwemb::StatusCode::SUCCESS);
1847   view.scan_enable().BackingStorage().WriteUInt(bredr_scan_state_);
1848   RespondWithCommandComplete(pwemb::OpCode::READ_SCAN_ENABLE, &event_packet);
1849 }
1850 
OnReadLocalName()1851 void FakeController::OnReadLocalName() {
1852   auto event_packet =
1853       hci::EventPacket::New<pwemb::ReadLocalNameCommandCompleteEventWriter>(
1854           hci_spec::kCommandCompleteEventCode);
1855   auto view = event_packet.view_t();
1856   view.status().Write(pwemb::StatusCode::SUCCESS);
1857   unsigned char* name_from_event = view.local_name().BackingStorage().data();
1858   char* name_as_cstr = reinterpret_cast<char*>(name_from_event);
1859   std::strncpy(name_as_cstr, local_name_.c_str(), hci_spec::kMaxNameLength);
1860   RespondWithCommandComplete(pwemb::OpCode::READ_LOCAL_NAME, &event_packet);
1861 }
1862 
OnWriteLocalName(const pwemb::WriteLocalNameCommandView & params)1863 void FakeController::OnWriteLocalName(
1864     const pwemb::WriteLocalNameCommandView& params) {
1865   std::size_t name_len = 0;
1866 
1867   auto local_name = params.local_name().BackingStorage().data();
1868 
1869   for (; name_len < hci_spec::kMaxNameLength; ++name_len) {
1870     if (local_name[name_len] == '\0') {
1871       break;
1872     }
1873   }
1874   local_name_ = std::string(local_name, local_name + name_len);
1875   NotifyControllerParametersChanged();
1876   RespondWithCommandComplete(pwemb::OpCode::WRITE_LOCAL_NAME,
1877                              pwemb::StatusCode::SUCCESS);
1878 }
1879 
OnCreateConnectionCancel()1880 void FakeController::OnCreateConnectionCancel() {
1881   auto packet = hci::EventPacket::New<
1882       pwemb::CreateConnectionCancelCommandCompleteEventWriter>(
1883       hci_spec::kCommandCompleteEventCode);
1884   auto view = packet.view_t();
1885   view.status().Write(pwemb::StatusCode::SUCCESS);
1886   view.bd_addr().CopyFrom(pending_bredr_connect_addr_.value().view());
1887 
1888   if (!bredr_connect_pending_) {
1889     // No request is currently pending.
1890     view.status().Write(pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1891     RespondWithCommandComplete(pwemb::OpCode::CREATE_CONNECTION_CANCEL,
1892                                &packet);
1893     return;
1894   }
1895 
1896   bredr_connect_pending_ = false;
1897   bredr_connect_rsp_task_.Cancel();
1898 
1899   NotifyConnectionState(
1900       pending_bredr_connect_addr_, 0, /*connected=*/false, /*canceled=*/true);
1901 
1902   RespondWithCommandComplete(pwemb::OpCode::CREATE_CONNECTION_CANCEL, &packet);
1903 
1904   auto response = hci::EventPacket::New<pwemb::ConnectionCompleteEventWriter>(
1905       hci_spec::kConnectionCompleteEventCode);
1906   response.view_t().status().Write(pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
1907   response.view_t().bd_addr().CopyFrom(
1908       pending_bredr_connect_addr_.value().view());
1909   SendCommandChannelPacket(response.data());
1910 }
1911 
OnReadBufferSize()1912 void FakeController::OnReadBufferSize() {
1913   auto packet =
1914       hci::EventPacket::New<pwemb::ReadBufferSizeCommandCompleteEventWriter>(
1915           hci_spec::kCommandCompleteEventCode);
1916   auto view = packet.view_t();
1917   view.acl_data_packet_length().Write(settings_.acl_data_packet_length);
1918   view.total_num_acl_data_packets().Write(settings_.total_num_acl_data_packets);
1919   view.synchronous_data_packet_length().Write(
1920       settings_.synchronous_data_packet_length);
1921   view.total_num_synchronous_data_packets().Write(
1922       settings_.total_num_synchronous_data_packets);
1923   RespondWithCommandComplete(pwemb::OpCode::READ_BUFFER_SIZE, &packet);
1924 }
1925 
OnReadBRADDR()1926 void FakeController::OnReadBRADDR() {
1927   auto packet =
1928       hci::EventPacket::New<pwemb::ReadBdAddrCommandCompleteEventWriter>(
1929           hci_spec::kCommandCompleteEventCode);
1930   auto view = packet.view_t();
1931   view.status().Write(pwemb::StatusCode::SUCCESS);
1932   view.bd_addr().CopyFrom(settings_.bd_addr.value().view());
1933   RespondWithCommandComplete(pwemb::OpCode::READ_BD_ADDR, &packet);
1934 }
1935 
OnLESetAdvertisingEnable(const pwemb::LESetAdvertisingEnableCommandView & params)1936 void FakeController::OnLESetAdvertisingEnable(
1937     const pwemb::LESetAdvertisingEnableCommandView& params) {
1938   if (!EnableLegacyAdvertising()) {
1939     bt_log(
1940         INFO,
1941         "fake-hci",
1942         "legacy advertising command rejected, extended advertising is in use");
1943     RespondWithCommandStatus(pwemb::OpCode::LE_SET_ADVERTISING_ENABLE,
1944                              pwemb::StatusCode::COMMAND_DISALLOWED);
1945     return;
1946   }
1947 
1948   if (legacy_advertising_state_.own_address_type ==
1949           pw::bluetooth::emboss::LEOwnAddressType::RANDOM &&
1950       !legacy_advertising_state_.random_address.has_value()) {
1951     bt_log(INFO,
1952            "fake-hci",
1953            "cannot enable, random address type requires a random address set");
1954     RespondWithCommandComplete(
1955         pwemb::OpCode::LE_SET_ADVERTISING_ENABLE,
1956         pw::bluetooth::emboss::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
1957     return;
1958   }
1959 
1960   legacy_advertising_state_.enabled =
1961       params.advertising_enable().Read() == pwemb::GenericEnableParam::ENABLE;
1962   RespondWithCommandComplete(pwemb::OpCode::LE_SET_ADVERTISING_ENABLE,
1963                              pwemb::StatusCode::SUCCESS);
1964   NotifyAdvertisingState();
1965 }
1966 
OnLESetScanResponseData(const pwemb::LESetScanResponseDataCommandView & params)1967 void FakeController::OnLESetScanResponseData(
1968     const pwemb::LESetScanResponseDataCommandView& params) {
1969   if (!EnableLegacyAdvertising()) {
1970     bt_log(
1971         INFO,
1972         "fake-hci",
1973         "legacy advertising command rejected, extended advertising is in use");
1974     RespondWithCommandStatus(pwemb::OpCode::LE_SET_SCAN_RESPONSE_DATA,
1975                              pwemb::StatusCode::COMMAND_DISALLOWED);
1976     return;
1977   }
1978 
1979   legacy_advertising_state_.scan_rsp_length =
1980       params.scan_response_data_length().Read();
1981 
1982   if (params.scan_response_data_length().Read() == 0) {
1983     std::memset(legacy_advertising_state_.scan_rsp_data,
1984                 0,
1985                 sizeof(legacy_advertising_state_.scan_rsp_data));
1986   } else {
1987     std::memcpy(legacy_advertising_state_.scan_rsp_data,
1988                 params.scan_response_data().BackingStorage().data(),
1989                 params.scan_response_data_length().Read());
1990   }
1991 
1992   RespondWithCommandComplete(pwemb::OpCode::LE_SET_SCAN_RESPONSE_DATA,
1993                              pwemb::StatusCode::SUCCESS);
1994   NotifyAdvertisingState();
1995 }
1996 
OnLESetAdvertisingData(const pwemb::LESetAdvertisingDataCommandView & params)1997 void FakeController::OnLESetAdvertisingData(
1998     const pwemb::LESetAdvertisingDataCommandView& params) {
1999   if (!EnableLegacyAdvertising()) {
2000     bt_log(
2001         INFO,
2002         "fake-hci",
2003         "legacy advertising command rejected, extended advertising is in use");
2004     RespondWithCommandStatus(pwemb::OpCode::LE_SET_ADVERTISING_DATA,
2005                              pwemb::StatusCode::COMMAND_DISALLOWED);
2006     return;
2007   }
2008 
2009   legacy_advertising_state_.data_length =
2010       params.advertising_data_length().Read();
2011 
2012   if (params.advertising_data_length().Read() == 0) {
2013     std::memset(legacy_advertising_state_.data,
2014                 0,
2015                 sizeof(legacy_advertising_state_.data));
2016   } else {
2017     std::memcpy(legacy_advertising_state_.data,
2018                 params.advertising_data().BackingStorage().data(),
2019                 params.advertising_data_length().Read());
2020   }
2021 
2022   RespondWithCommandComplete(pwemb::OpCode::LE_SET_ADVERTISING_DATA,
2023                              pwemb::StatusCode::SUCCESS);
2024   NotifyAdvertisingState();
2025 }
2026 
OnLESetAdvertisingParameters(const pwemb::LESetAdvertisingParametersCommandView & params)2027 void FakeController::OnLESetAdvertisingParameters(
2028     const pwemb::LESetAdvertisingParametersCommandView& params) {
2029   if (!EnableLegacyAdvertising()) {
2030     bt_log(
2031         INFO,
2032         "fake-hci",
2033         "legacy advertising command rejected, extended advertising is in use");
2034     RespondWithCommandStatus(pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2035                              pwemb::StatusCode::COMMAND_DISALLOWED);
2036     return;
2037   }
2038 
2039   if (legacy_advertising_state_.enabled) {
2040     bt_log(INFO,
2041            "fake-hci",
2042            "cannot set advertising parameters while advertising enabled");
2043     RespondWithCommandComplete(pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2044                                pwemb::StatusCode::COMMAND_DISALLOWED);
2045     return;
2046   }
2047 
2048   uint16_t interval_min = params.advertising_interval_min().UncheckedRead();
2049   uint16_t interval_max = params.advertising_interval_max().UncheckedRead();
2050 
2051   // Core Spec Volume 4, Part E, Section 7.8.5: For high duty cycle directed
2052   // advertising, the Advertising_Interval_Min and Advertising_Interval_Max
2053   // parameters are not used and shall be ignored.
2054   if (params.adv_type().Read() !=
2055       pwemb::LEAdvertisingType::CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED) {
2056     if (interval_min >= interval_max) {
2057       bt_log(INFO,
2058              "fake-hci",
2059              "advertising interval min (%d) not strictly less than max (%d)",
2060              interval_min,
2061              interval_max);
2062       RespondWithCommandComplete(
2063           pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2064           pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2065       return;
2066     }
2067 
2068     if (interval_min < hci_spec::kLEAdvertisingIntervalMin) {
2069       bt_log(INFO,
2070              "fake-hci",
2071              "advertising interval min (%d) less than spec min (%d)",
2072              interval_min,
2073              hci_spec::kLEAdvertisingIntervalMin);
2074       RespondWithCommandComplete(
2075           pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2076           pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2077       return;
2078     }
2079 
2080     if (interval_max > hci_spec::kLEAdvertisingIntervalMax) {
2081       bt_log(INFO,
2082              "fake-hci",
2083              "advertising interval max (%d) greater than spec max (%d)",
2084              interval_max,
2085              hci_spec::kLEAdvertisingIntervalMax);
2086       RespondWithCommandComplete(
2087           pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2088           pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2089       return;
2090     }
2091   }
2092 
2093   legacy_advertising_state_.own_address_type = params.own_address_type().Read();
2094   legacy_advertising_state_.interval_min = interval_min;
2095   legacy_advertising_state_.interval_max = interval_max;
2096 
2097   pwemb::LEAdvertisingType adv_type = params.adv_type().Read();
2098   switch (adv_type) {
2099     case pwemb::LEAdvertisingType::CONNECTABLE_AND_SCANNABLE_UNDIRECTED:
2100       legacy_advertising_state_.properties.scannable = true;
2101       legacy_advertising_state_.properties.connectable = true;
2102       break;
2103     case pwemb::LEAdvertisingType::CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED:
2104       legacy_advertising_state_.properties.directed = true;
2105       legacy_advertising_state_.properties.connectable = true;
2106       break;
2107     case pwemb::LEAdvertisingType::CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED:
2108       legacy_advertising_state_.properties
2109           .high_duty_cycle_directed_connectable = true;
2110       legacy_advertising_state_.properties.directed = true;
2111       legacy_advertising_state_.properties.connectable = true;
2112       break;
2113     case pwemb::LEAdvertisingType::SCANNABLE_UNDIRECTED:
2114       legacy_advertising_state_.properties.scannable = true;
2115       break;
2116     case pwemb::LEAdvertisingType::NOT_CONNECTABLE_UNDIRECTED:
2117       break;
2118   }
2119 
2120   bt_log(INFO,
2121          "fake-hci",
2122          "start advertising using address type: %hhd",
2123          static_cast<char>(legacy_advertising_state_.own_address_type));
2124 
2125   RespondWithCommandComplete(pwemb::OpCode::LE_SET_ADVERTISING_PARAMETERS,
2126                              pwemb::StatusCode::SUCCESS);
2127   NotifyAdvertisingState();
2128 }
2129 
OnLESetRandomAddress(const pwemb::LESetRandomAddressCommandView & params)2130 void FakeController::OnLESetRandomAddress(
2131     const pwemb::LESetRandomAddressCommandView& params) {
2132   if (!EnableLegacyAdvertising()) {
2133     bt_log(
2134         INFO,
2135         "fake-hci",
2136         "legacy advertising command rejected, extended advertising is in use");
2137     RespondWithCommandStatus(pwemb::OpCode::LE_SET_RANDOM_ADDRESS,
2138                              pwemb::StatusCode::COMMAND_DISALLOWED);
2139     return;
2140   }
2141 
2142   if (legacy_advertising_state().enabled || le_scan_state().enabled) {
2143     bt_log(INFO,
2144            "fake-hci",
2145            "cannot set LE random address while scanning or advertising");
2146     RespondWithCommandComplete(pwemb::OpCode::LE_SET_RANDOM_ADDRESS,
2147                                pwemb::StatusCode::COMMAND_DISALLOWED);
2148     return;
2149   }
2150 
2151   legacy_advertising_state_.random_address =
2152       DeviceAddress(DeviceAddress::Type::kLERandom,
2153                     DeviceAddressBytes(params.random_address()));
2154   RespondWithCommandComplete(pwemb::OpCode::LE_SET_RANDOM_ADDRESS,
2155                              pwemb::StatusCode::SUCCESS);
2156 }
2157 
OnReadLocalSupportedFeatures()2158 void FakeController::OnReadLocalSupportedFeatures() {
2159   auto packet = hci::EventPacket::New<
2160       pwemb::ReadLocalSupportedFeaturesCommandCompleteEventWriter>(
2161       hci_spec::kCommandCompleteEventCode);
2162   auto view = packet.view_t();
2163   view.status().Write(pwemb::StatusCode::SUCCESS);
2164   view.lmp_features().Write(settings_.lmp_features_page0);
2165   RespondWithCommandComplete(pwemb::OpCode::READ_LOCAL_SUPPORTED_FEATURES,
2166                              &packet);
2167 }
2168 
OnReadLocalSupportedCommands()2169 void FakeController::OnReadLocalSupportedCommands() {
2170   auto packet = hci::EventPacket::New<
2171       pwemb::ReadLocalSupportedCommandsCommandCompleteEventWriter>(
2172       hci_spec::kCommandCompleteEventCode);
2173   auto view = packet.view_t();
2174   view.status().Write(pwemb::StatusCode::SUCCESS);
2175   std::memcpy(view.supported_commands().BackingStorage().begin(),
2176               settings_.supported_commands,
2177               sizeof(settings_.supported_commands));
2178   RespondWithCommandComplete(pwemb::OpCode::READ_LOCAL_SUPPORTED_COMMANDS,
2179                              &packet);
2180 }
2181 
OnReadLocalVersionInfo()2182 void FakeController::OnReadLocalVersionInfo() {
2183   auto packet = hci::EventPacket::New<
2184       pwemb::ReadLocalVersionInfoCommandCompleteEventWriter>(
2185       hci_spec::kCommandCompleteEventCode);
2186   packet.view_t().hci_version().Write(settings_.hci_version);
2187   RespondWithCommandComplete(pwemb::OpCode::READ_LOCAL_VERSION_INFO, &packet);
2188 }
2189 
OnReadRemoteNameRequestCommandReceived(const pwemb::RemoteNameRequestCommandView & params)2190 void FakeController::OnReadRemoteNameRequestCommandReceived(
2191     const pwemb::RemoteNameRequestCommandView& params) {
2192   const DeviceAddress peer_address(DeviceAddress::Type::kBREDR,
2193                                    DeviceAddressBytes(params.bd_addr()));
2194 
2195   // Find the peer that matches the requested address.
2196   FakePeer* peer = FindPeer(peer_address);
2197   if (!peer) {
2198     RespondWithCommandStatus(pwemb::OpCode::REMOTE_NAME_REQUEST,
2199                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2200     return;
2201   }
2202 
2203   RespondWithCommandStatus(pwemb::OpCode::REMOTE_NAME_REQUEST,
2204                            pwemb::StatusCode::SUCCESS);
2205 
2206   auto response =
2207       hci::EventPacket::New<pwemb::RemoteNameRequestCompleteEventWriter>(
2208           hci_spec::kRemoteNameRequestCompleteEventCode);
2209   auto view = response.view_t();
2210   view.status().Write(pwemb::StatusCode::SUCCESS);
2211   view.bd_addr().CopyFrom(params.bd_addr());
2212   std::strncpy(
2213       reinterpret_cast<char*>(view.remote_name().BackingStorage().data()),
2214       peer->name().c_str(),
2215       view.remote_name().SizeInBytes());
2216   SendEvent(hci_spec::kRemoteNameRequestCompleteEventCode, &response);
2217 }
2218 
OnReadRemoteSupportedFeaturesCommandReceived(const pwemb::ReadRemoteSupportedFeaturesCommandView & params)2219 void FakeController::OnReadRemoteSupportedFeaturesCommandReceived(
2220     const pwemb::ReadRemoteSupportedFeaturesCommandView& params) {
2221   RespondWithCommandStatus(pwemb::OpCode::READ_REMOTE_SUPPORTED_FEATURES,
2222                            pwemb::StatusCode::SUCCESS);
2223 
2224   auto response = hci::EventPacket::New<
2225       pwemb::ReadRemoteSupportedFeaturesCompleteEventWriter>(
2226       hci_spec::kReadRemoteSupportedFeaturesCompleteEventCode);
2227   auto view = response.view_t();
2228   view.status().Write(pwemb::StatusCode::SUCCESS);
2229   view.connection_handle().Write(params.connection_handle().Read());
2230   view.lmp_features().BackingStorage().WriteUInt(settings_.lmp_features_page0);
2231   SendCommandChannelPacket(response.data());
2232 }
2233 
OnReadRemoteVersionInfoCommandReceived(const pwemb::ReadRemoteVersionInfoCommandView & params)2234 void FakeController::OnReadRemoteVersionInfoCommandReceived(
2235     const pwemb::ReadRemoteVersionInfoCommandView& params) {
2236   RespondWithCommandStatus(pwemb::OpCode::READ_REMOTE_VERSION_INFO,
2237                            pwemb::StatusCode::SUCCESS);
2238   auto response =
2239       hci::EventPacket::New<pwemb::ReadRemoteVersionInfoCompleteEventWriter>(
2240           hci_spec::kReadRemoteVersionInfoCompleteEventCode);
2241   auto view = response.view_t();
2242   view.status().Write(pwemb::StatusCode::SUCCESS);
2243   view.connection_handle().CopyFrom(params.connection_handle());
2244   view.version().Write(pwemb::CoreSpecificationVersion::V4_2);
2245   view.company_identifier().Write(0xFFFF);  // anything
2246   view.subversion().Write(0xADDE);          // anything
2247   SendCommandChannelPacket(response.data());
2248 }
2249 
OnReadRemoteExtendedFeaturesCommandReceived(const pwemb::ReadRemoteExtendedFeaturesCommandView & params)2250 void FakeController::OnReadRemoteExtendedFeaturesCommandReceived(
2251     const pwemb::ReadRemoteExtendedFeaturesCommandView& params) {
2252   auto response = hci::EventPacket::New<
2253       pwemb::ReadRemoteExtendedFeaturesCompleteEventWriter>(
2254       hci_spec::kReadRemoteExtendedFeaturesCompleteEventCode);
2255   auto view = response.view_t();
2256 
2257   switch (params.page_number().Read()) {
2258     case 1: {
2259       view.lmp_features().BackingStorage().WriteUInt(
2260           settings_.lmp_features_page1);
2261       break;
2262     }
2263     case 2: {
2264       view.lmp_features().BackingStorage().WriteUInt(
2265           settings_.lmp_features_page2);
2266       break;
2267     }
2268     default: {
2269       RespondWithCommandStatus(
2270           pwemb::OpCode::READ_REMOTE_EXTENDED_FEATURES,
2271           pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2272       return;
2273     }
2274   }
2275 
2276   RespondWithCommandStatus(pwemb::OpCode::READ_REMOTE_EXTENDED_FEATURES,
2277                            pwemb::StatusCode::SUCCESS);
2278   view.page_number().CopyFrom(params.page_number());
2279   view.max_page_number().Write(3);
2280   view.connection_handle().CopyFrom(params.connection_handle());
2281   view.status().Write(pwemb::StatusCode::SUCCESS);
2282   SendCommandChannelPacket(response.data());
2283 }
2284 
OnAuthenticationRequestedCommandReceived(const pwemb::AuthenticationRequestedCommandView & params)2285 void FakeController::OnAuthenticationRequestedCommandReceived(
2286     const pwemb::AuthenticationRequestedCommandView& params) {
2287   hci_spec::ConnectionHandle handle = params.connection_handle().Read();
2288   FakePeer* peer = FindByConnHandle(handle);
2289   if (!peer) {
2290     RespondWithCommandStatus(pwemb::OpCode::AUTHENTICATION_REQUESTED,
2291                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2292     return;
2293   }
2294 
2295   RespondWithCommandStatus(pwemb::OpCode::AUTHENTICATION_REQUESTED,
2296                            pwemb::StatusCode::SUCCESS);
2297 
2298   auto event = hci::EventPacket::New<pwemb::LinkKeyRequestEventWriter>(
2299       hci_spec::kLinkKeyRequestEventCode);
2300   event.view_t().bd_addr().CopyFrom(peer->address_.value().view());
2301   SendCommandChannelPacket(event.data());
2302 }
2303 
OnLinkKeyRequestReplyCommandReceived(const pwemb::LinkKeyRequestReplyCommandView & params)2304 void FakeController::OnLinkKeyRequestReplyCommandReceived(
2305     const pwemb::LinkKeyRequestReplyCommandView& params) {
2306   DeviceAddress peer_address(DeviceAddress::Type::kBREDR,
2307                              DeviceAddressBytes(params.bd_addr()));
2308   FakePeer* peer = FindPeer(peer_address);
2309   if (!peer) {
2310     RespondWithCommandStatus(pwemb::OpCode::LINK_KEY_REQUEST_REPLY,
2311                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2312     return;
2313   }
2314 
2315   RespondWithCommandStatus(pwemb::OpCode::LINK_KEY_REQUEST_REPLY,
2316                            pwemb::StatusCode::SUCCESS);
2317   RespondWithCommandComplete(pwemb::OpCode::LINK_KEY_REQUEST_REPLY,
2318                              pwemb::StatusCode::SUCCESS);
2319 
2320   PW_CHECK(!peer->logical_links().empty());
2321   for (auto& conn_handle : peer->logical_links()) {
2322     auto event =
2323         hci::EventPacket::New<pwemb::AuthenticationCompleteEventWriter>(
2324             hci_spec::kAuthenticationCompleteEventCode);
2325     event.view_t().status().Write(pwemb::StatusCode::SUCCESS);
2326     event.view_t().connection_handle().Write(conn_handle);
2327     SendCommandChannelPacket(event.data());
2328   }
2329 }
2330 
OnLinkKeyRequestNegativeReplyCommandReceived(const pwemb::LinkKeyRequestNegativeReplyCommandView & params)2331 void FakeController::OnLinkKeyRequestNegativeReplyCommandReceived(
2332     const pwemb::LinkKeyRequestNegativeReplyCommandView& params) {
2333   FakePeer* peer = FindPeer(DeviceAddress(
2334       DeviceAddress::Type::kBREDR, DeviceAddressBytes(params.bd_addr())));
2335   if (!peer) {
2336     RespondWithCommandStatus(pwemb::OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY,
2337                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2338     return;
2339   }
2340   RespondWithCommandStatus(pwemb::OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY,
2341                            pwemb::StatusCode::SUCCESS);
2342 
2343   auto event = hci::EventPacket::New<pwemb::IoCapabilityRequestEventWriter>(
2344       hci_spec::kIOCapabilityRequestEventCode);
2345   event.view_t().bd_addr().CopyFrom(params.bd_addr());
2346   SendCommandChannelPacket(event.data());
2347 }
2348 
OnIOCapabilityRequestReplyCommand(const pwemb::IoCapabilityRequestReplyCommandView & params)2349 void FakeController::OnIOCapabilityRequestReplyCommand(
2350     const pwemb::IoCapabilityRequestReplyCommandView& params) {
2351   RespondWithCommandStatus(pwemb::OpCode::IO_CAPABILITY_REQUEST_REPLY,
2352                            pwemb::StatusCode::SUCCESS);
2353 
2354   auto io_response =
2355       hci::EventPacket::New<pwemb::IoCapabilityResponseEventWriter>(
2356           hci_spec::kIOCapabilityResponseEventCode);
2357   io_response.view_t().bd_addr().CopyFrom(params.bd_addr());
2358   io_response.view_t().io_capability().Write(
2359       pwemb::IoCapability::NO_INPUT_NO_OUTPUT);
2360   io_response.view_t().oob_data_present().Write(
2361       pwemb::GenericPresenceParam::NOT_PRESENT);
2362   io_response.view_t().authentication_requirements().Write(
2363       pwemb::AuthenticationRequirements::GENERAL_BONDING);
2364   SendCommandChannelPacket(io_response.data());
2365 
2366   // Event type based on |params.io_capability| and |io_response.io_capability|.
2367   auto event = hci::EventPacket::New<pwemb::UserConfirmationRequestEventWriter>(
2368       hci_spec::kUserConfirmationRequestEventCode);
2369   event.view_t().bd_addr().CopyFrom(params.bd_addr());
2370   event.view_t().numeric_value().Write(0);
2371   SendCommandChannelPacket(event.data());
2372 }
2373 
OnUserConfirmationRequestReplyCommand(const pwemb::UserConfirmationRequestReplyCommandView & params)2374 void FakeController::OnUserConfirmationRequestReplyCommand(
2375     const pwemb::UserConfirmationRequestReplyCommandView& params) {
2376   FakePeer* peer = FindPeer(DeviceAddress(
2377       DeviceAddress::Type::kBREDR, DeviceAddressBytes(params.bd_addr())));
2378   if (!peer) {
2379     RespondWithCommandStatus(pwemb::OpCode::USER_CONFIRMATION_REQUEST_REPLY,
2380                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2381     return;
2382   }
2383 
2384   RespondWithCommandStatus(pwemb::OpCode::USER_CONFIRMATION_REQUEST_REPLY,
2385                            pwemb::StatusCode::SUCCESS);
2386 
2387   auto pairing_event =
2388       hci::EventPacket::New<pwemb::SimplePairingCompleteEventWriter>(
2389           hci_spec::kSimplePairingCompleteEventCode);
2390   pairing_event.view_t().bd_addr().CopyFrom(params.bd_addr());
2391   pairing_event.view_t().status().Write(pwemb::StatusCode::SUCCESS);
2392   SendCommandChannelPacket(pairing_event.data());
2393 
2394   auto link_key_event =
2395       hci::EventPacket::New<pwemb::LinkKeyNotificationEventWriter>(
2396           hci_spec::kLinkKeyNotificationEventCode);
2397   auto link_key_view = link_key_event.view_t();
2398   link_key_view.bd_addr().CopyFrom(params.bd_addr());
2399   uint8_t key[] = {0xc0,
2400                    0xde,
2401                    0xfa,
2402                    0x57,
2403                    0x4b,
2404                    0xad,
2405                    0xf0,
2406                    0x0d,
2407                    0xa7,
2408                    0x60,
2409                    0x06,
2410                    0x1e,
2411                    0xca,
2412                    0x1e,
2413                    0xca,
2414                    0xfe};
2415   link_key_view.link_key().value().BackingStorage().CopyFrom(
2416       ::emboss::support::ReadOnlyContiguousBuffer(key, sizeof(key)),
2417       sizeof(key));
2418   link_key_view.key_type().Write(
2419       pwemb::KeyType::UNAUTHENTICATED_COMBINATION_FROM_P192);
2420   SendCommandChannelPacket(link_key_event.data());
2421 
2422   PW_CHECK(!peer->logical_links().empty());
2423   for (auto& conn_handle : peer->logical_links()) {
2424     auto event =
2425         hci::EventPacket::New<pwemb::AuthenticationCompleteEventWriter>(
2426             hci_spec::kAuthenticationCompleteEventCode);
2427     event.view_t().status().Write(pwemb::StatusCode::SUCCESS);
2428     event.view_t().connection_handle().Write(conn_handle);
2429     SendCommandChannelPacket(event.data());
2430   }
2431 }
2432 
OnUserConfirmationRequestNegativeReplyCommand(const pwemb::UserConfirmationRequestNegativeReplyCommandView & params)2433 void FakeController::OnUserConfirmationRequestNegativeReplyCommand(
2434     const pwemb::UserConfirmationRequestNegativeReplyCommandView& params) {
2435   FakePeer* peer = FindPeer(DeviceAddress(
2436       DeviceAddress::Type::kBREDR, DeviceAddressBytes(params.bd_addr())));
2437   if (!peer) {
2438     RespondWithCommandStatus(
2439         pwemb::OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY,
2440         pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2441     return;
2442   }
2443 
2444   RespondWithCommandStatus(
2445       pwemb::OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY,
2446       pwemb::StatusCode::SUCCESS);
2447   RespondWithCommandComplete(
2448       pwemb::OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY,
2449       pwemb::StatusCode::SUCCESS);
2450 
2451   auto pairing_event =
2452       hci::EventPacket::New<pwemb::SimplePairingCompleteEventWriter>(
2453           hci_spec::kSimplePairingCompleteEventCode);
2454   pairing_event.view_t().bd_addr().CopyFrom(params.bd_addr());
2455   pairing_event.view_t().status().Write(
2456       pwemb::StatusCode::AUTHENTICATION_FAILURE);
2457   SendCommandChannelPacket(pairing_event.data());
2458 }
2459 
OnSetConnectionEncryptionCommand(const pwemb::SetConnectionEncryptionCommandView & params)2460 void FakeController::OnSetConnectionEncryptionCommand(
2461     const pwemb::SetConnectionEncryptionCommandView& params) {
2462   RespondWithCommandStatus(pwemb::OpCode::SET_CONNECTION_ENCRYPTION,
2463                            pwemb::StatusCode::SUCCESS);
2464   SendEncryptionChangeEvent(
2465       params.connection_handle().Read(),
2466       pwemb::StatusCode::SUCCESS,
2467       pwemb::EncryptionStatus::ON_WITH_E0_FOR_BREDR_OR_AES_FOR_LE);
2468 }
2469 
OnReadEncryptionKeySizeCommand(const pwemb::ReadEncryptionKeySizeCommandView & params)2470 void FakeController::OnReadEncryptionKeySizeCommand(
2471     const pwemb::ReadEncryptionKeySizeCommandView& params) {
2472   auto response = hci::EventPacket::New<
2473       pwemb::ReadEncryptionKeySizeCommandCompleteEventWriter>(
2474       hci_spec::kCommandCompleteEventCode);
2475   auto view = response.view_t();
2476   view.status().Write(pwemb::StatusCode::SUCCESS);
2477   view.connection_handle().Write(params.connection_handle().Read());
2478   view.key_size().Write(16);
2479   RespondWithCommandComplete(pwemb::OpCode::READ_ENCRYPTION_KEY_SIZE,
2480                              &response);
2481 }
2482 
OnEnhancedAcceptSynchronousConnectionRequestCommand(const pwemb::EnhancedAcceptSynchronousConnectionRequestCommandView & params)2483 void FakeController::OnEnhancedAcceptSynchronousConnectionRequestCommand(
2484     const pwemb::EnhancedAcceptSynchronousConnectionRequestCommandView&
2485         params) {
2486   DeviceAddress peer_address(DeviceAddress::Type::kBREDR,
2487                              DeviceAddressBytes(params.bd_addr()));
2488   FakePeer* peer = FindPeer(peer_address);
2489   if (!peer || !peer->last_connection_request_link_type().has_value()) {
2490     RespondWithCommandStatus(
2491         pwemb::OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST,
2492         pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2493     return;
2494   }
2495 
2496   RespondWithCommandStatus(
2497       pwemb::OpCode::ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION_REQUEST,
2498       pwemb::StatusCode::SUCCESS);
2499 
2500   hci_spec::ConnectionHandle sco_handle = ++next_conn_handle_;
2501   peer->AddLink(sco_handle);
2502 
2503   auto packet =
2504       hci::EventPacket::New<pwemb::SynchronousConnectionCompleteEventWriter>(
2505           hci_spec::kSynchronousConnectionCompleteEventCode);
2506   auto view = packet.view_t();
2507   view.status().Write(pwemb::StatusCode::SUCCESS);
2508   view.connection_handle().Write(sco_handle);
2509   view.bd_addr().CopyFrom(peer->address().value().view());
2510   view.link_type().Write(peer->last_connection_request_link_type().value());
2511   view.transmission_interval().Write(1);
2512   view.retransmission_window().Write(2);
2513   view.rx_packet_length().Write(3);
2514   view.tx_packet_length().Write(4);
2515   view.air_mode().Write(params.connection_parameters()
2516                             .transmit_coding_format()
2517                             .coding_format()
2518                             .Read());
2519   SendCommandChannelPacket(packet.data());
2520 }
2521 
OnEnhancedSetupSynchronousConnectionCommand(const pwemb::EnhancedSetupSynchronousConnectionCommandView & params)2522 void FakeController::OnEnhancedSetupSynchronousConnectionCommand(
2523     const pwemb::EnhancedSetupSynchronousConnectionCommandView& params) {
2524   const hci_spec::ConnectionHandle acl_handle =
2525       params.connection_handle().Read();
2526   FakePeer* peer = FindByConnHandle(acl_handle);
2527   if (!peer) {
2528     RespondWithCommandStatus(
2529         pwemb::OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION,
2530         pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2531     return;
2532   }
2533 
2534   RespondWithCommandStatus(pwemb::OpCode::ENHANCED_SETUP_SYNCHRONOUS_CONNECTION,
2535                            pwemb::StatusCode::SUCCESS);
2536 
2537   hci_spec::ConnectionHandle sco_handle = ++next_conn_handle_;
2538   peer->AddLink(sco_handle);
2539 
2540   auto packet =
2541       hci::EventPacket::New<pwemb::SynchronousConnectionCompleteEventWriter>(
2542           hci_spec::kSynchronousConnectionCompleteEventCode);
2543   auto view = packet.view_t();
2544   view.status().Write(pwemb::StatusCode::SUCCESS);
2545   view.connection_handle().Write(sco_handle);
2546   view.bd_addr().CopyFrom(peer->address().value().view());
2547   view.link_type().Write(pwemb::LinkType::ESCO);
2548   view.transmission_interval().Write(1);
2549   view.retransmission_window().Write(2);
2550   view.rx_packet_length().Write(3);
2551   view.tx_packet_length().Write(4);
2552   view.air_mode().Write(params.connection_parameters()
2553                             .transmit_coding_format()
2554                             .coding_format()
2555                             .Read());
2556   SendCommandChannelPacket(packet.data());
2557 }
2558 
OnLEReadRemoteFeaturesCommand(const pwemb::LEReadRemoteFeaturesCommandView & params)2559 void FakeController::OnLEReadRemoteFeaturesCommand(
2560     const pwemb::LEReadRemoteFeaturesCommandView& params) {
2561   if (le_read_remote_features_cb_) {
2562     le_read_remote_features_cb_();
2563   }
2564 
2565   const hci_spec::ConnectionHandle handle = params.connection_handle().Read();
2566   FakePeer* peer = FindByConnHandle(handle);
2567   if (!peer) {
2568     RespondWithCommandStatus(pwemb::OpCode::LE_READ_REMOTE_FEATURES,
2569                              pwemb::StatusCode::UNKNOWN_CONNECTION_ID);
2570     return;
2571   }
2572 
2573   RespondWithCommandStatus(pwemb::OpCode::LE_READ_REMOTE_FEATURES,
2574                            pwemb::StatusCode::SUCCESS);
2575 
2576   auto response =
2577       hci::EventPacket::New<pwemb::LEReadRemoteFeaturesCompleteSubeventWriter>(
2578           hci_spec::kLEMetaEventCode);
2579   auto view = response.view_t();
2580   view.le_meta_event().subevent_code().Write(
2581       hci_spec::kLEReadRemoteFeaturesCompleteSubeventCode);
2582   view.connection_handle().Write(handle);
2583   view.status().Write(pwemb::StatusCode::SUCCESS);
2584   view.le_features().BackingStorage().WriteUInt(peer->le_features());
2585   SendCommandChannelPacket(response.data());
2586 }
2587 
OnLEStartEncryptionCommand(const pwemb::LEEnableEncryptionCommandView & params)2588 void FakeController::OnLEStartEncryptionCommand(
2589     const pwemb::LEEnableEncryptionCommandView& params) {
2590   RespondWithCommandStatus(pwemb::OpCode::LE_START_ENCRYPTION,
2591                            pwemb::StatusCode::SUCCESS);
2592   SendEncryptionChangeEvent(
2593       params.connection_handle().Read(),
2594       pwemb::StatusCode::SUCCESS,
2595       pwemb::EncryptionStatus::ON_WITH_E0_FOR_BREDR_OR_AES_FOR_LE);
2596 }
2597 
OnWriteSynchronousFlowControlEnableCommand(const pwemb::WriteSynchronousFlowControlEnableCommandView & params)2598 void FakeController::OnWriteSynchronousFlowControlEnableCommand(
2599     [[maybe_unused]] const pwemb::WriteSynchronousFlowControlEnableCommandView&
2600         params) {
2601   if (!settings_.SupportedCommandsView()
2602            .write_synchronous_flow_control_enable()
2603            .Read()) {
2604     RespondWithCommandComplete(
2605         pwemb::OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE,
2606         pwemb::StatusCode::UNKNOWN_COMMAND);
2607     return;
2608   }
2609   RespondWithCommandComplete(
2610       pwemb::OpCode::WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE,
2611       pwemb::StatusCode::SUCCESS);
2612 }
2613 
OnLESetAdvertisingSetRandomAddress(const pwemb::LESetAdvertisingSetRandomAddressCommandView & params)2614 void FakeController::OnLESetAdvertisingSetRandomAddress(
2615     const pwemb::LESetAdvertisingSetRandomAddressCommandView& params) {
2616   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
2617 
2618   if (!IsValidAdvertisingHandle(handle)) {
2619     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
2620     RespondWithCommandComplete(
2621         pwemb::OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS,
2622         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2623     return;
2624   }
2625 
2626   if (extended_advertising_states_.count(handle) == 0) {
2627     bt_log(INFO,
2628            "fake-hci",
2629            "unknown advertising handle (%d), "
2630            "use HCI_LE_Set_Extended_Advertising_Parameters to create one first",
2631            handle);
2632     RespondWithCommandComplete(
2633         pwemb::OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS,
2634         pwemb::StatusCode::COMMAND_DISALLOWED);
2635     return;
2636   }
2637 
2638   LEAdvertisingState& state = extended_advertising_states_[handle];
2639   if (state.properties.connectable && state.enabled) {
2640     bt_log(
2641         INFO,
2642         "fake-hci",
2643         "cannot set LE random address while connectable advertising enabled");
2644     RespondWithCommandComplete(
2645         pwemb::OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS,
2646         pwemb::StatusCode::COMMAND_DISALLOWED);
2647     return;
2648   }
2649 
2650   state.random_address =
2651       DeviceAddress(DeviceAddress::Type::kLERandom,
2652                     DeviceAddressBytes(params.random_address()));
2653   RespondWithCommandComplete(
2654       pwemb::OpCode::LE_SET_ADVERTISING_SET_RANDOM_ADDRESS,
2655       pwemb::StatusCode::SUCCESS);
2656 }
2657 
OnLESetExtendedAdvertisingParameters(const pwemb::LESetExtendedAdvertisingParametersV1CommandView & params)2658 void FakeController::OnLESetExtendedAdvertisingParameters(
2659     const pwemb::LESetExtendedAdvertisingParametersV1CommandView& params) {
2660   if (!EnableExtendedAdvertising()) {
2661     bt_log(
2662         INFO,
2663         "fake-hci",
2664         "extended advertising command rejected, legacy advertising is in use");
2665     RespondWithCommandStatus(
2666         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2667         pwemb::StatusCode::COMMAND_DISALLOWED);
2668     return;
2669   }
2670 
2671   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
2672 
2673   if (!IsValidAdvertisingHandle(handle)) {
2674     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
2675     RespondWithCommandComplete(
2676         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2677         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2678     return;
2679   }
2680 
2681   // we cannot set parameters while an advertising set is currently enabled
2682   if (extended_advertising_states_.count(handle) != 0) {
2683     if (extended_advertising_states_[handle].enabled) {
2684       bt_log(INFO,
2685              "fake-hci",
2686              "cannot set parameters while advertising set is enabled");
2687       RespondWithCommandComplete(
2688           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2689           pwemb::StatusCode::COMMAND_DISALLOWED);
2690       return;
2691     }
2692   }
2693 
2694   // ensure we can allocate memory for this advertising set if not already
2695   // present
2696   if (extended_advertising_states_.count(handle) == 0 &&
2697       extended_advertising_states_.size() >= num_supported_advertising_sets()) {
2698     bt_log(INFO,
2699            "fake-hci",
2700            "no available memory for new advertising set, handle: %d",
2701            handle);
2702     RespondWithCommandComplete(
2703         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2704         pwemb::StatusCode::MEMORY_CAPACITY_EXCEEDED);
2705     return;
2706   }
2707 
2708   // ensure we have a valid bit combination in the advertising event properties
2709   bool connectable = params.advertising_event_properties().connectable().Read();
2710   bool scannable = params.advertising_event_properties().scannable().Read();
2711   bool directed = params.advertising_event_properties().directed().Read();
2712   bool high_duty_cycle_directed_connectable =
2713       params.advertising_event_properties()
2714           .high_duty_cycle_directed_connectable()
2715           .Read();
2716   bool use_legacy_pdus =
2717       params.advertising_event_properties().use_legacy_pdus().Read();
2718   bool anonymous_advertising =
2719       params.advertising_event_properties().anonymous_advertising().Read();
2720   bool include_tx_power =
2721       params.advertising_event_properties().include_tx_power().Read();
2722 
2723   std::optional<pwemb::LEAdvertisingType> adv_type;
2724   if (use_legacy_pdus) {
2725     // ADV_IND
2726     if (!high_duty_cycle_directed_connectable && !directed && scannable &&
2727         connectable) {
2728       adv_type = pwemb::LEAdvertisingType::CONNECTABLE_AND_SCANNABLE_UNDIRECTED;
2729     }
2730 
2731     // ADV_DIRECT_IND
2732     if (!high_duty_cycle_directed_connectable && directed && !scannable &&
2733         connectable) {
2734       adv_type = pwemb::LEAdvertisingType::CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED;
2735     }
2736 
2737     // ADV_DIRECT_IND
2738     if (high_duty_cycle_directed_connectable && directed && !scannable &&
2739         connectable) {
2740       adv_type = pwemb::LEAdvertisingType::CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED;
2741     }
2742 
2743     // ADV_SCAN_IND
2744     if (!high_duty_cycle_directed_connectable && !directed && scannable &&
2745         !connectable) {
2746       adv_type = pwemb::LEAdvertisingType::SCANNABLE_UNDIRECTED;
2747     }
2748 
2749     // ADV_NONCONN_IND
2750     if (!high_duty_cycle_directed_connectable && !directed && !scannable &&
2751         !connectable) {
2752       adv_type = pwemb::LEAdvertisingType::NOT_CONNECTABLE_UNDIRECTED;
2753     }
2754 
2755     if (!adv_type) {
2756       bt_log(INFO,
2757              "fake-hci",
2758              "invalid bit combination: %s",
2759              params.advertising_event_properties()
2760                  .BackingStorage()
2761                  .ToString<std::string>()
2762                  .c_str());
2763       RespondWithCommandComplete(
2764           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2765           pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2766       return;
2767     }
2768 
2769     // Core spec Volume 4, Part E, Section 7.8.53: if legacy advertising PDUs
2770     // are being used, the Primary_Advertising_PHY shall indicate the LE 1M PHY.
2771     if (params.primary_advertising_phy().Read() !=
2772         pwemb::LEPrimaryAdvertisingPHY::LE_1M) {
2773       bt_log(INFO,
2774              "fake-hci",
2775              "only legacy pdus are supported, requires advertising on 1M PHY");
2776       RespondWithCommandComplete(
2777           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2778           pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2779       return;
2780     }
2781   } else {
2782     // Core spec Volume 4, Part E, Section 7.8.53: If extended advertising PDU
2783     // types are being used (bit 4 = 0) then: The advertisement shall not be
2784     // both connectable and scannable.
2785     if (connectable && scannable) {
2786       bt_log(
2787           INFO,
2788           "fake-hci",
2789           "extended advertising pdus can't be both connectable and scannable");
2790       RespondWithCommandComplete(
2791           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2792           pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2793       return;
2794     }
2795 
2796     // Core spec Volume 4, Part E, Section 7.8.53: If extended advertising PDU
2797     // types are being used (bit 4 = 0) then: High duty cycle directed
2798     // connectable advertising (≤ 3.75 ms advertising interval) shall not be
2799     // used (bit 3 = 0).
2800     if (high_duty_cycle_directed_connectable) {
2801       bt_log(INFO,
2802              "fake-hci",
2803              "extended advertising pdus can't use the high duty cycle directed "
2804              "connectable type");
2805       RespondWithCommandComplete(
2806           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2807           pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2808       return;
2809     }
2810   }
2811 
2812   // In case there is an error below, we want to reject all parameters instead
2813   // of storing a dead state and taking up an advertising handle. Avoid creating
2814   // the LEAdvertisingState directly in the map and add it in only once we have
2815   // made sure all is good.
2816   LEAdvertisingState state;
2817   state.properties.connectable = connectable;
2818   state.properties.scannable = scannable;
2819   state.properties.directed = directed;
2820   state.properties.high_duty_cycle_directed_connectable =
2821       high_duty_cycle_directed_connectable;
2822   state.properties.use_legacy_pdus = use_legacy_pdus;
2823   state.properties.anonymous_advertising = anonymous_advertising;
2824   state.properties.include_tx_power = include_tx_power;
2825 
2826   state.own_address_type = params.own_address_type().Read();
2827   state.interval_min = params.primary_advertising_interval_min().Read();
2828   state.interval_max = params.primary_advertising_interval_max().Read();
2829 
2830   if (state.interval_min >= state.interval_max) {
2831     bt_log(INFO,
2832            "fake-hci",
2833            "advertising interval min (%d) not strictly less than max (%d)",
2834            state.interval_min,
2835            state.interval_max);
2836     RespondWithCommandComplete(
2837         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2838         pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2839     return;
2840   }
2841 
2842   if (state.interval_min < hci_spec::kLEExtendedAdvertisingIntervalMin) {
2843     bt_log(INFO,
2844            "fake-hci",
2845            "advertising interval min (%d) less than spec min (%dstate.)",
2846            state.interval_min,
2847            hci_spec::kLEAdvertisingIntervalMin);
2848     RespondWithCommandComplete(
2849         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2850         pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2851     return;
2852   }
2853 
2854   if (state.interval_max > hci_spec::kLEExtendedAdvertisingIntervalMax) {
2855     bt_log(INFO,
2856            "fake-hci",
2857            "advertising interval max (%d) greater than spec max (%d)",
2858            state.interval_max,
2859            hci_spec::kLEAdvertisingIntervalMax);
2860     RespondWithCommandComplete(
2861         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2862         pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
2863     return;
2864   }
2865 
2866   uint8_t advertising_channels =
2867       params.primary_advertising_channel_map().BackingStorage().ReadUInt();
2868   if (!advertising_channels) {
2869     bt_log(INFO,
2870            "fake-hci",
2871            "at least one bit must be set in primary advertising channel map");
2872     RespondWithCommandComplete(
2873         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2874         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2875     return;
2876   }
2877 
2878   int8_t advertising_tx_power = params.advertising_tx_power().Read();
2879   if (advertising_tx_power !=
2880           hci_spec::kLEExtendedAdvertisingTxPowerNoPreference &&
2881       (advertising_tx_power < hci_spec::kLEAdvertisingTxPowerMin ||
2882        advertising_tx_power > hci_spec::kLEAdvertisingTxPowerMax)) {
2883     bt_log(INFO,
2884            "fake-hci",
2885            "advertising tx power out of range: %d",
2886            advertising_tx_power);
2887     RespondWithCommandComplete(
2888         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1,
2889         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2890     return;
2891   }
2892 
2893   // write full state back only at the end (we don't have a reference because we
2894   // only want to write if there are no errors)
2895   extended_advertising_states_[handle] = state;
2896 
2897   auto packet = hci::EventPacket::New<
2898       pwemb::LESetExtendedAdvertisingParametersCommandCompleteEventWriter>(
2899       hci_spec::kCommandCompleteEventCode);
2900   auto view = packet.view_t();
2901   view.status().Write(pwemb::StatusCode::SUCCESS);
2902   view.selected_tx_power().Write(hci_spec::kLEAdvertisingTxPowerMax);
2903   RespondWithCommandComplete(
2904       pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS_V1, &packet);
2905   NotifyAdvertisingState();
2906 }
2907 
OnLESetExtendedAdvertisingData(const pwemb::LESetExtendedAdvertisingDataCommandView & params)2908 void FakeController::OnLESetExtendedAdvertisingData(
2909     const pwemb::LESetExtendedAdvertisingDataCommandView& params) {
2910   if (!EnableExtendedAdvertising()) {
2911     bt_log(
2912         INFO,
2913         "fake-hci",
2914         "extended advertising command rejected, legacy advertising is in use");
2915     RespondWithCommandStatus(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2916                              pwemb::StatusCode::COMMAND_DISALLOWED);
2917     return;
2918   }
2919 
2920   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
2921 
2922   if (!IsValidAdvertisingHandle(handle)) {
2923     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
2924     RespondWithCommandComplete(
2925         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2926         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2927     return;
2928   }
2929 
2930   if (extended_advertising_states_.count(handle) == 0) {
2931     bt_log(INFO,
2932            "fake-hci",
2933            "advertising handle (%d) maps to an unknown advertising set",
2934            handle);
2935     RespondWithCommandComplete(
2936         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2937         pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
2938     return;
2939   }
2940 
2941   LEAdvertisingState& state = extended_advertising_states_[handle];
2942 
2943   // removing advertising data entirely doesn't require us to check for error
2944   // conditions
2945   size_t advertising_data_length = params.advertising_data_length().Read();
2946   if (advertising_data_length == 0) {
2947     state.data_length = 0;
2948     std::memset(state.data, 0, sizeof(state.data));
2949     RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2950                                pwemb::StatusCode::SUCCESS);
2951     NotifyAdvertisingState();
2952     return;
2953   }
2954 
2955   // directed advertising doesn't support advertising data
2956   if (state.IsDirectedAdvertising()) {
2957     bt_log(INFO,
2958            "fake-hci",
2959            "cannot provide advertising data when using directed advertising");
2960     RespondWithCommandComplete(
2961         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2962         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2963     return;
2964   }
2965 
2966   if (params.operation().Read() ==
2967       pwemb::LESetExtendedAdvDataOp::UNCHANGED_DATA) {
2968     RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2969                                pwemb::StatusCode::SUCCESS);
2970     return;
2971   }
2972 
2973   // For backwards compatibility with older devices, we support both legacy and
2974   // extended advertising pdus. Each pdu type has its own size limits.
2975   if (state.properties.use_legacy_pdus &&
2976       advertising_data_length > hci_spec::kMaxLEAdvertisingDataLength) {
2977     bt_log(INFO,
2978            "fake-hci",
2979            "data length (%zu bytes) larger than legacy PDU size limit",
2980            advertising_data_length);
2981     RespondWithCommandComplete(
2982         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2983         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2984     return;
2985   }
2986 
2987   if (!state.properties.use_legacy_pdus &&
2988       advertising_data_length > pwemb::LESetExtendedAdvertisingDataCommand::
2989                                     advertising_data_length_max()) {
2990     bt_log(INFO,
2991            "fake-hci",
2992            "data length (%zu bytes) larger than individual extended PDU size "
2993            "limit",
2994            advertising_data_length);
2995     RespondWithCommandComplete(
2996         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
2997         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
2998     return;
2999   }
3000 
3001   if (!state.properties.use_legacy_pdus &&
3002       state.data_length + advertising_data_length >
3003           max_advertising_data_length_) {
3004     bt_log(INFO,
3005            "fake-hci",
3006            "data length (%zu bytes) larger than total extended PDU size limit",
3007            advertising_data_length);
3008     RespondWithCommandComplete(
3009         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
3010         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3011     return;
3012   }
3013 
3014   if (state.properties.use_legacy_pdus ||
3015       params.operation().Read() == pwemb::LESetExtendedAdvDataOp::COMPLETE ||
3016       params.operation().Read() ==
3017           pwemb::LESetExtendedAdvDataOp::FIRST_FRAGMENT) {
3018     std::memcpy(state.data,
3019                 params.advertising_data().BackingStorage().data(),
3020                 advertising_data_length);
3021     state.data_length = static_cast<uint16_t>(advertising_data_length);
3022   } else {
3023     std::memcpy(state.data + state.data_length,
3024                 params.advertising_data().BackingStorage().data(),
3025                 advertising_data_length);
3026     state.data_length += advertising_data_length;
3027   }
3028 
3029   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_DATA,
3030                              pwemb::StatusCode::SUCCESS);
3031   NotifyAdvertisingState();
3032 }
3033 
OnLESetExtendedScanResponseData(const pwemb::LESetExtendedScanResponseDataCommandView & params)3034 void FakeController::OnLESetExtendedScanResponseData(
3035     const pwemb::LESetExtendedScanResponseDataCommandView& params) {
3036   if (!EnableExtendedAdvertising()) {
3037     bt_log(
3038         INFO,
3039         "fake-hci",
3040         "extended advertising command rejected, legacy advertising is in use");
3041     RespondWithCommandStatus(pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3042                              pwemb::StatusCode::COMMAND_DISALLOWED);
3043     return;
3044   }
3045 
3046   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
3047 
3048   if (!IsValidAdvertisingHandle(handle)) {
3049     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3050     RespondWithCommandComplete(
3051         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3052         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3053     return;
3054   }
3055 
3056   if (extended_advertising_states_.count(handle) == 0) {
3057     bt_log(INFO,
3058            "fake-hci",
3059            "advertising handle (%d) maps to an unknown advertising set",
3060            handle);
3061     RespondWithCommandComplete(
3062         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3063         pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3064     return;
3065   }
3066 
3067   LEAdvertisingState& state = extended_advertising_states_[handle];
3068 
3069   // removing scan response data entirely doesn't require us to check for error
3070   // conditions
3071   size_t scan_response_data_length = params.scan_response_data_length().Read();
3072   if (scan_response_data_length == 0) {
3073     state.scan_rsp_length = 0;
3074     std::memset(state.scan_rsp_data, 0, sizeof(state.scan_rsp_data));
3075     RespondWithCommandComplete(
3076         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3077         pwemb::StatusCode::SUCCESS);
3078     NotifyAdvertisingState();
3079     return;
3080   }
3081 
3082   // adding or changing scan response data, check for error conditions
3083   if (!state.properties.scannable) {
3084     bt_log(
3085         INFO,
3086         "fake-hci",
3087         "cannot provide scan response data for unscannable advertising types");
3088     RespondWithCommandComplete(
3089         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3090         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3091     return;
3092   }
3093 
3094   if (params.operation().Read() ==
3095       pwemb::LESetExtendedAdvDataOp::UNCHANGED_DATA) {
3096     RespondWithCommandComplete(
3097         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3098         pwemb::StatusCode::SUCCESS);
3099     return;
3100   }
3101 
3102   // For backwards compatibility with older devices, we support both legacy and
3103   // extended advertising pdus. Each pdu type has its own size limits.
3104   if (state.properties.use_legacy_pdus &&
3105       scan_response_data_length > hci_spec::kMaxLEAdvertisingDataLength) {
3106     bt_log(INFO,
3107            "fake-hci",
3108            "data length (%zu bytes) larger than legacy PDU size limit",
3109            scan_response_data_length);
3110     RespondWithCommandComplete(
3111         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3112         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3113     return;
3114   }
3115 
3116   if (!state.properties.use_legacy_pdus &&
3117       scan_response_data_length > pwemb::LESetExtendedAdvertisingDataCommand::
3118                                       advertising_data_length_max()) {
3119     bt_log(INFO,
3120            "fake-hci",
3121            "data length (%zu bytes) larger than individual extended PDU size "
3122            "limit",
3123            scan_response_data_length);
3124     RespondWithCommandComplete(
3125         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3126         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3127     return;
3128   }
3129 
3130   if (!state.properties.use_legacy_pdus &&
3131       state.scan_rsp_length + scan_response_data_length >
3132           max_advertising_data_length_) {
3133     bt_log(INFO,
3134            "fake-hci",
3135            "data length (%zu bytes) larger than total extended PDU size limit",
3136            scan_response_data_length);
3137     RespondWithCommandComplete(
3138         pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3139         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3140     return;
3141   }
3142 
3143   if (state.properties.use_legacy_pdus ||
3144       params.operation().Read() == pwemb::LESetExtendedAdvDataOp::COMPLETE ||
3145       params.operation().Read() ==
3146           pwemb::LESetExtendedAdvDataOp::FIRST_FRAGMENT) {
3147     std::memcpy(state.scan_rsp_data,
3148                 params.scan_response_data().BackingStorage().data(),
3149                 scan_response_data_length);
3150     state.scan_rsp_length = static_cast<uint16_t>(scan_response_data_length);
3151   } else {
3152     std::memcpy(state.scan_rsp_data + state.scan_rsp_length,
3153                 params.scan_response_data().BackingStorage().data(),
3154                 scan_response_data_length);
3155     state.scan_rsp_length += scan_response_data_length;
3156   }
3157 
3158   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_SCAN_RESPONSE_DATA,
3159                              pwemb::StatusCode::SUCCESS);
3160   NotifyAdvertisingState();
3161 }
3162 
OnLESetExtendedAdvertisingEnable(const pwemb::LESetExtendedAdvertisingEnableCommandView & params)3163 void FakeController::OnLESetExtendedAdvertisingEnable(
3164     const pwemb::LESetExtendedAdvertisingEnableCommandView& params) {
3165   if (!EnableExtendedAdvertising()) {
3166     bt_log(
3167         INFO,
3168         "fake-hci",
3169         "extended advertising command rejected, legacy advertising is in use");
3170     RespondWithCommandStatus(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3171                              pwemb::StatusCode::COMMAND_DISALLOWED);
3172     return;
3173   }
3174 
3175   uint8_t num_sets = params.num_sets().Read();
3176 
3177   // do some preliminary checks before making any state changes
3178   if (num_sets != 0) {
3179     std::unordered_set<hci_spec::AdvertisingHandle> handles;
3180 
3181     for (uint8_t i = 0; i < num_sets; i++) {
3182       hci_spec::AdvertisingHandle handle =
3183           params.data()[i].advertising_handle().Read();
3184 
3185       if (!IsValidAdvertisingHandle(handle)) {
3186         bt_log(
3187             ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3188         RespondWithCommandComplete(
3189             pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3190             pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3191         return;
3192       }
3193 
3194       // cannot have two array entries for the same advertising handle
3195       if (handles.count(handle) != 0) {
3196         bt_log(INFO,
3197                "fake-hci",
3198                "cannot refer to handle more than once (handle: %d)",
3199                handle);
3200         RespondWithCommandComplete(
3201             pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3202             pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3203         return;
3204       }
3205       handles.insert(handle);
3206 
3207       // cannot have instructions for an advertising handle we don't know about
3208       if (extended_advertising_states_.count(handle) == 0) {
3209         bt_log(INFO,
3210                "fake-hci",
3211                "cannot enable/disable an unknown handle (handle: %d)",
3212                handle);
3213         RespondWithCommandComplete(
3214             pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3215             pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3216         return;
3217       }
3218     }
3219   }
3220 
3221   if (params.enable().Read() == pwemb::GenericEnableParam::DISABLE) {
3222     if (num_sets == 0) {
3223       // if params.enable == kDisable and params.num_sets == 0, spec asks we
3224       // disable all
3225       for (auto& element : extended_advertising_states_) {
3226         element.second.enabled = false;
3227       }
3228     } else {
3229       for (int i = 0; i < num_sets; i++) {
3230         hci_spec::AdvertisingHandle handle =
3231             params.data()[i].advertising_handle().Read();
3232         extended_advertising_states_[handle].enabled = false;
3233       }
3234     }
3235 
3236     RespondWithCommandComplete(
3237         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3238         pwemb::StatusCode::SUCCESS);
3239     NotifyAdvertisingState();
3240     return;
3241   }
3242 
3243   // rest of the function deals with enabling advertising for a given set of
3244   // advertising sets
3245   PW_CHECK(params.enable().Read() == pwemb::GenericEnableParam::ENABLE);
3246 
3247   if (num_sets == 0) {
3248     bt_log(
3249         INFO, "fake-hci", "cannot enable with an empty advertising set list");
3250     RespondWithCommandComplete(
3251         pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3252         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3253     return;
3254   }
3255 
3256   for (uint8_t i = 0; i < num_sets; i++) {
3257     // FakeController currently doesn't support testing with duration and max
3258     // events. When those are used in the host, these checks will fail and
3259     // remind us to add the necessary code to FakeController.
3260     PW_CHECK(params.data()[i].duration().Read() == 0);
3261     PW_CHECK(params.data()[i].max_extended_advertising_events().Read() == 0);
3262 
3263     hci_spec::AdvertisingHandle handle =
3264         params.data()[i].advertising_handle().Read();
3265     LEAdvertisingState& state = extended_advertising_states_[handle];
3266 
3267     if (state.IsDirectedAdvertising() && state.data_length == 0) {
3268       bt_log(
3269           INFO,
3270           "fake-hci",
3271           "cannot enable type requiring advertising data without setting it");
3272       RespondWithCommandComplete(
3273           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3274           pwemb::StatusCode::COMMAND_DISALLOWED);
3275       return;
3276     }
3277 
3278     if (state.properties.scannable && state.scan_rsp_length == 0) {
3279       bt_log(INFO,
3280              "fake-hci",
3281              "cannot enable, requires scan response data but hasn't been set");
3282       RespondWithCommandComplete(
3283           pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3284           pwemb::StatusCode::COMMAND_DISALLOWED);
3285       return;
3286     }
3287 
3288     // TODO(fxbug.dev/42161900): if own address type is random, check that a
3289     // random address is set.
3290 
3291     state.enabled = true;
3292   }
3293 
3294   RespondWithCommandComplete(pwemb::OpCode::LE_SET_EXTENDED_ADVERTISING_ENABLE,
3295                              pwemb::StatusCode::SUCCESS);
3296   NotifyAdvertisingState();
3297 }
3298 
OnLEReadMaximumAdvertisingDataLength()3299 void FakeController::OnLEReadMaximumAdvertisingDataLength() {
3300   if (!settings_.SupportedCommandsView()
3301            .le_read_maximum_advertising_data_length()
3302            .Read()) {
3303     RespondWithCommandComplete(
3304         pwemb::OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH,
3305         pwemb::StatusCode::UNKNOWN_COMMAND);
3306   }
3307 
3308   auto response = hci::EventPacket::New<
3309       pwemb::LEReadMaximumAdvertisingDataLengthCommandCompleteEventWriter>(
3310       hci_spec::kCommandCompleteEventCode);
3311   auto view = response.view_t();
3312   view.status().Write(pwemb::StatusCode::SUCCESS);
3313   view.max_advertising_data_length().Write(max_advertising_data_length_);
3314   RespondWithCommandComplete(
3315       pwemb::OpCode::LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, &response);
3316 }
3317 
OnLEReadNumberOfSupportedAdvertisingSets()3318 void FakeController::OnLEReadNumberOfSupportedAdvertisingSets() {
3319   auto event = hci::EventPacket::New<
3320       pwemb::LEReadNumberOfSupportedAdvertisingSetsCommandCompleteEventWriter>(
3321       hci_spec::kCommandCompleteEventCode);
3322   auto view = event.view_t();
3323   view.status().Write(pwemb::StatusCode::SUCCESS);
3324   view.num_supported_advertising_sets().Write(num_supported_advertising_sets_);
3325   RespondWithCommandComplete(
3326       pwemb::OpCode::LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, &event);
3327 }
3328 
OnLERemoveAdvertisingSet(const pwemb::LERemoveAdvertisingSetCommandView & params)3329 void FakeController::OnLERemoveAdvertisingSet(
3330     const pwemb::LERemoveAdvertisingSetCommandView& params) {
3331   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
3332 
3333   if (!IsValidAdvertisingHandle(handle)) {
3334     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3335     RespondWithCommandComplete(
3336         pwemb::OpCode::LE_REMOVE_ADVERTISING_SET,
3337         pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3338     return;
3339   }
3340 
3341   if (extended_advertising_states_.count(handle) == 0) {
3342     bt_log(INFO,
3343            "fake-hci",
3344            "advertising handle (%d) maps to an unknown advertising set",
3345            handle);
3346     RespondWithCommandComplete(
3347         pwemb::OpCode::LE_REMOVE_ADVERTISING_SET,
3348         pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3349     return;
3350   }
3351 
3352   if (extended_advertising_states_[handle].enabled) {
3353     bt_log(INFO,
3354            "fake-hci",
3355            "cannot remove enabled advertising set (handle: %d)",
3356            handle);
3357     RespondWithCommandComplete(pwemb::OpCode::LE_REMOVE_ADVERTISING_SET,
3358                                pwemb::StatusCode::COMMAND_DISALLOWED);
3359     return;
3360   }
3361 
3362   extended_advertising_states_.erase(handle);
3363   RespondWithCommandComplete(pwemb::OpCode::LE_REMOVE_ADVERTISING_SET,
3364                              pwemb::StatusCode::SUCCESS);
3365   NotifyAdvertisingState();
3366 }
3367 
OnLEClearAdvertisingSets()3368 void FakeController::OnLEClearAdvertisingSets() {
3369   for (const auto& element : extended_advertising_states_) {
3370     if (element.second.enabled) {
3371       bt_log(INFO,
3372              "fake-hci",
3373              "cannot remove currently enabled advertising set (handle: %d)",
3374              element.second.enabled);
3375       RespondWithCommandComplete(pwemb::OpCode::LE_CLEAR_ADVERTISING_SETS,
3376                                  pwemb::StatusCode::COMMAND_DISALLOWED);
3377       return;
3378     }
3379   }
3380 
3381   extended_advertising_states_.clear();
3382   RespondWithCommandComplete(pwemb::OpCode::LE_CLEAR_ADVERTISING_SETS,
3383                              pwemb::StatusCode::SUCCESS);
3384   NotifyAdvertisingState();
3385 }
3386 
OnLEReadAdvertisingChannelTxPower()3387 void FakeController::OnLEReadAdvertisingChannelTxPower() {
3388   if (!respond_to_tx_power_read_) {
3389     return;
3390   }
3391 
3392   // Send back arbitrary tx power.
3393   auto packet = hci::EventPacket::New<
3394       pwemb::LEReadAdvertisingChannelTxPowerCommandCompleteEventWriter>(
3395       hci_spec::kCommandCompleteEventCode);
3396   auto view = packet.view_t();
3397   view.status().Write(pwemb::StatusCode::SUCCESS);
3398   view.tx_power_level().Write(9);
3399   RespondWithCommandComplete(
3400       pwemb::OpCode::LE_READ_ADVERTISING_CHANNEL_TX_POWER, &packet);
3401 }
3402 
SendLEAdvertisingSetTerminatedEvent(hci_spec::ConnectionHandle conn_handle,hci_spec::AdvertisingHandle adv_handle)3403 void FakeController::SendLEAdvertisingSetTerminatedEvent(
3404     hci_spec::ConnectionHandle conn_handle,
3405     hci_spec::AdvertisingHandle adv_handle) {
3406   auto packet =
3407       hci::EventPacket::New<pwemb::LEAdvertisingSetTerminatedSubeventWriter>(
3408           hci_spec::kLEMetaEventCode);
3409   auto view = packet.view_t();
3410   view.le_meta_event().subevent_code().Write(
3411       hci_spec::kLEAdvertisingSetTerminatedSubeventCode);
3412   view.status().Write(pwemb::StatusCode::SUCCESS);
3413   view.connection_handle().Write(conn_handle);
3414   view.advertising_handle().Write(adv_handle);
3415   SendCommandChannelPacket(packet.data());
3416 }
3417 
SendAndroidLEMultipleAdvertisingStateChangeSubevent(hci_spec::ConnectionHandle conn_handle,hci_spec::AdvertisingHandle adv_handle)3418 void FakeController::SendAndroidLEMultipleAdvertisingStateChangeSubevent(
3419     hci_spec::ConnectionHandle conn_handle,
3420     hci_spec::AdvertisingHandle adv_handle) {
3421   auto packet =
3422       hci::EventPacket::New<android_emb::LEMultiAdvtStateChangeSubeventWriter>(
3423           hci_spec::kVendorDebugEventCode);
3424   auto view = packet.view_t();
3425   view.vendor_event().subevent_code().Write(
3426       android_hci::kLEMultiAdvtStateChangeSubeventCode);
3427   view.advertising_handle().Write(adv_handle);
3428   view.status().Write(pwemb::StatusCode::SUCCESS);
3429   view.connection_handle().Write(conn_handle);
3430   SendCommandChannelPacket(packet.data());
3431 }
3432 
OnReadLocalSupportedControllerDelay(const pwemb::ReadLocalSupportedControllerDelayCommandView & params)3433 void FakeController::OnReadLocalSupportedControllerDelay(
3434     [[maybe_unused]] const pwemb::ReadLocalSupportedControllerDelayCommandView&
3435         params) {
3436   auto packet = hci::EventPacket::New<
3437       pwemb::ReadLocalSupportedControllerDelayCommandCompleteEventWriter>(
3438       hci_spec::kCommandCompleteEventCode);
3439   auto response_view = packet.view_t();
3440   if (settings_.SupportedCommandsView()
3441           .read_local_supported_controller_delay()
3442           .Read()) {
3443     response_view.status().Write(pwemb::StatusCode::SUCCESS);
3444     response_view.min_controller_delay().Write(0);  // no delay
3445     response_view.max_controller_delay().Write(
3446         pwemb::ReadLocalSupportedControllerDelayCommandCompleteEvent::
3447             max_delay_usecs());  // maximum allowable delay
3448   } else {
3449     response_view.status().Write(pwemb::StatusCode::UNKNOWN_COMMAND);
3450   }
3451 
3452   RespondWithCommandComplete(
3453       pwemb::OpCode::READ_LOCAL_SUPPORTED_CONTROLLER_DELAY, &packet);
3454 }
3455 
OnCommandPacketReceived(const PacketView<hci_spec::CommandHeader> & command_packet)3456 void FakeController::OnCommandPacketReceived(
3457     const PacketView<hci_spec::CommandHeader>& command_packet) {
3458   hci_spec::OpCode opcode = pw::bytes::ConvertOrderFrom(
3459       cpp20::endian::little, command_packet.header().opcode);
3460 
3461   bt_log(
3462       TRACE, "fake-hci", "received command packet with opcode: %#.4x", opcode);
3463   // We handle commands immediately unless a client has explicitly set a
3464   // listener for `opcode`.
3465   if (paused_opcode_listeners_.find(opcode) == paused_opcode_listeners_.end()) {
3466     HandleReceivedCommandPacket(command_packet);
3467     return;
3468   }
3469 
3470   bt_log(DEBUG, "fake-hci", "pausing response for opcode: %#.4x", opcode);
3471   paused_opcode_listeners_[opcode](
3472       [this, packet_data = DynamicByteBuffer(command_packet.data())]() {
3473         PacketView<hci_spec::CommandHeader> command_packet(
3474             &packet_data, packet_data.size() - sizeof(hci_spec::CommandHeader));
3475         HandleReceivedCommandPacket(command_packet);
3476       });
3477 }
3478 
OnAndroidLEGetVendorCapabilities()3479 void FakeController::OnAndroidLEGetVendorCapabilities() {
3480   // We use the
3481   // android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter as
3482   // storage. This is the full HCI packet, including the header. Ensure we don't
3483   // accidentally send the header twice by using the overloaded
3484   // RespondWithCommandComplete that takes in an EventPacket. The one that
3485   // takes a BufferView allocates space for the header, assuming that it's been
3486   // sent only the payload.
3487   auto packet = hci::EventPacket::New<
3488       android_emb::LEGetVendorCapabilitiesCommandCompleteEventWriter>(
3489       hci_spec::kCommandCompleteEventCode);
3490   MutableBufferView buffer = packet.mutable_data();
3491   settings_.android_extension_settings.data().Copy(&buffer);
3492   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_GET_VENDOR_CAPABILITIES,
3493                              &packet);
3494 }
3495 
OnAndroidStartA2dpOffload(const android_emb::StartA2dpOffloadCommandView & params)3496 void FakeController::OnAndroidStartA2dpOffload(
3497     const android_emb::StartA2dpOffloadCommandView& params) {
3498   auto packet =
3499       hci::EventPacket::New<android_emb::A2dpOffloadCommandCompleteEventWriter>(
3500           hci_spec::kCommandCompleteEventCode);
3501   auto view = packet.view_t();
3502   view.sub_opcode().Write(android_emb::A2dpOffloadSubOpcode::START_LEGACY);
3503 
3504   // return in case A2DP offload already started
3505   if (offloaded_a2dp_channel_state_) {
3506     view.status().Write(pwemb::StatusCode::CONNECTION_ALREADY_EXISTS);
3507     RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3508                                &packet);
3509     return;
3510   }
3511 
3512   // SCMS-T is not currently supported
3513   if (params.scms_t_enable().enabled().Read() ==
3514       pwemb::GenericEnableParam::ENABLE) {
3515     view.status().Write(pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
3516     RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3517                                &packet);
3518     return;
3519   }
3520 
3521   // return in case any parameter has an invalid value
3522   view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3523 
3524   android_emb::A2dpCodecType const codec_type = params.codec_type().Read();
3525   switch (codec_type) {
3526     case android_emb::A2dpCodecType::SBC:
3527     case android_emb::A2dpCodecType::AAC:
3528     case android_emb::A2dpCodecType::APTX:
3529     case android_emb::A2dpCodecType::APTX_HD:
3530     case android_emb::A2dpCodecType::LDAC:
3531       break;
3532       RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3533                                  &packet);
3534       return;
3535   }
3536 
3537   android_emb::A2dpSamplingFrequency const sampling_frequency =
3538       params.sampling_frequency().Read();
3539   switch (sampling_frequency) {
3540     case android_emb::A2dpSamplingFrequency::HZ_44100:
3541     case android_emb::A2dpSamplingFrequency::HZ_48000:
3542     case android_emb::A2dpSamplingFrequency::HZ_88200:
3543     case android_emb::A2dpSamplingFrequency::HZ_96000:
3544       break;
3545     default:
3546       RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3547                                  &packet);
3548       return;
3549   }
3550 
3551   android_emb::A2dpBitsPerSample const bits_per_sample =
3552       static_cast<android_emb::A2dpBitsPerSample>(
3553           params.bits_per_sample().Read());
3554   switch (bits_per_sample) {
3555     case android_emb::A2dpBitsPerSample::BITS_PER_SAMPLE_16:
3556     case android_emb::A2dpBitsPerSample::BITS_PER_SAMPLE_24:
3557     case android_emb::A2dpBitsPerSample::BITS_PER_SAMPLE_32:
3558       break;
3559     default:
3560       RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3561                                  &packet);
3562       return;
3563   }
3564 
3565   android_emb::A2dpChannelMode const channel_mode =
3566       static_cast<android_emb::A2dpChannelMode>(params.channel_mode().Read());
3567   switch (channel_mode) {
3568     case android_emb::A2dpChannelMode::MONO:
3569     case android_emb::A2dpChannelMode::STEREO:
3570       break;
3571     default:
3572       RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3573                                  &packet);
3574       return;
3575   }
3576 
3577   uint32_t const encoded_audio_bitrate = pw::bytes::ConvertOrderFrom(
3578       cpp20::endian::little, params.encoded_audio_bitrate().Read());
3579   // Bits 0x01000000 to 0xFFFFFFFF are reserved
3580   if (encoded_audio_bitrate >= 0x01000000) {
3581     RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3582                                &packet);
3583     return;
3584   }
3585 
3586   OffloadedA2dpChannel state;
3587   state.codec_type = codec_type;
3588   state.max_latency = pw::bytes::ConvertOrderFrom(cpp20::endian::little,
3589                                                   params.max_latency().Read());
3590   state.scms_t_enable.view().CopyFrom(params.scms_t_enable());
3591   state.sampling_frequency = sampling_frequency;
3592   state.bits_per_sample = bits_per_sample;
3593   state.channel_mode = channel_mode;
3594   state.encoded_audio_bitrate = encoded_audio_bitrate;
3595   state.connection_handle = pw::bytes::ConvertOrderFrom(
3596       cpp20::endian::little, params.connection_handle().Read());
3597   state.l2cap_channel_id = pw::bytes::ConvertOrderFrom(
3598       cpp20::endian::little, params.l2cap_channel_id().Read());
3599   state.l2cap_mtu_size = pw::bytes::ConvertOrderFrom(
3600       cpp20::endian::little, params.l2cap_mtu_size().Read());
3601   offloaded_a2dp_channel_state_ = state;
3602 
3603   view.status().Write(pwemb::StatusCode::SUCCESS);
3604   RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3605                              &packet);
3606 }
3607 
OnAndroidStopA2dpOffload()3608 void FakeController::OnAndroidStopA2dpOffload() {
3609   auto packet =
3610       hci::EventPacket::New<android_emb::A2dpOffloadCommandCompleteEventWriter>(
3611           hci_spec::kCommandCompleteEventCode);
3612   auto view = packet.view_t();
3613   view.sub_opcode().Write(android_emb::A2dpOffloadSubOpcode::STOP_LEGACY);
3614 
3615   if (!offloaded_a2dp_channel_state_) {
3616     view.status().Write(pwemb::StatusCode::REPEATED_ATTEMPTS);
3617     RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3618                                &packet);
3619     return;
3620   }
3621 
3622   offloaded_a2dp_channel_state_ = std::nullopt;
3623 
3624   view.status().Write(pwemb::StatusCode::SUCCESS);
3625   RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3626                              &packet);
3627 }
3628 
OnAndroidA2dpOffloadCommand(const PacketView<hci_spec::CommandHeader> & command_packet)3629 void FakeController::OnAndroidA2dpOffloadCommand(
3630     const PacketView<hci_spec::CommandHeader>& command_packet) {
3631   const auto& payload = command_packet.payload_data();
3632 
3633   uint8_t subopcode = payload.To<uint8_t>();
3634   switch (subopcode) {
3635     case android_hci::kStartA2dpOffloadCommandSubopcode: {
3636       auto view = android_emb::MakeStartA2dpOffloadCommandView(
3637           command_packet.data().data(), command_packet.size());
3638       OnAndroidStartA2dpOffload(view);
3639       break;
3640     }
3641     case android_hci::kStopA2dpOffloadCommandSubopcode:
3642       OnAndroidStopA2dpOffload();
3643       break;
3644     default:
3645       bt_log(WARN,
3646              "fake-hci",
3647              "unhandled android A2DP offload command, subopcode: %#.4x",
3648              subopcode);
3649       RespondWithCommandComplete(pwemb::OpCode::ANDROID_A2DP_HARDWARE_OFFLOAD,
3650                                  pwemb::StatusCode::UNKNOWN_COMMAND);
3651       break;
3652   }
3653 }
3654 
OnAndroidLEMultiAdvtSetAdvtParam(const android_emb::LEMultiAdvtSetAdvtParamCommandView & params)3655 void FakeController::OnAndroidLEMultiAdvtSetAdvtParam(
3656     const android_emb::LEMultiAdvtSetAdvtParamCommandView& params) {
3657   auto packet =
3658       hci::EventPacket::New<android_emb::LEMultiAdvtCommandCompleteEventWriter>(
3659           hci_spec::kCommandCompleteEventCode);
3660   auto view = packet.view_t();
3661   view.sub_opcode().Write(
3662       android_emb::LEMultiAdvtSubOpcode::SET_ADVERTISING_PARAMETERS);
3663 
3664   hci_spec::AdvertisingHandle handle = params.adv_handle().Read();
3665   if (!IsValidAdvertisingHandle(handle)) {
3666     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3667 
3668     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3669     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3670     return;
3671   }
3672 
3673   // ensure we can allocate memory for this advertising set if not already
3674   // present
3675   if (extended_advertising_states_.count(handle) == 0 &&
3676       extended_advertising_states_.size() >= num_supported_advertising_sets()) {
3677     bt_log(INFO,
3678            "fake-hci",
3679            "no available memory for new advertising set, handle: %d",
3680            handle);
3681 
3682     view.status().Write(pwemb::StatusCode::MEMORY_CAPACITY_EXCEEDED);
3683     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3684     return;
3685   }
3686 
3687   // In case there is an error below, we want to reject all parameters instead
3688   // of storing a dead state and taking up an advertising handle. Avoid creating
3689   // the LEAdvertisingState directly in the map and add it in only once we have
3690   // made sure all is good.
3691   LEAdvertisingState state;
3692   state.own_address_type = params.own_addr_type().Read();
3693 
3694   pwemb::LEAdvertisingType adv_type = params.adv_type().Read();
3695   switch (adv_type) {
3696     case pwemb::LEAdvertisingType::CONNECTABLE_AND_SCANNABLE_UNDIRECTED:
3697       state.properties.connectable = true;
3698       state.properties.scannable = true;
3699       break;
3700     case pwemb::LEAdvertisingType::CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED:
3701       state.properties.directed = true;
3702       state.properties.connectable = true;
3703       break;
3704     case pwemb::LEAdvertisingType::CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED:
3705       state.properties.high_duty_cycle_directed_connectable = true;
3706       state.properties.directed = true;
3707       state.properties.connectable = true;
3708       break;
3709     case pwemb::LEAdvertisingType::SCANNABLE_UNDIRECTED:
3710       state.properties.scannable = true;
3711       break;
3712     case pwemb::LEAdvertisingType::NOT_CONNECTABLE_UNDIRECTED:
3713       break;
3714   }
3715 
3716   state.interval_min = params.adv_interval_min().Read();
3717   state.interval_max = params.adv_interval_max().Read();
3718 
3719   if (state.interval_min >= state.interval_max) {
3720     bt_log(INFO,
3721            "fake-hci",
3722            "advertising interval min (%d) not strictly less than max (%d)",
3723            state.interval_min,
3724            state.interval_max);
3725 
3726     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3727     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3728     return;
3729   }
3730 
3731   if (state.interval_min < hci_spec::kLEAdvertisingIntervalMin) {
3732     bt_log(INFO,
3733            "fake-hci",
3734            "advertising interval min (%d) less than spec min (%d)",
3735            state.interval_min,
3736            hci_spec::kLEAdvertisingIntervalMin);
3737     view.status().Write(pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
3738     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3739     return;
3740   }
3741 
3742   if (state.interval_max > hci_spec::kLEAdvertisingIntervalMax) {
3743     bt_log(INFO,
3744            "fake-hci",
3745            "advertising interval max (%d) greater than spec max (%d)",
3746            state.interval_max,
3747            hci_spec::kLEAdvertisingIntervalMax);
3748     view.status().Write(pwemb::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
3749     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3750     return;
3751   }
3752 
3753   // write full state back only at the end (we don't have a reference because we
3754   // only want to write if there are no errors)
3755   extended_advertising_states_[handle] = state;
3756 
3757   view.status().Write(pwemb::StatusCode::SUCCESS);
3758   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3759   NotifyAdvertisingState();
3760 }
3761 
OnAndroidLEMultiAdvtSetAdvtData(const android_emb::LEMultiAdvtSetAdvtDataCommandView & params)3762 void FakeController::OnAndroidLEMultiAdvtSetAdvtData(
3763     const android_emb::LEMultiAdvtSetAdvtDataCommandView& params) {
3764   auto packet =
3765       hci::EventPacket::New<android_emb::LEMultiAdvtCommandCompleteEventWriter>(
3766           hci_spec::kCommandCompleteEventCode);
3767   auto view = packet.view_t();
3768   view.sub_opcode().Write(
3769       android_emb::LEMultiAdvtSubOpcode::SET_ADVERTISING_DATA);
3770 
3771   hci_spec::AdvertisingHandle handle = params.adv_handle().Read();
3772   if (!IsValidAdvertisingHandle(handle)) {
3773     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3774 
3775     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3776     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3777     return;
3778   }
3779 
3780   if (extended_advertising_states_.count(handle) == 0) {
3781     bt_log(INFO,
3782            "fake-hci",
3783            "advertising handle (%d) maps to an unknown advertising set",
3784            handle);
3785 
3786     view.status().Write(pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3787     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3788     return;
3789   }
3790 
3791   LEAdvertisingState& state = extended_advertising_states_[handle];
3792 
3793   // removing advertising data entirely doesn't require us to check for error
3794   // conditions
3795   if (params.adv_data_length().Read() == 0) {
3796     state.data_length = 0;
3797     std::memset(state.data, 0, sizeof(state.data));
3798     view.status().Write(pwemb::StatusCode::SUCCESS);
3799     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3800     NotifyAdvertisingState();
3801     return;
3802   }
3803 
3804   // directed advertising doesn't support advertising data
3805   if (state.IsDirectedAdvertising()) {
3806     bt_log(INFO,
3807            "fake-hci",
3808            "cannot provide advertising data when using directed advertising");
3809 
3810     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3811     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3812     return;
3813   }
3814 
3815   if (params.adv_data_length().Read() > hci_spec::kMaxLEAdvertisingDataLength) {
3816     bt_log(INFO,
3817            "fake-hci",
3818            "data length (%d bytes) larger than legacy PDU size limit",
3819            params.adv_data_length().Read());
3820 
3821     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3822     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3823     return;
3824   }
3825 
3826   state.data_length = params.adv_data_length().Read();
3827   std::memcpy(state.data,
3828               params.adv_data().BackingStorage().data(),
3829               params.adv_data_length().Read());
3830 
3831   view.status().Write(pwemb::StatusCode::SUCCESS);
3832   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3833   NotifyAdvertisingState();
3834 }
3835 
OnAndroidLEMultiAdvtSetScanResp(const android_emb::LEMultiAdvtSetScanRespDataCommandView & params)3836 void FakeController::OnAndroidLEMultiAdvtSetScanResp(
3837     const android_emb::LEMultiAdvtSetScanRespDataCommandView& params) {
3838   auto packet =
3839       hci::EventPacket::New<android_emb::LEMultiAdvtCommandCompleteEventWriter>(
3840           hci_spec::kCommandCompleteEventCode);
3841   auto view = packet.view_t();
3842   view.sub_opcode().Write(
3843       android_emb::LEMultiAdvtSubOpcode::SET_SCAN_RESPONSE_DATA);
3844 
3845   hci_spec::AdvertisingHandle handle = params.adv_handle().Read();
3846   if (!IsValidAdvertisingHandle(handle)) {
3847     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3848 
3849     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3850     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3851     return;
3852   }
3853 
3854   if (extended_advertising_states_.count(handle) == 0) {
3855     bt_log(INFO,
3856            "fake-hci",
3857            "advertising handle (%d) maps to an unknown advertising set",
3858            handle);
3859 
3860     view.status().Write(pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3861     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3862     return;
3863   }
3864 
3865   LEAdvertisingState& state = extended_advertising_states_[handle];
3866 
3867   // removing scan response data entirely doesn't require us to check for error
3868   // conditions
3869   if (params.scan_resp_length().Read() == 0) {
3870     state.scan_rsp_length = 0;
3871     std::memset(state.scan_rsp_data, 0, sizeof(state.scan_rsp_data));
3872 
3873     view.status().Write(pwemb::StatusCode::SUCCESS);
3874     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3875     NotifyAdvertisingState();
3876     return;
3877   }
3878 
3879   // adding or changing scan response data, check for error conditions
3880   if (!state.properties.scannable) {
3881     bt_log(
3882         INFO,
3883         "fake-hci",
3884         "cannot provide scan response data for unscannable advertising types");
3885 
3886     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3887     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3888     return;
3889   }
3890 
3891   if (params.scan_resp_length().Read() >
3892       hci_spec::kMaxLEAdvertisingDataLength) {
3893     bt_log(INFO,
3894            "fake-hci",
3895            "data length (%d bytes) larger than legacy PDU size limit",
3896            params.scan_resp_length().Read());
3897 
3898     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3899     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3900     return;
3901   }
3902 
3903   state.scan_rsp_length = params.scan_resp_length().Read();
3904   std::memcpy(state.scan_rsp_data,
3905               params.scan_resp_data().BackingStorage().data(),
3906               params.scan_resp_length().Read());
3907 
3908   view.status().Write(pwemb::StatusCode::SUCCESS);
3909   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3910   NotifyAdvertisingState();
3911 }
3912 
OnAndroidLEMultiAdvtSetRandomAddr(const android_emb::LEMultiAdvtSetRandomAddrCommandView & params)3913 void FakeController::OnAndroidLEMultiAdvtSetRandomAddr(
3914     const android_emb::LEMultiAdvtSetRandomAddrCommandView& params) {
3915   auto packet =
3916       hci::EventPacket::New<android_emb::LEMultiAdvtCommandCompleteEventWriter>(
3917           hci_spec::kCommandCompleteEventCode);
3918   auto view = packet.view_t();
3919   view.sub_opcode().Write(
3920       android_emb::LEMultiAdvtSubOpcode::SET_RANDOM_ADDRESS);
3921 
3922   hci_spec::AdvertisingHandle handle = params.adv_handle().Read();
3923   if (!IsValidAdvertisingHandle(handle)) {
3924     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3925 
3926     view.status().Write(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS);
3927     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3928     return;
3929   }
3930 
3931   if (extended_advertising_states_.count(handle) == 0) {
3932     bt_log(INFO,
3933            "fake-hci",
3934            "advertising handle (%d) maps to an unknown advertising set",
3935            handle);
3936 
3937     view.status().Write(pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3938     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3939     return;
3940   }
3941 
3942   LEAdvertisingState& state = extended_advertising_states_[handle];
3943   if (state.properties.connectable && state.enabled) {
3944     bt_log(
3945         INFO,
3946         "fake-hci",
3947         "cannot set LE random address while connectable advertising enabled");
3948 
3949     view.status().Write(pwemb::StatusCode::COMMAND_DISALLOWED);
3950     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3951     return;
3952   }
3953 
3954   state.random_address =
3955       DeviceAddress(DeviceAddress::Type::kLERandom,
3956                     DeviceAddressBytes(params.random_address()));
3957 
3958   view.status().Write(pwemb::StatusCode::SUCCESS);
3959   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3960 }
3961 
OnAndroidLEMultiAdvtEnable(const android_emb::LEMultiAdvtEnableCommandView & params)3962 void FakeController::OnAndroidLEMultiAdvtEnable(
3963     const android_emb::LEMultiAdvtEnableCommandView& params) {
3964   auto packet =
3965       hci::EventPacket::New<android_emb::LEMultiAdvtCommandCompleteEventWriter>(
3966           hci_spec::kCommandCompleteEventCode);
3967   auto view = packet.view_t();
3968   view.sub_opcode().Write(android_emb::LEMultiAdvtSubOpcode::ENABLE);
3969 
3970   hci_spec::AdvertisingHandle handle = params.advertising_handle().Read();
3971 
3972   if (!IsValidAdvertisingHandle(handle)) {
3973     bt_log(ERROR, "fake-hci", "advertising handle outside range: %d", handle);
3974 
3975     view.status().Write(pwemb::StatusCode::UNKNOWN_ADVERTISING_IDENTIFIER);
3976     RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3977     return;
3978   }
3979 
3980   bool enabled = false;
3981   if (params.enable().Read() == pwemb::GenericEnableParam::ENABLE) {
3982     enabled = true;
3983   }
3984 
3985   extended_advertising_states_[handle].enabled = enabled;
3986 
3987   view.status().Write(pwemb::StatusCode::SUCCESS);
3988   RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT, &packet);
3989   NotifyAdvertisingState();
3990 }
3991 
OnAndroidLEMultiAdvt(const PacketView<hci_spec::CommandHeader> & command_packet)3992 void FakeController::OnAndroidLEMultiAdvt(
3993     const PacketView<hci_spec::CommandHeader>& command_packet) {
3994   const auto& payload = command_packet.payload_data();
3995 
3996   uint8_t subopcode = payload.To<uint8_t>();
3997   switch (subopcode) {
3998     case android_hci::kLEMultiAdvtSetAdvtParamSubopcode: {
3999       auto params = android_emb::MakeLEMultiAdvtSetAdvtParamCommandView(
4000           command_packet.data().data(), command_packet.size());
4001       OnAndroidLEMultiAdvtSetAdvtParam(params);
4002       break;
4003     }
4004     case android_hci::kLEMultiAdvtSetAdvtDataSubopcode: {
4005       auto params = android_emb::MakeLEMultiAdvtSetAdvtDataCommandView(
4006           command_packet.data().data(), command_packet.size());
4007       OnAndroidLEMultiAdvtSetAdvtData(params);
4008       break;
4009     }
4010     case android_hci::kLEMultiAdvtSetScanRespSubopcode: {
4011       auto params = android_emb::MakeLEMultiAdvtSetScanRespDataCommandView(
4012           command_packet.data().data(), command_packet.size());
4013       OnAndroidLEMultiAdvtSetScanResp(params);
4014       break;
4015     }
4016     case android_hci::kLEMultiAdvtSetRandomAddrSubopcode: {
4017       auto params = android_emb::MakeLEMultiAdvtSetRandomAddrCommandView(
4018           command_packet.data().data(), command_packet.size());
4019       OnAndroidLEMultiAdvtSetRandomAddr(params);
4020       break;
4021     }
4022     case android_hci::kLEMultiAdvtEnableSubopcode: {
4023       auto view = android_emb::MakeLEMultiAdvtEnableCommandView(
4024           command_packet.data().data(), command_packet.size());
4025       OnAndroidLEMultiAdvtEnable(view);
4026       break;
4027     }
4028     default: {
4029       bt_log(WARN,
4030              "fake-hci",
4031              "unhandled android multiple advertising command, subopcode: %#.4x",
4032              subopcode);
4033       RespondWithCommandComplete(pwemb::OpCode::ANDROID_LE_MULTI_ADVT,
4034                                  pwemb::StatusCode::UNKNOWN_COMMAND);
4035       break;
4036     }
4037   }
4038 }
4039 
OnVendorCommand(const PacketView<hci_spec::CommandHeader> & command_packet)4040 void FakeController::OnVendorCommand(
4041     const PacketView<hci_spec::CommandHeader>& command_packet) {
4042   auto opcode = pw::bytes::ConvertOrderFrom(cpp20::endian::little,
4043                                             command_packet.header().opcode);
4044 
4045   switch (opcode) {
4046     case android_hci::kLEGetVendorCapabilities:
4047       OnAndroidLEGetVendorCapabilities();
4048       break;
4049     case android_hci::kA2dpOffloadCommand:
4050       OnAndroidA2dpOffloadCommand(command_packet);
4051       break;
4052     case android_hci::kLEMultiAdvt:
4053       OnAndroidLEMultiAdvt(command_packet);
4054       break;
4055     default:
4056       bt_log(WARN,
4057              "fake-hci",
4058              "received unhandled vendor command with opcode: %#.4x",
4059              opcode);
4060       RespondWithCommandComplete(static_cast<pwemb::OpCode>(opcode),
4061                                  pwemb::StatusCode::UNKNOWN_COMMAND);
4062       break;
4063   }
4064 }
4065 
OnACLDataPacketReceived(const ByteBuffer & acl_data_packet)4066 void FakeController::OnACLDataPacketReceived(
4067     const ByteBuffer& acl_data_packet) {
4068   if (acl_data_callback_) {
4069     PW_DCHECK(data_dispatcher_);
4070     DynamicByteBuffer packet_copy(acl_data_packet);
4071     (void)data_dispatcher_->Post(
4072         [packet_copy = std::move(packet_copy), cb = acl_data_callback_.share()](
4073             pw::async::Context /*ctx*/, pw::Status status) mutable {
4074           if (status.ok()) {
4075             cb(packet_copy);
4076           }
4077         });
4078   }
4079 
4080   if (acl_data_packet.size() < sizeof(hci_spec::ACLDataHeader)) {
4081     bt_log(WARN, "fake-hci", "malformed ACL packet!");
4082     return;
4083   }
4084 
4085   const auto& header = acl_data_packet.To<hci_spec::ACLDataHeader>();
4086   hci_spec::ConnectionHandle handle =
4087       pw::bytes::ConvertOrderFrom(cpp20::endian::little,
4088                                   header.handle_and_flags) &
4089       0x0FFFF;
4090   FakePeer* peer = FindByConnHandle(handle);
4091   if (!peer) {
4092     bt_log(WARN, "fake-hci", "ACL data received for unknown handle!");
4093     return;
4094   }
4095 
4096   if (auto_completed_packets_event_enabled_) {
4097     SendNumberOfCompletedPacketsEvent(handle, 1);
4098   }
4099   peer->OnRxL2CAP(handle,
4100                   acl_data_packet.view(sizeof(hci_spec::ACLDataHeader)));
4101 }
4102 
OnScoDataPacketReceived(const ByteBuffer & sco_data_packet)4103 void FakeController::OnScoDataPacketReceived(
4104     const ByteBuffer& sco_data_packet) {
4105   if (sco_data_callback_) {
4106     sco_data_callback_(sco_data_packet);
4107   }
4108 
4109   if (sco_data_packet.size() < sizeof(hci_spec::SynchronousDataHeader)) {
4110     bt_log(WARN, "fake-hci", "malformed SCO packet!");
4111     return;
4112   }
4113 
4114   const auto& header = sco_data_packet.To<hci_spec::SynchronousDataHeader>();
4115   hci_spec::ConnectionHandle handle =
4116       pw::bytes::ConvertOrderFrom(cpp20::endian::little,
4117                                   header.handle_and_flags) &
4118       0x0FFFF;
4119   FakePeer* peer = FindByConnHandle(handle);
4120   if (!peer) {
4121     bt_log(WARN, "fake-hci", "SCO data received for unknown handle!");
4122     return;
4123   }
4124 
4125   if (auto_completed_packets_event_enabled_) {
4126     SendNumberOfCompletedPacketsEvent(handle, 1);
4127   }
4128 }
4129 
OnIsoDataPacketReceived(const ByteBuffer & iso_data_packet)4130 void FakeController::OnIsoDataPacketReceived(
4131     const ByteBuffer& iso_data_packet) {
4132   if (iso_data_callback_) {
4133     iso_data_callback_(iso_data_packet);
4134   }
4135 
4136   if (iso_data_packet.size() < pwemb::IsoDataFrameHeader::MinSizeInBytes()) {
4137     bt_log(WARN, "fake-hci", "malformed ISO packet!");
4138     return;
4139   }
4140 
4141   auto iso_header_view = pwemb::MakeIsoDataFrameHeaderView(
4142       iso_data_packet.data(), iso_data_packet.size());
4143   hci_spec::ConnectionHandle handle =
4144       iso_header_view.connection_handle().Read();
4145 
4146   if (auto_completed_packets_event_enabled_) {
4147     SendNumberOfCompletedPacketsEvent(handle, 1);
4148   }
4149 }
4150 
SetDataCallback(DataCallback callback,pw::async::Dispatcher & pw_dispatcher)4151 void FakeController::SetDataCallback(DataCallback callback,
4152                                      pw::async::Dispatcher& pw_dispatcher) {
4153   PW_DCHECK(callback);
4154   PW_DCHECK(!acl_data_callback_);
4155   PW_DCHECK(!data_dispatcher_);
4156 
4157   acl_data_callback_ = std::move(callback);
4158   data_dispatcher_.emplace(pw_dispatcher);
4159 }
4160 
ClearDataCallback()4161 void FakeController::ClearDataCallback() {
4162   // Leave dispatcher set (if already set) to preserve its write-once-ness (this
4163   // catches bugs with setting multiple data callbacks in class hierarchies).
4164   acl_data_callback_ = nullptr;
4165 }
4166 
IsDirectedAdvertising() const4167 bool FakeController::LEAdvertisingState::IsDirectedAdvertising() const {
4168   return properties.directed || properties.high_duty_cycle_directed_connectable;
4169 }
4170 
EnableLegacyAdvertising()4171 bool FakeController::EnableLegacyAdvertising() {
4172   if (advertising_procedure() == AdvertisingProcedure::kExtended) {
4173     return false;
4174   }
4175 
4176   advertising_procedure_ = AdvertisingProcedure::kLegacy;
4177   return true;
4178 }
4179 
EnableExtendedAdvertising()4180 bool FakeController::EnableExtendedAdvertising() {
4181   if (advertising_procedure() == AdvertisingProcedure::kLegacy) {
4182     return false;
4183   }
4184 
4185   advertising_procedure_ = AdvertisingProcedure::kExtended;
4186   return true;
4187 }
4188 
HandleReceivedCommandPacket(const PacketView<hci_spec::CommandHeader> & command_packet)4189 void FakeController::HandleReceivedCommandPacket(
4190     const PacketView<hci_spec::CommandHeader>& command_packet) {
4191   hci_spec::OpCode opcode = pw::bytes::ConvertOrderFrom(
4192       cpp20::endian::little, command_packet.header().opcode);
4193 
4194   if (MaybeRespondWithDefaultCommandStatus(opcode)) {
4195     return;
4196   }
4197 
4198   if (MaybeRespondWithDefaultStatus(opcode)) {
4199     return;
4200   }
4201 
4202   auto ogf = hci_spec::GetOGF(opcode);
4203   if (ogf == hci_spec::kVendorOGF) {
4204     OnVendorCommand(command_packet);
4205     return;
4206   }
4207 
4208   // TODO(fxbug.dev/42175513): Validate size of payload to be the correct length
4209   // below.
4210   switch (opcode) {
4211     case hci_spec::kReadLocalVersionInfo: {
4212       OnReadLocalVersionInfo();
4213       break;
4214     }
4215     case hci_spec::kReadLocalSupportedCommands: {
4216       OnReadLocalSupportedCommands();
4217       break;
4218     }
4219     case hci_spec::kReadLocalSupportedFeatures: {
4220       OnReadLocalSupportedFeatures();
4221       break;
4222     }
4223     case hci_spec::kReadBDADDR: {
4224       OnReadBRADDR();
4225       break;
4226     }
4227     case hci_spec::kReadBufferSize: {
4228       OnReadBufferSize();
4229       break;
4230     }
4231     case hci_spec::kCreateConnectionCancel: {
4232       OnCreateConnectionCancel();
4233       break;
4234     }
4235     case hci_spec::kReadLocalName: {
4236       OnReadLocalName();
4237       break;
4238     }
4239     case hci_spec::kReadScanEnable: {
4240       OnReadScanEnable();
4241       break;
4242     }
4243     case hci_spec::kReadPageScanActivity: {
4244       OnReadPageScanActivity();
4245       break;
4246     }
4247     case hci_spec::kReadInquiryMode: {
4248       OnReadInquiryMode();
4249       break;
4250     }
4251     case hci_spec::kReadPageScanType: {
4252       OnReadPageScanType();
4253       break;
4254     }
4255     case hci_spec::kReadSimplePairingMode: {
4256       OnReadSimplePairingMode();
4257       break;
4258     }
4259     case hci_spec::kLECreateConnectionCancel: {
4260       OnLECreateConnectionCancel();
4261       break;
4262     }
4263     case hci_spec::kLEReadLocalSupportedFeatures: {
4264       OnLEReadLocalSupportedFeatures();
4265       break;
4266     }
4267     case hci_spec::kLEReadSupportedStates: {
4268       OnLEReadSupportedStates();
4269       break;
4270     }
4271     case hci_spec::kLEReadBufferSizeV1: {
4272       OnLEReadBufferSizeV1();
4273       break;
4274     }
4275     case hci_spec::kLEReadBufferSizeV2: {
4276       OnLEReadBufferSizeV2();
4277       break;
4278     }
4279     case hci_spec::kReset: {
4280       OnReset();
4281       break;
4282     }
4283     case hci_spec::kLinkKeyRequestReply: {
4284       const auto& params =
4285           command_packet.payload<pwemb::LinkKeyRequestReplyCommandView>();
4286       OnLinkKeyRequestReplyCommandReceived(params);
4287       break;
4288     }
4289     case hci_spec::kLEReadAdvertisingChannelTxPower: {
4290       OnLEReadAdvertisingChannelTxPower();
4291       break;
4292     }
4293     case hci_spec::kAuthenticationRequested:
4294     case hci_spec::kCreateConnection:
4295     case hci_spec::kDisconnect:
4296     case hci_spec::kEnhancedAcceptSynchronousConnectionRequest:
4297     case hci_spec::kEnhancedSetupSynchronousConnection:
4298     case hci_spec::kIOCapabilityRequestReply:
4299     case hci_spec::kInquiry:
4300     case hci_spec::kLEClearAdvertisingSets:
4301     case hci_spec::kLEConnectionUpdate:
4302     case hci_spec::kLECreateConnection:
4303     case hci_spec::kLEExtendedCreateConnection:
4304     case hci_spec::kLEReadMaximumAdvertisingDataLength:
4305     case hci_spec::kLEReadNumSupportedAdvertisingSets:
4306     case hci_spec::kLEReadRemoteFeatures:
4307     case hci_spec::kLERemoveAdvertisingSet:
4308     case hci_spec::kLESetAdvertisingData:
4309     case hci_spec::kLESetAdvertisingEnable:
4310     case hci_spec::kLESetAdvertisingParameters:
4311     case hci_spec::kLESetAdvertisingSetRandomAddress:
4312     case hci_spec::kLESetEventMask:
4313     case hci_spec::kLESetExtendedAdvertisingData:
4314     case hci_spec::kLESetExtendedAdvertisingEnable:
4315     case hci_spec::kLESetExtendedAdvertisingParameters:
4316     case hci_spec::kLESetExtendedScanEnable:
4317     case hci_spec::kLESetExtendedScanParameters:
4318     case hci_spec::kLESetExtendedScanResponseData:
4319     case hci_spec::kLESetHostFeature:
4320     case hci_spec::kLESetRandomAddress:
4321     case hci_spec::kLESetScanEnable:
4322     case hci_spec::kLESetScanParameters:
4323     case hci_spec::kLESetScanResponseData:
4324     case hci_spec::kLEStartEncryption:
4325     case hci_spec::kLinkKeyRequestNegativeReply:
4326     case hci_spec::kReadEncryptionKeySize:
4327     case hci_spec::kReadLocalExtendedFeatures:
4328     case hci_spec::kReadLocalSupportedControllerDelay:
4329     case hci_spec::kReadRemoteExtendedFeatures:
4330     case hci_spec::kReadRemoteSupportedFeatures:
4331     case hci_spec::kReadRemoteVersionInfo:
4332     case hci_spec::kRemoteNameRequest:
4333     case hci_spec::kSetConnectionEncryption:
4334     case hci_spec::kSetEventMask:
4335     case hci_spec::kUserConfirmationRequestNegativeReply:
4336     case hci_spec::kUserConfirmationRequestReply:
4337     case hci_spec::kWriteClassOfDevice:
4338     case hci_spec::kWriteExtendedInquiryResponse:
4339     case hci_spec::kWriteInquiryMode:
4340     case hci_spec::kWriteLEHostSupport:
4341     case hci_spec::kWriteLocalName:
4342     case hci_spec::kWritePageScanActivity:
4343     case hci_spec::kWritePageScanType:
4344     case hci_spec::kWriteScanEnable:
4345     case hci_spec::kWriteSecureConnectionsHostSupport:
4346     case hci_spec::kWriteSimplePairingMode:
4347     case hci_spec::kWriteSynchronousFlowControlEnable: {
4348       // This case is for packet types that have been migrated to the new Emboss
4349       // architecture. Their old version can be still be assembled from the
4350       // HciEmulator channel, so here we repackage and forward them as Emboss
4351       // packets.
4352       auto emboss_packet =
4353           bt::hci::CommandPacket::New<pwemb::CommandHeaderView>(
4354               opcode, command_packet.size());
4355       bt::MutableBufferView dest = emboss_packet.mutable_data();
4356       command_packet.data().view().Copy(&dest);
4357       HandleReceivedCommandPacket(emboss_packet);
4358       break;
4359     }
4360     default: {
4361       bt_log(WARN,
4362              "fake-hci",
4363              "received unhandled command with opcode: %#.4x",
4364              opcode);
4365       RespondWithCommandComplete(static_cast<pwemb::OpCode>(opcode),
4366                                  pwemb::StatusCode::UNKNOWN_COMMAND);
4367       break;
4368     }
4369   }
4370 }
4371 
HandleReceivedCommandPacket(const hci::CommandPacket & command_packet)4372 void FakeController::HandleReceivedCommandPacket(
4373     const hci::CommandPacket& command_packet) {
4374   hci_spec::OpCode opcode = command_packet.opcode();
4375 
4376   if (MaybeRespondWithDefaultCommandStatus(opcode)) {
4377     return;
4378   }
4379 
4380   if (MaybeRespondWithDefaultStatus(opcode)) {
4381     return;
4382   }
4383 
4384   auto ogf = command_packet.ogf();
4385   if (ogf == hci_spec::kVendorOGF) {
4386     bt_log(WARN,
4387            "fake-hci",
4388            "vendor commands not yet migrated to Emboss; received Emboss vendor "
4389            "command with "
4390            "opcode: %#.4x",
4391            opcode);
4392     RespondWithCommandComplete(static_cast<pwemb::OpCode>(opcode),
4393                                pwemb::StatusCode::UNKNOWN_COMMAND);
4394     return;
4395   }
4396 
4397   switch (opcode) {
4398     case hci_spec::kInquiry: {
4399       auto params = command_packet.view<pwemb::InquiryCommandView>();
4400       OnInquiry(params);
4401       break;
4402     }
4403     case hci_spec::kEnhancedAcceptSynchronousConnectionRequest: {
4404       auto params = command_packet.view<
4405           pwemb::EnhancedAcceptSynchronousConnectionRequestCommandView>();
4406       OnEnhancedAcceptSynchronousConnectionRequestCommand(params);
4407       break;
4408     }
4409     case hci_spec::kEnhancedSetupSynchronousConnection: {
4410       auto params =
4411           command_packet
4412               .view<pwemb::EnhancedSetupSynchronousConnectionCommandView>();
4413       OnEnhancedSetupSynchronousConnectionCommand(params);
4414       break;
4415     }
4416     case hci_spec::kCreateConnection: {
4417       const auto params =
4418           command_packet.view<pwemb::CreateConnectionCommandView>();
4419       OnCreateConnectionCommandReceived(params);
4420       break;
4421     }
4422     case hci_spec::kDisconnect: {
4423       const auto params = command_packet.view<pwemb::DisconnectCommandView>();
4424       OnDisconnectCommandReceived(params);
4425       break;
4426     }
4427     case hci_spec::kLESetAdvertisingEnable: {
4428       const auto params =
4429           command_packet.view<pwemb::LESetAdvertisingEnableCommandView>();
4430       OnLESetAdvertisingEnable(params);
4431       break;
4432     }
4433     case hci_spec::kLESetExtendedAdvertisingEnable: {
4434       const auto params =
4435           command_packet
4436               .view<pwemb::LESetExtendedAdvertisingEnableCommandView>();
4437       OnLESetExtendedAdvertisingEnable(params);
4438       break;
4439     }
4440     case hci_spec::kLERemoveAdvertisingSet: {
4441       const auto params =
4442           command_packet.view<pwemb::LERemoveAdvertisingSetCommandView>();
4443       OnLERemoveAdvertisingSet(params);
4444       break;
4445     }
4446     case hci_spec::kLinkKeyRequestNegativeReply: {
4447       const auto params =
4448           command_packet.view<pwemb::LinkKeyRequestNegativeReplyCommandView>();
4449       OnLinkKeyRequestNegativeReplyCommandReceived(params);
4450       break;
4451     }
4452     case hci_spec::kAuthenticationRequested: {
4453       const auto params =
4454           command_packet.view<pwemb::AuthenticationRequestedCommandView>();
4455       OnAuthenticationRequestedCommandReceived(params);
4456       break;
4457     }
4458     case hci_spec::kSetConnectionEncryption: {
4459       const auto params =
4460           command_packet.view<pwemb::SetConnectionEncryptionCommandView>();
4461       OnSetConnectionEncryptionCommand(params);
4462       break;
4463     }
4464     case hci_spec::kRemoteNameRequest: {
4465       const auto params =
4466           command_packet.view<pwemb::RemoteNameRequestCommandView>();
4467       OnReadRemoteNameRequestCommandReceived(params);
4468       break;
4469     }
4470     case hci_spec::kReadRemoteSupportedFeatures: {
4471       const auto params =
4472           command_packet.view<pwemb::ReadRemoteSupportedFeaturesCommandView>();
4473       OnReadRemoteSupportedFeaturesCommandReceived(params);
4474       break;
4475     }
4476     case hci_spec::kReadRemoteExtendedFeatures: {
4477       const auto params =
4478           command_packet.view<pwemb::ReadRemoteExtendedFeaturesCommandView>();
4479       OnReadRemoteExtendedFeaturesCommandReceived(params);
4480       break;
4481     }
4482     case hci_spec::kReadRemoteVersionInfo: {
4483       const auto params =
4484           command_packet.view<pwemb::ReadRemoteVersionInfoCommandView>();
4485       OnReadRemoteVersionInfoCommandReceived(params);
4486       break;
4487     }
4488     case hci_spec::kIOCapabilityRequestReply: {
4489       const auto params =
4490           command_packet.view<pwemb::IoCapabilityRequestReplyCommandView>();
4491       OnIOCapabilityRequestReplyCommand(params);
4492       break;
4493     }
4494     case hci_spec::kSetEventMask: {
4495       const auto params = command_packet.view<pwemb::SetEventMaskCommandView>();
4496       OnSetEventMask(params);
4497       break;
4498     }
4499     case hci_spec::kWriteLocalName: {
4500       const auto params =
4501           command_packet.view<pwemb::WriteLocalNameCommandView>();
4502       OnWriteLocalName(params);
4503       break;
4504     }
4505     case hci_spec::kWriteScanEnable: {
4506       const auto& params =
4507           command_packet.view<pwemb::WriteScanEnableCommandView>();
4508       OnWriteScanEnable(params);
4509       break;
4510     }
4511     case hci_spec::kWritePageScanActivity: {
4512       const auto& params =
4513           command_packet.view<pwemb::WritePageScanActivityCommandView>();
4514       OnWritePageScanActivity(params);
4515       break;
4516     }
4517     case hci_spec::kUserConfirmationRequestReply: {
4518       const auto& params =
4519           command_packet.view<pwemb::UserConfirmationRequestReplyCommandView>();
4520       OnUserConfirmationRequestReplyCommand(params);
4521       break;
4522     }
4523     case hci_spec::kUserConfirmationRequestNegativeReply: {
4524       const auto& params =
4525           command_packet
4526               .view<pwemb::UserConfirmationRequestNegativeReplyCommandView>();
4527       OnUserConfirmationRequestNegativeReplyCommand(params);
4528       break;
4529     }
4530     case hci_spec::kWriteSynchronousFlowControlEnable: {
4531       const auto& params =
4532           command_packet
4533               .view<pwemb::WriteSynchronousFlowControlEnableCommandView>();
4534       OnWriteSynchronousFlowControlEnableCommand(params);
4535       break;
4536     }
4537     case hci_spec::kWriteExtendedInquiryResponse: {
4538       const auto& params =
4539           command_packet.view<pwemb::WriteExtendedInquiryResponseCommandView>();
4540       OnWriteExtendedInquiryResponse(params);
4541       break;
4542     }
4543     case hci_spec::kWriteSimplePairingMode: {
4544       const auto& params =
4545           command_packet.view<pwemb::WriteSimplePairingModeCommandView>();
4546       OnWriteSimplePairingMode(params);
4547       break;
4548     }
4549     case hci_spec::kWriteClassOfDevice: {
4550       const auto& params =
4551           command_packet.view<pwemb::WriteClassOfDeviceCommandView>();
4552       OnWriteClassOfDevice(params);
4553       break;
4554     }
4555     case hci_spec::kWriteInquiryMode: {
4556       const auto& params =
4557           command_packet.view<pwemb::WriteInquiryModeCommandView>();
4558       OnWriteInquiryMode(params);
4559       break;
4560     };
4561     case hci_spec::kWritePageScanType: {
4562       const auto& params =
4563           command_packet.view<pwemb::WritePageScanTypeCommandView>();
4564       OnWritePageScanType(params);
4565       break;
4566     }
4567     case hci_spec::kWriteLEHostSupport: {
4568       const auto& params =
4569           command_packet.view<pwemb::WriteLEHostSupportCommandView>();
4570       OnWriteLEHostSupportCommandReceived(params);
4571       break;
4572     }
4573     case hci_spec::kWriteSecureConnectionsHostSupport: {
4574       const auto& params =
4575           command_packet
4576               .view<pwemb::WriteSecureConnectionsHostSupportCommandView>();
4577       OnWriteSecureConnectionsHostSupport(params);
4578       break;
4579     }
4580     case hci_spec::kReadEncryptionKeySize: {
4581       const auto& params =
4582           command_packet.view<pwemb::ReadEncryptionKeySizeCommandView>();
4583       OnReadEncryptionKeySizeCommand(params);
4584       break;
4585     }
4586     case hci_spec::kLEReadRemoteFeatures: {
4587       const auto& params =
4588           command_packet.view<pwemb::LEReadRemoteFeaturesCommandView>();
4589       OnLEReadRemoteFeaturesCommand(params);
4590       break;
4591     }
4592     case hci_spec::kLESetEventMask: {
4593       const auto& params =
4594           command_packet.view<pwemb::LESetEventMaskCommandView>();
4595       OnLESetEventMask(params);
4596       break;
4597     }
4598     case hci_spec::kLESetRandomAddress: {
4599       const auto& params =
4600           command_packet.view<pwemb::LESetRandomAddressCommandView>();
4601       OnLESetRandomAddress(params);
4602       break;
4603     }
4604     case hci_spec::kLESetAdvertisingData: {
4605       const auto& params =
4606           command_packet.view<pwemb::LESetAdvertisingDataCommandView>();
4607       OnLESetAdvertisingData(params);
4608       break;
4609     }
4610     case hci_spec::kLESetScanResponseData: {
4611       const auto& params =
4612           command_packet.view<pwemb::LESetScanResponseDataCommandView>();
4613       OnLESetScanResponseData(params);
4614       break;
4615     }
4616     case hci_spec::kLESetScanParameters: {
4617       const auto& params =
4618           command_packet.view<pwemb::LESetScanParametersCommandView>();
4619       OnLESetScanParameters(params);
4620       break;
4621     }
4622     case hci_spec::kLESetExtendedScanParameters: {
4623       const auto& params =
4624           command_packet.view<pwemb::LESetExtendedScanParametersCommandView>();
4625       OnLESetExtendedScanParameters(params);
4626       break;
4627     }
4628     case hci_spec::kLESetScanEnable: {
4629       const auto& params =
4630           command_packet.view<pwemb::LESetScanEnableCommandView>();
4631       OnLESetScanEnable(params);
4632       break;
4633     }
4634     case hci_spec::kLESetExtendedScanEnable: {
4635       const auto& params =
4636           command_packet.view<pwemb::LESetExtendedScanEnableCommandView>();
4637       OnLESetExtendedScanEnable(params);
4638       break;
4639     }
4640     case hci_spec::kLECreateConnection: {
4641       const auto& params =
4642           command_packet.view<pwemb::LECreateConnectionCommandView>();
4643       OnLECreateConnectionCommandReceived(params);
4644       break;
4645     }
4646     case hci_spec::kLEExtendedCreateConnection: {
4647       const auto& params =
4648           command_packet.view<pwemb::LEExtendedCreateConnectionCommandV1View>();
4649       OnLEExtendedCreateConnectionCommandReceived(params);
4650       break;
4651     }
4652     case hci_spec::kLEConnectionUpdate: {
4653       const auto& params =
4654           command_packet.view<pwemb::LEConnectionUpdateCommandView>();
4655       OnLEConnectionUpdateCommandReceived(params);
4656       break;
4657     }
4658     case hci_spec::kLEStartEncryption: {
4659       const auto& params =
4660           command_packet.view<pwemb::LEEnableEncryptionCommandView>();
4661       OnLEStartEncryptionCommand(params);
4662       break;
4663     }
4664     case hci_spec::kReadLocalExtendedFeatures: {
4665       const auto& params =
4666           command_packet.view<pwemb::ReadLocalExtendedFeaturesCommandView>();
4667       OnReadLocalExtendedFeatures(params);
4668       break;
4669     }
4670     case hci_spec::kLESetAdvertisingParameters: {
4671       const auto& params =
4672           command_packet.view<pwemb::LESetAdvertisingParametersCommandView>();
4673       OnLESetAdvertisingParameters(params);
4674       break;
4675     }
4676     case hci_spec::kLESetExtendedAdvertisingData: {
4677       const auto& params =
4678           command_packet.view<pwemb::LESetExtendedAdvertisingDataCommandView>();
4679       OnLESetExtendedAdvertisingData(params);
4680       break;
4681     }
4682     case hci_spec::kLESetExtendedScanResponseData: {
4683       const auto& params =
4684           command_packet
4685               .view<pwemb::LESetExtendedScanResponseDataCommandView>();
4686       OnLESetExtendedScanResponseData(params);
4687       break;
4688     }
4689     case hci_spec::kLESetHostFeature: {
4690       const auto& params =
4691           command_packet.view<pwemb::LESetHostFeatureCommandView>();
4692       OnLESetHostFeature(params);
4693       break;
4694     }
4695     case hci_spec::kLEReadMaximumAdvertisingDataLength: {
4696       OnLEReadMaximumAdvertisingDataLength();
4697       break;
4698     }
4699     case hci_spec::kLEReadNumSupportedAdvertisingSets: {
4700       OnLEReadNumberOfSupportedAdvertisingSets();
4701       break;
4702     }
4703     case hci_spec::kLEClearAdvertisingSets: {
4704       OnLEClearAdvertisingSets();
4705       break;
4706     }
4707     case hci_spec::kLESetAdvertisingSetRandomAddress: {
4708       const auto& params =
4709           command_packet
4710               .view<pwemb::LESetAdvertisingSetRandomAddressCommandView>();
4711       OnLESetAdvertisingSetRandomAddress(params);
4712       break;
4713     }
4714     case hci_spec::kLESetExtendedAdvertisingParameters: {
4715       const auto& params =
4716           command_packet
4717               .view<pwemb::LESetExtendedAdvertisingParametersV1CommandView>();
4718       OnLESetExtendedAdvertisingParameters(params);
4719       break;
4720     }
4721     case hci_spec::kReadLocalSupportedControllerDelay: {
4722       const auto& params =
4723           command_packet
4724               .view<pwemb::ReadLocalSupportedControllerDelayCommandView>();
4725       OnReadLocalSupportedControllerDelay(params);
4726       break;
4727     }
4728     default: {
4729       bt_log(WARN, "fake-hci", "opcode: %#.4x", opcode);
4730       break;
4731     }
4732   }
4733 }
4734 }  // namespace bt::testing
4735