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