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