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