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/gap/bredr_connection_manager.h"
16
17 #include <pw_assert/check.h>
18 #include <pw_bytes/endian.h>
19 #include <pw_string/string_builder.h>
20
21 #include "pw_bluetooth_sapphire/internal/host/common/expiring_set.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
24 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection.h"
25 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection_request.h"
26 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_interrogator.h"
27 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
28 #include "pw_bluetooth_sapphire/internal/host/gap/legacy_pairing_state.h"
29 #include "pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
30 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
31 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
32 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
33 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h"
34 #include "pw_bluetooth_sapphire/internal/host/hci/sequential_command_runner.h"
35 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
36 #include "pw_bluetooth_sapphire/internal/host/l2cap/types.h"
37 #include "pw_bluetooth_sapphire/internal/host/transport/command_channel.h"
38 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
39
40 namespace bt::gap {
41
42 using ConnectionState = Peer::ConnectionState;
43
44 namespace {
45
46 const char* const kInspectRequestsNodeName = "connection_requests";
47 const char* const kInspectRequestNodeNamePrefix = "request_";
48 const char* const kInspectSecurityModeName = "security_mode";
49 const char* const kInspectConnectionsNodeName = "connections";
50 const char* const kInspectConnectionNodeNamePrefix = "connection_";
51 const char* const kInspectLastDisconnectedListName = "last_disconnected";
52 const char* const kInspectLastDisconnectedItemDurationPropertyName =
53 "duration_s";
54 const char* const kInspectLastDisconnectedItemPeerPropertyName = "peer_id";
55 const char* const kInspectTimestampPropertyName = "@time";
56 const char* const kInspectOutgoingNodeName = "outgoing";
57 const char* const kInspectIncomingNodeName = "incoming";
58 const char* const kInspectConnectionAttemptsNodeName = "connection_attempts";
59 const char* const kInspectSuccessfulConnectionsNodeName =
60 "successful_connections";
61 const char* const kInspectFailedConnectionsNodeName = "failed_connections";
62 const char* const kInspectInterrogationCompleteCountNodeName =
63 "interrogation_complete_count";
64 const char* const kInspectLocalApiRequestCountNodeName =
65 "disconnect_local_api_request_count";
66 const char* const kInspectInterrogationFailedCountNodeName =
67 "disconnect_interrogation_failed_count";
68 const char* const kInspectPairingFailedCountNodeName =
69 "disconnect_pairing_failed_count";
70 const char* const kInspectAclLinkErrorCountNodeName =
71 "disconnect_acl_link_error_count";
72 const char* const kInspectPeerDisconnectionCountNodeName =
73 "disconnect_peer_disconnection_count";
74
ReasonAsString(DisconnectReason reason)75 std::string ReasonAsString(DisconnectReason reason) {
76 switch (reason) {
77 case DisconnectReason::kApiRequest:
78 return "ApiRequest";
79 case DisconnectReason::kInterrogationFailed:
80 return "InterrogationFailed";
81 case DisconnectReason::kPairingFailed:
82 return "PairingFailed";
83 case DisconnectReason::kAclLinkError:
84 return "AclLinkError";
85 case DisconnectReason::kPeerDisconnection:
86 return "PeerDisconnection";
87 default:
88 return "<Unknown Reason>";
89 }
90 }
91
92 // This procedure can continue to operate independently of the existence of an
93 // BrEdrConnectionManager instance, which will begin to disable Page Scan as it
94 // shuts down.
SetPageScanEnabled(bool enabled,hci::Transport::WeakPtr hci,hci::ResultFunction<> cb)95 void SetPageScanEnabled(bool enabled,
96 hci::Transport::WeakPtr hci,
97 hci::ResultFunction<> cb) {
98 PW_DCHECK(cb);
99 auto read_enable = hci::CommandPacket::New<
100 pw::bluetooth::emboss::ReadScanEnableCommandWriter>(
101 hci_spec::kReadScanEnable);
102 auto finish_enable_cb = [enabled, hci, finish_cb = std::move(cb)](
103 auto, const hci::EventPacket& event) mutable {
104 if (HCI_IS_ERROR(event, WARN, "gap-bredr", "read scan enable failed")) {
105 finish_cb(event.ToResult());
106 return;
107 }
108
109 const auto params = event.view<
110 pw::bluetooth::emboss::ReadScanEnableCommandCompleteEventView>();
111 uint8_t scan_type = params.scan_enable().BackingStorage().ReadUInt();
112 if (enabled) {
113 scan_type |= static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
114 } else {
115 scan_type &= ~static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
116 }
117
118 auto write_enable = hci::CommandPacket::New<
119 pw::bluetooth::emboss::WriteScanEnableCommandWriter>(
120 hci_spec::kWriteScanEnable);
121 auto write_enable_view = write_enable.view_t();
122 write_enable_view.scan_enable().inquiry().Write(
123 scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kInquiry));
124 write_enable_view.scan_enable().page().Write(
125 scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage));
126 hci->command_channel()->SendCommand(
127 std::move(write_enable),
128 [callback = std::move(finish_cb)](auto,
129 const hci::EventPacket& response) {
130 callback(response.ToResult());
131 });
132 };
133 hci->command_channel()->SendCommand(std::move(read_enable),
134 std::move(finish_enable_cb));
135 }
136
137 } // namespace
138
AddEventHandler(const hci_spec::EventCode & code,hci::CommandChannel::EventCallback cb)139 hci::CommandChannel::EventHandlerId BrEdrConnectionManager::AddEventHandler(
140 const hci_spec::EventCode& code, hci::CommandChannel::EventCallback cb) {
141 auto self = weak_self_.GetWeakPtr();
142 hci::CommandChannel::EventHandlerId event_id = 0;
143 event_id = hci_->command_channel()->AddEventHandler(
144 code,
145 [self, emboss_event_cb = std::move(cb)](const hci::EventPacket& event) {
146 if (!self.is_alive()) {
147 return hci::CommandChannel::EventCallbackResult::kRemove;
148 }
149 return emboss_event_cb(event);
150 });
151 PW_DCHECK(event_id);
152 event_handler_ids_.push_back(event_id);
153 return event_id;
154 }
155
BrEdrConnectionManager(hci::Transport::WeakPtr hci,PeerCache * peer_cache,DeviceAddress local_address,hci::LocalAddressDelegate * low_energy_address_delegate,l2cap::ChannelManager * l2cap,bool use_interlaced_scan,bool local_secure_connections_supported,bool legacy_pairing_enabled,bool controller_remote_public_key_validation_supported,sm::BrEdrSecurityManagerFactory security_manager_factory,pw::async::Dispatcher & dispatcher)156 BrEdrConnectionManager::BrEdrConnectionManager(
157 hci::Transport::WeakPtr hci,
158 PeerCache* peer_cache,
159 DeviceAddress local_address,
160 hci::LocalAddressDelegate* low_energy_address_delegate,
161 l2cap::ChannelManager* l2cap,
162 bool use_interlaced_scan,
163 bool local_secure_connections_supported,
164 bool legacy_pairing_enabled,
165 bool controller_remote_public_key_validation_supported,
166 sm::BrEdrSecurityManagerFactory security_manager_factory,
167 pw::async::Dispatcher& dispatcher)
168 : hci_(std::move(hci)),
169 cache_(peer_cache),
170 local_address_(local_address),
171 l2cap_(l2cap),
172 deny_incoming_(dispatcher),
173 page_scan_interval_(0),
174 page_scan_window_(0),
175 use_interlaced_scan_(use_interlaced_scan),
176 local_secure_connections_supported_(local_secure_connections_supported),
177 legacy_pairing_enabled_(legacy_pairing_enabled),
178 controller_remote_public_key_validation_supported_(
179 controller_remote_public_key_validation_supported),
180 security_manager_factory_(std::move(security_manager_factory)),
181 low_energy_address_delegate_(low_energy_address_delegate),
182 dispatcher_(dispatcher),
183 weak_self_(this) {
184 PW_DCHECK(hci_.is_alive());
185 PW_DCHECK(cache_);
186 PW_DCHECK(l2cap_);
187
188 hci_cmd_runner_ = std::make_unique<hci::SequentialCommandRunner>(
189 hci_->command_channel()->AsWeakPtr());
190
191 // Register event handlers
192 AddEventHandler(
193 hci_spec::kAuthenticationCompleteEventCode,
194 fit::bind_member<&BrEdrConnectionManager::OnAuthenticationComplete>(
195 this));
196 AddEventHandler(
197 hci_spec::kConnectionCompleteEventCode,
198 fit::bind_member<&BrEdrConnectionManager::OnConnectionComplete>(this));
199 AddEventHandler(
200 hci_spec::kConnectionRequestEventCode,
201 fit::bind_member<&BrEdrConnectionManager::OnConnectionRequest>(this));
202 AddEventHandler(
203 hci_spec::kIOCapabilityRequestEventCode,
204 fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityRequest>(this));
205 AddEventHandler(
206 hci_spec::kIOCapabilityResponseEventCode,
207 fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityResponse>(this));
208 AddEventHandler(
209 hci_spec::kLinkKeyRequestEventCode,
210 fit::bind_member<&BrEdrConnectionManager::OnLinkKeyRequest>(this));
211 AddEventHandler(
212 hci_spec::kLinkKeyNotificationEventCode,
213 fit::bind_member<&BrEdrConnectionManager::OnLinkKeyNotification>(this));
214 AddEventHandler(
215 hci_spec::kSimplePairingCompleteEventCode,
216 fit::bind_member<&BrEdrConnectionManager::OnSimplePairingComplete>(this));
217 AddEventHandler(
218 hci_spec::kUserConfirmationRequestEventCode,
219 fit::bind_member<&BrEdrConnectionManager::OnUserConfirmationRequest>(
220 this));
221 AddEventHandler(
222 hci_spec::kUserPasskeyRequestEventCode,
223 fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyRequest>(this));
224 AddEventHandler(
225 hci_spec::kUserPasskeyNotificationEventCode,
226 fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyNotification>(
227 this));
228 AddEventHandler(
229 hci_spec::kRoleChangeEventCode,
230 fit::bind_member<&BrEdrConnectionManager::OnRoleChange>(this));
231 AddEventHandler(
232 hci_spec::kPinCodeRequestEventCode,
233 fit::bind_member<&BrEdrConnectionManager::OnPinCodeRequest>(this));
234
235 // Set the timeout for outbound connections explicitly to the spec default.
236 WritePageTimeout(
237 hci_spec::kDefaultPageTimeoutDuration, [](const hci::Result<> status) {
238 [[maybe_unused]] bool _ =
239 bt_is_error(status, WARN, "gap-bredr", "write page timeout failed");
240 });
241
242 // Set variable PIN type for legacy pairing
243 WritePinType(pw::bluetooth::emboss::PinType::VARIABLE);
244 }
245
~BrEdrConnectionManager()246 BrEdrConnectionManager::~BrEdrConnectionManager() {
247 // Disconnect any connections that we're holding.
248 connections_.clear();
249
250 if (!hci_.is_alive() || !hci_->command_channel()) {
251 return;
252 }
253
254 // Cancel the outstanding HCI_Connection_Request if not already cancelled
255 if (pending_request_ && pending_request_->Cancel()) {
256 SendCreateConnectionCancelCommand(pending_request_->peer_address());
257 }
258
259 // Become unconnectable
260 SetPageScanEnabled(/*enabled=*/false, hci_, [](const auto) {});
261
262 // Remove all event handlers
263 for (auto handler_id : event_handler_ids_) {
264 hci_->command_channel()->RemoveEventHandler(handler_id);
265 }
266 }
267
SetConnectable(bool connectable,hci::ResultFunction<> status_cb)268 void BrEdrConnectionManager::SetConnectable(bool connectable,
269 hci::ResultFunction<> status_cb) {
270 auto self = weak_self_.GetWeakPtr();
271 if (!connectable) {
272 auto not_connectable_cb = [self,
273 cb = std::move(status_cb)](const auto& status) {
274 if (self.is_alive()) {
275 self->page_scan_interval_ = 0;
276 self->page_scan_window_ = 0;
277 } else if (status.is_ok()) {
278 cb(ToResult(HostError::kFailed));
279 return;
280 }
281 cb(status);
282 };
283 SetPageScanEnabled(/*enabled=*/false, hci_, std::move(not_connectable_cb));
284 return;
285 }
286
287 WritePageScanSettings(
288 hci_spec::kPageScanR1Interval,
289 hci_spec::kPageScanR1Window,
290 use_interlaced_scan_,
291 [self, cb = std::move(status_cb)](const auto& status) mutable {
292 if (bt_is_error(
293 status, WARN, "gap-bredr", "Write Page Scan Settings failed")) {
294 cb(status);
295 return;
296 }
297 if (!self.is_alive()) {
298 cb(ToResult(HostError::kFailed));
299 return;
300 }
301 SetPageScanEnabled(/*enabled=*/true, self->hci_, std::move(cb));
302 });
303 }
304
SetPairingDelegate(PairingDelegate::WeakPtr delegate)305 void BrEdrConnectionManager::SetPairingDelegate(
306 PairingDelegate::WeakPtr delegate) {
307 pairing_delegate_ = std::move(delegate);
308 for (auto& [handle, connection] : connections_) {
309 connection.pairing_state_manager().SetPairingDelegate(pairing_delegate_);
310 }
311 }
312
GetPeerId(hci_spec::ConnectionHandle handle) const313 PeerId BrEdrConnectionManager::GetPeerId(
314 hci_spec::ConnectionHandle handle) const {
315 auto it = connections_.find(handle);
316 if (it == connections_.end()) {
317 return kInvalidPeerId;
318 }
319
320 auto* peer = cache_->FindByAddress(it->second.link().peer_address());
321 PW_DCHECK(peer, "Couldn't find peer for handle %#.4x", handle);
322 return peer->identifier();
323 }
324
Pair(PeerId peer_id,BrEdrSecurityRequirements security,hci::ResultFunction<> callback)325 void BrEdrConnectionManager::Pair(PeerId peer_id,
326 BrEdrSecurityRequirements security,
327 hci::ResultFunction<> callback) {
328 auto conn_pair = FindConnectionById(peer_id);
329 if (!conn_pair) {
330 bt_log(WARN,
331 "gap-bredr",
332 "can't pair to peer_id %s: connection not found",
333 bt_str(peer_id));
334 callback(ToResult(HostError::kNotFound));
335 return;
336 }
337
338 auto& [handle, connection] = *conn_pair;
339 auto pairing_callback = [pair_callback = std::move(callback)](
340 auto, hci::Result<> status) {
341 pair_callback(status);
342 };
343 connection->pairing_state_manager().InitiatePairing(
344 security, std::move(pairing_callback));
345 }
346
OpenL2capChannel(PeerId peer_id,l2cap::Psm psm,BrEdrSecurityRequirements security_reqs,l2cap::ChannelParameters params,l2cap::ChannelCallback cb)347 void BrEdrConnectionManager::OpenL2capChannel(
348 PeerId peer_id,
349 l2cap::Psm psm,
350 BrEdrSecurityRequirements security_reqs,
351 l2cap::ChannelParameters params,
352 l2cap::ChannelCallback cb) {
353 auto pairing_cb = [self = weak_self_.GetWeakPtr(),
354 peer_id,
355 psm,
356 params,
357 callback = std::move(cb)](auto status) mutable {
358 bt_log(TRACE,
359 "gap-bredr",
360 "got pairing status %s, %sreturning socket to %s",
361 bt_str(status),
362 status.is_ok() ? "" : "not ",
363 bt_str(peer_id));
364 if (status.is_error() || !self.is_alive()) {
365 // Report the failure to the user with a null channel.
366 callback(l2cap::Channel::WeakPtr());
367 return;
368 }
369
370 auto conn_pair = self->FindConnectionById(peer_id);
371 if (!conn_pair) {
372 bt_log(INFO,
373 "gap-bredr",
374 "can't open l2cap channel: connection not found (peer: %s)",
375 bt_str(peer_id));
376 callback(l2cap::Channel::WeakPtr());
377 return;
378 }
379 auto& [handle, connection] = *conn_pair;
380
381 connection->OpenL2capChannel(
382 psm, params, [open_cb = std::move(callback)](auto chan) {
383 open_cb(std::move(chan));
384 });
385 };
386
387 Pair(peer_id, security_reqs, std::move(pairing_cb));
388 }
389
AddServiceSearch(const UUID & uuid,std::unordered_set<sdp::AttributeId> attributes,BrEdrConnectionManager::SearchCallback callback)390 BrEdrConnectionManager::SearchId BrEdrConnectionManager::AddServiceSearch(
391 const UUID& uuid,
392 std::unordered_set<sdp::AttributeId> attributes,
393 BrEdrConnectionManager::SearchCallback callback) {
394 auto on_service_discovered =
395 [self = weak_self_.GetWeakPtr(), uuid, client_cb = std::move(callback)](
396 PeerId peer_id, auto& service_attributes) {
397 if (self.is_alive()) {
398 Peer* const peer = self->cache_->FindById(peer_id);
399 PW_CHECK(peer);
400 peer->MutBrEdr().AddService(uuid);
401 }
402 client_cb(peer_id, service_attributes);
403 };
404 SearchId new_id = discoverer_.AddSearch(
405 uuid, std::move(attributes), std::move(on_service_discovered));
406 for (auto& [handle, connection] : connections_) {
407 auto self = weak_self_.GetWeakPtr();
408 connection.OpenL2capChannel(
409 l2cap::kSDP,
410 l2cap::ChannelParameters(),
411 [self, peer_id = connection.peer_id(), search_id = new_id](
412 auto channel) {
413 if (!self.is_alive()) {
414 return;
415 }
416 if (!channel.is_alive()) {
417 // Likely interrogation is not complete. Search will be done at end
418 // of interrogation.
419 bt_log(INFO,
420 "gap",
421 "no l2cap channel for new search (peer: %s)",
422 bt_str(peer_id));
423 // Try anyway, maybe there's a channel open
424 self->discoverer_.SingleSearch(search_id, peer_id, nullptr);
425 return;
426 }
427 auto client =
428 sdp::Client::Create(std::move(channel), self->dispatcher_);
429 self->discoverer_.SingleSearch(search_id, peer_id, std::move(client));
430 });
431 }
432 return new_id;
433 }
434
RemoveServiceSearch(SearchId id)435 bool BrEdrConnectionManager::RemoveServiceSearch(SearchId id) {
436 return discoverer_.RemoveSearch(id);
437 }
438
439 std::optional<BrEdrConnectionManager::ScoRequestHandle>
OpenScoConnection(PeerId peer_id,bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter> parameters,sco::ScoConnectionManager::OpenConnectionCallback callback)440 BrEdrConnectionManager::OpenScoConnection(
441 PeerId peer_id,
442 bt::StaticPacket<
443 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
444 parameters,
445 sco::ScoConnectionManager::OpenConnectionCallback callback) {
446 auto conn_pair = FindConnectionById(peer_id);
447 if (!conn_pair) {
448 bt_log(WARN,
449 "gap-bredr",
450 "Can't open SCO connection to unconnected peer (peer: %s)",
451 bt_str(peer_id));
452 callback(fit::error(HostError::kNotFound));
453 return std::nullopt;
454 };
455 return conn_pair->second->OpenScoConnection(std::move(parameters),
456 std::move(callback));
457 }
458
459 std::optional<BrEdrConnectionManager::ScoRequestHandle>
AcceptScoConnection(PeerId peer_id,std::vector<bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>> parameters,sco::ScoConnectionManager::AcceptConnectionCallback callback)460 BrEdrConnectionManager::AcceptScoConnection(
461 PeerId peer_id,
462 std::vector<bt::StaticPacket<
463 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
464 parameters,
465 sco::ScoConnectionManager::AcceptConnectionCallback callback) {
466 auto conn_pair = FindConnectionById(peer_id);
467 if (!conn_pair) {
468 bt_log(WARN,
469 "gap-bredr",
470 "Can't accept SCO connection from unconnected peer (peer: %s)",
471 bt_str(peer_id));
472 callback(fit::error(HostError::kNotFound));
473 return std::nullopt;
474 };
475 return conn_pair->second->AcceptScoConnection(std::move(parameters),
476 std::move(callback));
477 }
478
Disconnect(PeerId peer_id,DisconnectReason reason)479 bool BrEdrConnectionManager::Disconnect(PeerId peer_id,
480 DisconnectReason reason) {
481 bt_log(INFO,
482 "gap-bredr",
483 "Disconnect Requested (reason %hhu - %s) (peer: %s)",
484 static_cast<unsigned char>(reason),
485 ReasonAsString(reason).c_str(),
486 bt_str(peer_id));
487
488 // TODO(fxbug.dev/42143836) - If a disconnect request is received when we have
489 // a pending connection, we should instead abort the connection, by either:
490 // * removing the request if it has not yet been processed
491 // * sending a cancel command to the controller and waiting for it to be
492 // processed
493 // * sending a cancel command, and if we already complete, then beginning a
494 // disconnect procedure
495 if (connection_requests_.find(peer_id) != connection_requests_.end()) {
496 bt_log(WARN,
497 "gap-bredr",
498 "Can't disconnect because it's being connected to (peer: %s)",
499 bt_str(peer_id));
500 return false;
501 }
502
503 auto conn_pair = FindConnectionById(peer_id);
504 if (!conn_pair) {
505 bt_log(INFO,
506 "gap-bredr",
507 "No need to disconnect: It is not connected (peer: %s)",
508 bt_str(peer_id));
509 return true;
510 }
511
512 auto [handle, connection] = *conn_pair;
513
514 const DeviceAddress& peer_addr = connection->link().peer_address();
515 if (reason == DisconnectReason::kApiRequest) {
516 bt_log(DEBUG,
517 "gap-bredr",
518 "requested disconnect from peer, cooldown for %llds (addr: %s)",
519 std::chrono::duration_cast<std::chrono::seconds>(
520 kLocalDisconnectCooldownDuration)
521 .count(),
522 bt_str(peer_addr));
523 deny_incoming_.add_until(
524 peer_addr, dispatcher_.now() + kLocalDisconnectCooldownDuration);
525 }
526
527 CleanUpConnection(
528 handle, std::move(connections_.extract(handle).mapped()), reason);
529 return true;
530 }
531
SetSecurityMode(BrEdrSecurityMode mode)532 void BrEdrConnectionManager::SetSecurityMode(BrEdrSecurityMode mode) {
533 security_mode_.Set(mode);
534
535 if (mode == BrEdrSecurityMode::SecureConnectionsOnly) {
536 // Disconnecting the peer must not be done while iterating through
537 // |connections_| as it removes the connection from |connections_|, hence
538 // the helper vector.
539 std::vector<PeerId> insufficiently_secure_peers;
540 for (auto& [_, connection] : connections_) {
541 if (connection.security_properties().level() !=
542 sm::SecurityLevel::kSecureAuthenticated) {
543 insufficiently_secure_peers.push_back(connection.peer_id());
544 }
545 }
546 for (PeerId id : insufficiently_secure_peers) {
547 bt_log(WARN,
548 "gap-bredr",
549 "Peer has insufficient security for Secure Connections Only mode. \
550 Closing connection for peer (%s)",
551 bt_str(id));
552 Disconnect(id, DisconnectReason::kPairingFailed);
553 }
554 }
555 for (auto& [_, connection] : connections_) {
556 connection.set_security_mode(mode);
557 }
558 }
559
AttachInspect(inspect::Node & parent,std::string name)560 void BrEdrConnectionManager::AttachInspect(inspect::Node& parent,
561 std::string name) {
562 inspect_node_ = parent.CreateChild(name);
563
564 security_mode_.AttachInspect(inspect_node_, kInspectSecurityModeName);
565
566 inspect_properties_.connections_node_ =
567 inspect_node_.CreateChild(kInspectConnectionsNodeName);
568 inspect_properties_.last_disconnected_list.AttachInspect(
569 inspect_node_, kInspectLastDisconnectedListName);
570
571 inspect_properties_.requests_node_ =
572 inspect_node_.CreateChild(kInspectRequestsNodeName);
573 for (auto& [_, req] : connection_requests_) {
574 req.AttachInspect(inspect_properties_.requests_node_,
575 inspect_properties_.requests_node_.UniqueName(
576 kInspectRequestNodeNamePrefix));
577 }
578
579 inspect_properties_.outgoing_.node_ =
580 inspect_node_.CreateChild(kInspectOutgoingNodeName);
581 inspect_properties_.outgoing_.connection_attempts_.AttachInspect(
582 inspect_properties_.outgoing_.node_, kInspectConnectionAttemptsNodeName);
583 inspect_properties_.outgoing_.successful_connections_.AttachInspect(
584 inspect_properties_.outgoing_.node_,
585 kInspectSuccessfulConnectionsNodeName);
586 inspect_properties_.outgoing_.failed_connections_.AttachInspect(
587 inspect_properties_.outgoing_.node_, kInspectFailedConnectionsNodeName);
588
589 inspect_properties_.incoming_.node_ =
590 inspect_node_.CreateChild(kInspectIncomingNodeName);
591 inspect_properties_.incoming_.connection_attempts_.AttachInspect(
592 inspect_properties_.incoming_.node_, kInspectConnectionAttemptsNodeName);
593 inspect_properties_.incoming_.successful_connections_.AttachInspect(
594 inspect_properties_.incoming_.node_,
595 kInspectSuccessfulConnectionsNodeName);
596 inspect_properties_.incoming_.failed_connections_.AttachInspect(
597 inspect_properties_.incoming_.node_, kInspectFailedConnectionsNodeName);
598
599 inspect_properties_.interrogation_complete_count_.AttachInspect(
600 inspect_node_, kInspectInterrogationCompleteCountNodeName);
601
602 inspect_properties_.disconnect_local_api_request_count_.AttachInspect(
603 inspect_node_, kInspectLocalApiRequestCountNodeName);
604 inspect_properties_.disconnect_interrogation_failed_count_.AttachInspect(
605 inspect_node_, kInspectInterrogationFailedCountNodeName);
606 inspect_properties_.disconnect_pairing_failed_count_.AttachInspect(
607 inspect_node_, kInspectPairingFailedCountNodeName);
608 inspect_properties_.disconnect_acl_link_error_count_.AttachInspect(
609 inspect_node_, kInspectAclLinkErrorCountNodeName);
610 inspect_properties_.disconnect_peer_disconnection_count_.AttachInspect(
611 inspect_node_, kInspectPeerDisconnectionCountNodeName);
612 }
613
WritePageTimeout(pw::chrono::SystemClock::duration page_timeout,hci::ResultFunction<> cb)614 void BrEdrConnectionManager::WritePageTimeout(
615 pw::chrono::SystemClock::duration page_timeout, hci::ResultFunction<> cb) {
616 PW_CHECK(page_timeout >= hci_spec::kMinPageTimeoutDuration);
617 PW_CHECK(page_timeout <= hci_spec::kMaxPageTimeoutDuration);
618
619 const int64_t raw_page_timeout =
620 page_timeout / hci_spec::kDurationPerPageTimeoutUnit;
621 PW_CHECK(raw_page_timeout >=
622 static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MIN));
623 PW_CHECK(raw_page_timeout <=
624 static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MAX));
625
626 auto write_page_timeout_cmd = hci::CommandPacket::New<
627 pw::bluetooth::emboss::WritePageTimeoutCommandWriter>(
628 hci_spec::kWritePageTimeout);
629 auto params = write_page_timeout_cmd.view_t();
630 params.page_timeout().Write(raw_page_timeout);
631
632 hci_->command_channel()->SendCommand(
633 std::move(write_page_timeout_cmd),
634 [callback = std::move(cb)](auto, const hci::EventPacket& event) {
635 callback(event.ToResult());
636 });
637 }
638
WritePageScanSettings(uint16_t interval,uint16_t window,bool interlaced,hci::ResultFunction<> cb)639 void BrEdrConnectionManager::WritePageScanSettings(uint16_t interval,
640 uint16_t window,
641 bool interlaced,
642 hci::ResultFunction<> cb) {
643 auto self = weak_self_.GetWeakPtr();
644 if (!hci_cmd_runner_->IsReady()) {
645 // TODO(jamuraa): could run the three "settings" commands in parallel and
646 // remove the sequence runner.
647 cb(ToResult(HostError::kInProgress));
648 return;
649 }
650
651 auto write_activity = hci::CommandPacket::New<
652 pw::bluetooth::emboss::WritePageScanActivityCommandWriter>(
653 hci_spec::kWritePageScanActivity);
654 auto activity_params = write_activity.view_t();
655 activity_params.page_scan_interval().Write(interval);
656 activity_params.page_scan_window().Write(window);
657
658 hci_cmd_runner_->QueueCommand(
659 std::move(write_activity),
660 [self, interval, window](const hci::EventPacket& event) {
661 if (!self.is_alive() ||
662 HCI_IS_ERROR(
663 event, WARN, "gap-bredr", "write page scan activity failed")) {
664 return;
665 }
666
667 self->page_scan_interval_ = interval;
668 self->page_scan_window_ = window;
669
670 bt_log(TRACE, "gap-bredr", "page scan activity updated");
671 });
672
673 const pw::bluetooth::emboss::PageScanType scan_type =
674 interlaced ? pw::bluetooth::emboss::PageScanType::INTERLACED_SCAN
675 : pw::bluetooth::emboss::PageScanType::STANDARD_SCAN;
676
677 auto write_type = hci::CommandPacket::New<
678 pw::bluetooth::emboss::WritePageScanTypeCommandWriter>(
679 hci_spec::kWritePageScanType);
680 auto type_params = write_type.view_t();
681 type_params.page_scan_type().Write(scan_type);
682
683 hci_cmd_runner_->QueueCommand(
684 std::move(write_type), [self, scan_type](const hci::EventPacket& event) {
685 if (!self.is_alive() ||
686 HCI_IS_ERROR(
687 event, WARN, "gap-bredr", "write page scan type failed")) {
688 return;
689 }
690
691 bt_log(TRACE, "gap-bredr", "page scan type updated");
692 self->page_scan_type_ = scan_type;
693 });
694
695 hci_cmd_runner_->RunCommands(std::move(cb));
696 }
697
WritePinType(pw::bluetooth::emboss::PinType pin_type)698 void BrEdrConnectionManager::WritePinType(
699 pw::bluetooth::emboss::PinType pin_type) {
700 auto write_pin_type_cmd =
701 hci::CommandPacket::New<pw::bluetooth::emboss::WritePinTypeCommandWriter>(
702 hci_spec::kWritePinType);
703 auto params = write_pin_type_cmd.view_t();
704 params.pin_type().Write(pin_type);
705
706 hci_->command_channel()->SendCommand(
707 std::move(write_pin_type_cmd), [](auto, const hci::EventPacket& event) {
708 [[maybe_unused]] bool _ = bt_is_error(
709 event.ToResult(), WARN, "gap-bredr", "Write PIN Type failed");
710 });
711 }
712
713 std::optional<BrEdrConnectionRequest*>
FindConnectionRequestById(PeerId peer_id)714 BrEdrConnectionManager::FindConnectionRequestById(PeerId peer_id) {
715 auto iter = connection_requests_.find(peer_id);
716 if (iter == connection_requests_.end()) {
717 return std::nullopt;
718 }
719
720 return &iter->second;
721 }
722
723 std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
FindConnectionById(PeerId peer_id)724 BrEdrConnectionManager::FindConnectionById(PeerId peer_id) {
725 auto it = std::find_if(
726 connections_.begin(), connections_.end(), [peer_id](const auto& c) {
727 return c.second.peer_id() == peer_id;
728 });
729
730 if (it == connections_.end()) {
731 return std::nullopt;
732 }
733
734 auto& [handle, conn] = *it;
735 return std::pair(handle, &conn);
736 }
737
738 std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
FindConnectionByAddress(const DeviceAddressBytes & bd_addr)739 BrEdrConnectionManager::FindConnectionByAddress(
740 const DeviceAddressBytes& bd_addr) {
741 auto* const peer = cache_->FindByAddress(
742 DeviceAddress(DeviceAddress::Type::kBREDR, bd_addr));
743 if (!peer) {
744 return std::nullopt;
745 }
746
747 return FindConnectionById(peer->identifier());
748 }
749
FindOrInitPeer(DeviceAddress addr)750 Peer* BrEdrConnectionManager::FindOrInitPeer(DeviceAddress addr) {
751 Peer* peer = cache_->FindByAddress(addr);
752 if (!peer) {
753 peer = cache_->NewPeer(addr, /*connectable*/ true);
754 }
755 return peer;
756 }
757
758 // Build connection state for a new connection and begin interrogation. L2CAP is
759 // not enabled for this link but pairing is allowed before interrogation
760 // completes.
InitializeConnection(DeviceAddress addr,hci_spec::ConnectionHandle connection_handle,pw::bluetooth::emboss::ConnectionRole role)761 void BrEdrConnectionManager::InitializeConnection(
762 DeviceAddress addr,
763 hci_spec::ConnectionHandle connection_handle,
764 pw::bluetooth::emboss::ConnectionRole role) {
765 auto link = std::make_unique<hci::BrEdrConnection>(
766 connection_handle, local_address_, addr, role, hci_);
767 Peer* const peer = FindOrInitPeer(addr);
768 auto peer_id = peer->identifier();
769 bt_log(DEBUG,
770 "gap-bredr",
771 "Beginning interrogation for peer %s",
772 bt_str(peer_id));
773
774 // We should never have more than one link to a given peer
775 PW_DCHECK(!FindConnectionById(peer_id));
776
777 // The controller has completed the HCI connection procedure, so the
778 // connection request can no longer be failed by a lower layer error. Now tie
779 // error reporting of the request to the lifetime of the connection state
780 // object (BrEdrConnection RAII).
781 auto node = connection_requests_.extract(peer_id);
782 auto request = node ? std::optional(std::move(node.mapped())) : std::nullopt;
783
784 const hci_spec::ConnectionHandle handle = link->handle();
785 auto send_auth_request_cb = [this, handle]() {
786 this->SendAuthenticationRequested(handle, [handle](auto status) {
787 bt_is_error(status,
788 WARN,
789 "gap-bredr",
790 "authentication requested command failed for %#.4x",
791 handle);
792 });
793 };
794 auto disconnect_cb = [this, handle, peer_id] {
795 bt_log(WARN,
796 "gap-bredr",
797 "Error occurred during pairing (handle %#.4x)",
798 handle);
799 Disconnect(peer_id, DisconnectReason::kPairingFailed);
800 };
801 auto on_peer_disconnect_cb = [this, connection = link.get()] {
802 OnPeerDisconnect(connection);
803 };
804
805 // Create the BrEdrConnection object and place into |connections_| map
806 auto [conn_iter, success] = connections_.try_emplace(
807 handle,
808 peer->GetWeakPtr(),
809 std::move(link),
810 std::move(send_auth_request_cb),
811 std::move(disconnect_cb),
812 std::move(on_peer_disconnect_cb),
813 l2cap_,
814 hci_,
815 std::move(request),
816 low_energy_address_delegate_,
817 controller_remote_public_key_validation_supported_,
818 security_manager_factory_,
819 dispatcher_);
820 PW_CHECK(success);
821
822 BrEdrConnection& connection = conn_iter->second;
823 connection.AttachInspect(inspect_properties_.connections_node_,
824 inspect_properties_.connections_node_.UniqueName(
825 kInspectConnectionNodeNamePrefix));
826
827 // Interrogate this peer to find out its version/capabilities.
828 connection.Interrogate(
829 [this, peer_weak_ptr = peer->GetWeakPtr(), handle](hci::Result<> result) {
830 if (bt_is_error(result,
831 WARN,
832 "gap-bredr",
833 "interrogation failed, dropping connection (peer: %s, "
834 "handle: %#.4x)",
835 bt_str(peer_weak_ptr->identifier()),
836 handle)) {
837 // If this connection was locally requested, requester(s) are notified
838 // by the disconnection.
839 Disconnect(peer_weak_ptr->identifier(),
840 DisconnectReason::kInterrogationFailed);
841 return;
842 }
843 bt_log(INFO,
844 "gap-bredr",
845 "interrogation complete (peer: %s, handle: %#.4x)",
846 bt_str(peer_weak_ptr->identifier()),
847 handle);
848 CompleteConnectionSetup(peer_weak_ptr, handle);
849 });
850
851 // If this was our in-flight request, close it
852 if (pending_request_ && addr == pending_request_->peer_address()) {
853 pending_request_.reset();
854 }
855
856 TryCreateNextConnection();
857 }
858
859 // Finish connection setup after a successful interrogation.
CompleteConnectionSetup(Peer::WeakPtr peer,hci_spec::ConnectionHandle handle)860 void BrEdrConnectionManager::CompleteConnectionSetup(
861 Peer::WeakPtr peer, hci_spec::ConnectionHandle handle) {
862 auto self = weak_self_.GetWeakPtr();
863 auto peer_id = peer->identifier();
864
865 auto connections_iter = connections_.find(handle);
866 if (connections_iter == connections_.end()) {
867 bt_log(WARN,
868 "gap-bredr",
869 "Connection to complete not found (peer: %s, handle: %#.4x)",
870 bt_str(peer_id),
871 handle);
872 return;
873 }
874 BrEdrConnection& conn_state = connections_iter->second;
875 if (conn_state.peer_id() != peer->identifier()) {
876 bt_log(WARN,
877 "gap-bredr",
878 "Connection switched peers! (now to %s), ignoring interrogation "
879 "result (peer: %s, "
880 "handle: %#.4x)",
881 bt_str(conn_state.peer_id()),
882 bt_str(peer_id),
883 handle);
884 return;
885 }
886
887 // Now that interrogation has successfully completed, check if the peer's
888 // feature bits indicate SSP support. If not, use LegacyPairingState to
889 // perform pairing if legacy pairing is enabled.
890 PairingStateType pairing_type = PairingStateType::kSecureSimplePairing;
891 if (!peer->IsSecureSimplePairingSupported()) {
892 if (!legacy_pairing_enabled_) {
893 bt_log(WARN,
894 "gap-bredr",
895 "Peer %s does not support SSP but legacy pairing is not enabled "
896 "so pairing cannot occur",
897 bt_str(peer_id));
898 return;
899 }
900 pairing_type = PairingStateType::kLegacyPairing;
901 }
902 conn_state.CreateOrUpdatePairingState(
903 pairing_type, pairing_delegate_, security_mode());
904
905 WeakPtr<hci::BrEdrConnection> const connection =
906 conn_state.link().GetWeakPtr();
907
908 auto error_handler =
909 [self, peer_id, connection_weak_ptr = connection->GetWeakPtr(), handle] {
910 if (!self.is_alive() || !connection_weak_ptr.is_alive()) {
911 return;
912 }
913 bt_log(
914 WARN,
915 "gap-bredr",
916 "Link error received, closing connection (peer: %s, handle: %#.4x)",
917 bt_str(peer_id),
918 handle);
919 self->Disconnect(peer_id, DisconnectReason::kAclLinkError);
920 };
921
922 // TODO(fxbug.dev/42113313): Implement this callback as a call to
923 // InitiatePairing().
924 auto security_callback = [peer_id](hci_spec::ConnectionHandle conn_handle,
925 sm::SecurityLevel,
926 auto cb) {
927 bt_log(INFO,
928 "gap-bredr",
929 "Ignoring security upgrade request; not implemented (peer: %s, "
930 "handle: %#.4x)",
931 bt_str(peer_id),
932 conn_handle);
933 cb(ToResult(HostError::kNotSupported));
934 };
935
936 // Register with L2CAP to handle services on the ACL signaling channel and get
937 // the SMP channel.
938 l2cap_->AddACLConnection(
939 handle,
940 connection->role(),
941 error_handler,
942 std::move(security_callback),
943 [self, handle](l2cap::ChannelManager::BrEdrFixedChannels channels) {
944 if (!self.is_alive()) {
945 return;
946 }
947 auto conn = self->connections_.find(handle);
948 if (conn == self->connections_.end()) {
949 return;
950 }
951 conn->second.SetSecurityManagerChannel(std::move(channels.smp));
952 });
953
954 // Remove from the denylist if we successfully connect.
955 deny_incoming_.remove(peer->address());
956
957 inspect_properties_.interrogation_complete_count_.Add(1);
958
959 if (discoverer_.search_count()) {
960 l2cap_->OpenL2capChannel(
961 handle,
962 l2cap::kSDP,
963 l2cap::ChannelParameters(),
964 [self, peer_id](auto channel) {
965 if (!self.is_alive()) {
966 return;
967 }
968 if (!channel.is_alive()) {
969 bt_log(ERROR,
970 "gap",
971 "failed to create l2cap channel for SDP (peer: %s)",
972 bt_str(peer_id));
973 return;
974 }
975 auto client =
976 sdp::Client::Create(std::move(channel), self->dispatcher_);
977 self->discoverer_.StartServiceDiscovery(peer_id, std::move(client));
978 });
979 }
980
981 conn_state.OnInterrogationComplete();
982 }
983
984 hci::CommandChannel::EventCallbackResult
OnAuthenticationComplete(const hci::EventPacket & event)985 BrEdrConnectionManager::OnAuthenticationComplete(
986 const hci::EventPacket& event) {
987 PW_DCHECK(event.event_code() == hci_spec::kAuthenticationCompleteEventCode);
988 auto params =
989 event.view<pw::bluetooth::emboss::AuthenticationCompleteEventView>();
990 hci_spec::ConnectionHandle connection_handle =
991 params.connection_handle().Read();
992 pw::bluetooth::emboss::StatusCode status = params.status().Read();
993
994 auto iter = connections_.find(connection_handle);
995 if (iter == connections_.end()) {
996 bt_log(INFO,
997 "gap-bredr",
998 "ignoring authentication complete (status: %s) for unknown "
999 "connection handle %#.04x",
1000 bt_str(ToResult(status)),
1001 connection_handle);
1002 return hci::CommandChannel::EventCallbackResult::kContinue;
1003 }
1004
1005 iter->second.pairing_state_manager().OnAuthenticationComplete(status);
1006 return hci::CommandChannel::EventCallbackResult::kContinue;
1007 }
1008
ExistsIncomingRequest(PeerId id)1009 bool BrEdrConnectionManager::ExistsIncomingRequest(PeerId id) {
1010 auto request = connection_requests_.find(id);
1011 return (request != connection_requests_.end() &&
1012 request->second.HasIncoming());
1013 }
1014
1015 hci::CommandChannel::EventCallbackResult
OnConnectionRequest(const hci::EventPacket & event)1016 BrEdrConnectionManager::OnConnectionRequest(const hci::EventPacket& event) {
1017 auto params = event.view<pw::bluetooth::emboss::ConnectionRequestEventView>();
1018 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1019 DeviceAddressBytes(params.bd_addr()));
1020 const pw::bluetooth::emboss::LinkType link_type = params.link_type().Read();
1021 const DeviceClass device_class(
1022 params.class_of_device().BackingStorage().ReadUInt());
1023
1024 if (link_type != pw::bluetooth::emboss::LinkType::ACL) {
1025 HandleNonAclConnectionRequest(addr, link_type);
1026 return hci::CommandChannel::EventCallbackResult::kContinue;
1027 }
1028
1029 if (deny_incoming_.contains(addr)) {
1030 bt_log(INFO,
1031 "gap-bredr",
1032 "rejecting incoming from peer (addr: %s) on cooldown",
1033 bt_str(addr));
1034 SendRejectConnectionRequest(
1035 addr,
1036 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
1037 return hci::CommandChannel::EventCallbackResult::kContinue;
1038 }
1039
1040 // Initialize the peer if it doesn't exist, to ensure we have allocated a
1041 // PeerId Do this after checking the denylist to avoid adding denied peers to
1042 // cache.
1043 auto peer = FindOrInitPeer(addr);
1044 auto peer_id = peer->identifier();
1045
1046 // In case of concurrent incoming requests from the same peer, reject all but
1047 // the first
1048 if (ExistsIncomingRequest(peer_id)) {
1049 bt_log(WARN,
1050 "gap-bredr",
1051 "rejecting duplicate incoming connection request (peer: %s, addr: "
1052 "%s, link_type: %s, "
1053 "class: %s)",
1054 bt_str(peer_id),
1055 bt_str(addr),
1056 hci_spec::LinkTypeToString(params.link_type().Read()),
1057 bt_str(device_class));
1058 SendRejectConnectionRequest(
1059 addr,
1060 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
1061 return hci::CommandChannel::EventCallbackResult::kContinue;
1062 }
1063
1064 // If we happen to be already connected (for example, if our outgoing raced,
1065 // or we received duplicate requests), we reject the request with
1066 // 'ConnectionAlreadyExists'
1067 if (FindConnectionById(peer_id)) {
1068 bt_log(WARN,
1069 "gap-bredr",
1070 "rejecting incoming connection request; already connected (peer: "
1071 "%s, addr: %s)",
1072 bt_str(peer_id),
1073 bt_str(addr));
1074 SendRejectConnectionRequest(
1075 addr, pw::bluetooth::emboss::StatusCode::CONNECTION_ALREADY_EXISTS);
1076 return hci::CommandChannel::EventCallbackResult::kContinue;
1077 }
1078
1079 // Accept the connection, performing a role switch. We receive a Connection
1080 // Complete event when the connection is complete, and finish the link then.
1081 bt_log(INFO,
1082 "gap-bredr",
1083 "accepting incoming connection (peer: %s, addr: %s, link_type: %s, "
1084 "class: %s)",
1085 bt_str(peer_id),
1086 bt_str(addr),
1087 hci_spec::LinkTypeToString(link_type),
1088 bt_str(device_class));
1089
1090 peer->MutBrEdr().SetIncomingRequest(params);
1091
1092 // Register that we're in the middle of an incoming request for this peer -
1093 // create a new request if one doesn't already exist
1094 auto [request, _] = connection_requests_.try_emplace(
1095 peer_id,
1096 dispatcher_,
1097 addr,
1098 peer_id,
1099 peer->MutBrEdr().RegisterInitializingConnection());
1100
1101 inspect_properties_.incoming_.connection_attempts_.Add(1);
1102
1103 request->second.BeginIncoming();
1104 request->second.AttachInspect(inspect_properties_.requests_node_,
1105 inspect_properties_.requests_node_.UniqueName(
1106 kInspectRequestNodeNamePrefix));
1107
1108 SendAcceptConnectionRequest(
1109 addr.value(),
1110 [addr, self = weak_self_.GetWeakPtr(), peer_id](auto status) {
1111 if (self.is_alive() && status.is_error()) {
1112 self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
1113 }
1114 });
1115 return hci::CommandChannel::EventCallbackResult::kContinue;
1116 }
1117
1118 hci::CommandChannel::EventCallbackResult
OnConnectionComplete(const hci::EventPacket & event)1119 BrEdrConnectionManager::OnConnectionComplete(const hci::EventPacket& event) {
1120 auto params =
1121 event.view<pw::bluetooth::emboss::ConnectionCompleteEventView>();
1122 if (params.link_type().Read() != pw::bluetooth::emboss::LinkType::ACL) {
1123 // Only ACL links are processed
1124 return hci::CommandChannel::EventCallbackResult::kContinue;
1125 }
1126
1127 // Initialize the peer if it doesn't exist, to ensure we have allocated a
1128 // PeerId (we should usually have a peer by this point)
1129 DeviceAddress addr(DeviceAddress::Type::kBREDR,
1130 DeviceAddressBytes(params.bd_addr()));
1131 auto peer = FindOrInitPeer(addr);
1132
1133 CompleteRequest(peer->identifier(),
1134 addr,
1135 event.ToResult(),
1136 params.connection_handle().Read());
1137 return hci::CommandChannel::EventCallbackResult::kContinue;
1138 }
1139
1140 // A request for a connection - from an upstream client _or_ a remote peer -
1141 // completed, successfully or not. This may be due to a ConnectionComplete event
1142 // being received, or due to a CommandStatus response being received in response
1143 // to a CreateConnection command
CompleteRequest(PeerId peer_id,DeviceAddress address,hci::Result<> status,hci_spec::ConnectionHandle handle)1144 void BrEdrConnectionManager::CompleteRequest(
1145 PeerId peer_id,
1146 DeviceAddress address,
1147 hci::Result<> status,
1148 hci_spec::ConnectionHandle handle) {
1149 auto req_iter = connection_requests_.find(peer_id);
1150 if (req_iter == connection_requests_.end()) {
1151 // Prevent logspam for rejected during cooldown.
1152 if (deny_incoming_.contains(address)) {
1153 return;
1154 }
1155 // This could potentially happen if the peer expired from the peer cache
1156 // during the connection procedure
1157 bt_log(INFO,
1158 "gap-bredr",
1159 "ConnectionComplete received with no known request (status: %s, "
1160 "peer: %s, addr: %s, "
1161 "handle: %#.4x)",
1162 bt_str(status),
1163 bt_str(peer_id),
1164 bt_str(address),
1165 handle);
1166 return;
1167 }
1168 auto& request = req_iter->second;
1169
1170 bool completes_outgoing_request =
1171 pending_request_ && pending_request_->peer_address() == address;
1172 bool has_incoming_request =
1173 !completes_outgoing_request && request.HasIncoming();
1174 bool failed = status.is_error();
1175
1176 const char* direction = completes_outgoing_request ? "outgoing" : "incoming";
1177 const char* result = status.is_ok() ? "complete" : "error";
1178 pw::bluetooth::emboss::ConnectionRole role =
1179 completes_outgoing_request
1180 ? pw::bluetooth::emboss::ConnectionRole::CENTRAL
1181 : pw::bluetooth::emboss::ConnectionRole::PERIPHERAL;
1182 if (request.role_change()) {
1183 role = request.role_change().value();
1184 }
1185
1186 bt_log(INFO,
1187 "gap-bredr",
1188 "%s connection %s (status: %s, role: %s, peer: %s, addr: %s, handle: "
1189 "%#.4x)",
1190 direction,
1191 result,
1192 bt_str(status),
1193 role == pw::bluetooth::emboss::ConnectionRole::CENTRAL ? "central"
1194 : "peripheral",
1195 bt_str(peer_id),
1196 bt_str(address),
1197 handle);
1198
1199 if (completes_outgoing_request) {
1200 // Determine the modified status in case of cancellation or timeout
1201 status = pending_request_->CompleteRequest(status);
1202 pending_request_.reset();
1203 } else {
1204 // This incoming connection arrived while we're trying to make an outgoing
1205 // connection; not an impossible coincidence but log it in case it's
1206 // interesting.
1207 // TODO(fxbug.dev/42173957): Added to investigate timing and can be removed
1208 // if it adds no value
1209 if (pending_request_) {
1210 bt_log(
1211 INFO,
1212 "gap-bredr",
1213 "doesn't complete pending outgoing connection to peer %s (addr: %s)",
1214 bt_str(pending_request_->peer_id()),
1215 bt_str(pending_request_->peer_address()));
1216 }
1217 // If this was an incoming attempt, clear it
1218 request.CompleteIncoming();
1219 }
1220
1221 if (failed) {
1222 if (request.HasIncoming() ||
1223 (!completes_outgoing_request && request.AwaitingOutgoing())) {
1224 // This request failed, but we're still waiting on either:
1225 // * an in-progress incoming request or
1226 // * to attempt our own outgoing request
1227 // Therefore we don't notify yet - instead take no action, and wait until
1228 // we finish those steps before completing the request and notifying
1229 // callbacks
1230 TryCreateNextConnection();
1231 return;
1232 }
1233 if (completes_outgoing_request && connection_requests_.size() == 1 &&
1234 request.ShouldRetry(status.error_value())) {
1235 bt_log(INFO,
1236 "gap-bredr",
1237 "no pending connection requests to other peers, so %sretrying "
1238 "outbound connection (peer: "
1239 "%s, addr: %s)",
1240 request.HasIncoming()
1241 ? "waiting for inbound request completion before potentially "
1242 : "",
1243 bt_str(peer_id),
1244 bt_str(address));
1245 // By not erasing |request| from |connection_requests_|, even if
1246 // TryCreateNextConnection does not directly retry because there's an
1247 // inbound request to the same peer, the retry will happen if the inbound
1248 // request completes unusuccessfully.
1249 TryCreateNextConnection();
1250 return;
1251 }
1252 if (completes_outgoing_request) {
1253 inspect_properties_.outgoing_.failed_connections_.Add(1);
1254 } else if (has_incoming_request) {
1255 inspect_properties_.incoming_.failed_connections_.Add(1);
1256 }
1257 request.NotifyCallbacks(status, [] { return nullptr; });
1258 connection_requests_.erase(req_iter);
1259 } else {
1260 if (completes_outgoing_request) {
1261 inspect_properties_.outgoing_.successful_connections_.Add(1);
1262 } else if (has_incoming_request) {
1263 inspect_properties_.incoming_.successful_connections_.Add(1);
1264 }
1265 // Callbacks will be notified when interrogation completes
1266 InitializeConnection(address, handle, role);
1267 }
1268
1269 TryCreateNextConnection();
1270 }
1271
OnPeerDisconnect(const hci::Connection * connection)1272 void BrEdrConnectionManager::OnPeerDisconnect(
1273 const hci::Connection* connection) {
1274 auto handle = connection->handle();
1275
1276 auto it = connections_.find(handle);
1277 if (it == connections_.end()) {
1278 bt_log(WARN,
1279 "gap-bredr",
1280 "disconnect from unknown connection handle %#.4x",
1281 handle);
1282 return;
1283 }
1284
1285 auto conn = std::move(it->second);
1286 connections_.erase(it);
1287
1288 bt_log(INFO,
1289 "gap-bredr",
1290 "peer disconnected (peer: %s, handle: %#.4x)",
1291 bt_str(conn.peer_id()),
1292 handle);
1293 CleanUpConnection(
1294 handle, std::move(conn), DisconnectReason::kPeerDisconnection);
1295 }
1296
CleanUpConnection(hci_spec::ConnectionHandle handle,BrEdrConnection conn,DisconnectReason reason)1297 void BrEdrConnectionManager::CleanUpConnection(
1298 hci_spec::ConnectionHandle handle,
1299 BrEdrConnection conn,
1300 DisconnectReason reason) {
1301 l2cap_->RemoveConnection(handle);
1302 RecordDisconnectInspect(conn, reason);
1303 // |conn| is destroyed when it goes out of scope.
1304 }
1305
1306 hci::CommandChannel::EventCallbackResult
OnIoCapabilityRequest(const hci::EventPacket & event)1307 BrEdrConnectionManager::OnIoCapabilityRequest(const hci::EventPacket& event) {
1308 const auto params =
1309 event.view<pw::bluetooth::emboss::IoCapabilityRequestEventView>();
1310 const DeviceAddressBytes addr(params.bd_addr());
1311
1312 auto conn_pair = FindConnectionByAddress(addr);
1313 if (!conn_pair) {
1314 bt_log(ERROR,
1315 "gap-bredr",
1316 "got %s for unconnected addr %s",
1317 __func__,
1318 bt_str(addr));
1319 SendIoCapabilityRequestNegativeReply(
1320 addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
1321 return hci::CommandChannel::EventCallbackResult::kContinue;
1322 }
1323 auto [handle, conn_ptr] = *conn_pair;
1324
1325 // If we receive an HCI_IO_Capability_Request event before interrogation is
1326 // complete, there will be no pairing state object so we need to create it now
1327 conn_ptr->CreateOrUpdatePairingState(PairingStateType::kSecureSimplePairing,
1328 pairing_delegate_,
1329 security_mode());
1330
1331 auto reply = conn_ptr->pairing_state_manager().OnIoCapabilityRequest();
1332
1333 if (!reply) {
1334 SendIoCapabilityRequestNegativeReply(
1335 addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
1336 return hci::CommandChannel::EventCallbackResult::kContinue;
1337 }
1338
1339 const pw::bluetooth::emboss::IoCapability io_capability = *reply;
1340
1341 // TODO(fxbug.dev/42138242): Add OOB status from PeerCache.
1342 const pw::bluetooth::emboss::OobDataPresent oob_data_present =
1343 pw::bluetooth::emboss::OobDataPresent::NOT_PRESENT;
1344
1345 // TODO(fxbug.dev/42075714): Determine this based on the service requirements.
1346 const pw::bluetooth::emboss::AuthenticationRequirements auth_requirements =
1347 io_capability == pw::bluetooth::emboss::IoCapability::NO_INPUT_NO_OUTPUT
1348 ? pw::bluetooth::emboss::AuthenticationRequirements::GENERAL_BONDING
1349 : pw::bluetooth::emboss::AuthenticationRequirements::
1350 MITM_GENERAL_BONDING; // inclusive-language: ignore
1351
1352 SendIoCapabilityRequestReply(
1353 addr, io_capability, oob_data_present, auth_requirements);
1354 return hci::CommandChannel::EventCallbackResult::kContinue;
1355 }
1356
1357 hci::CommandChannel::EventCallbackResult
OnIoCapabilityResponse(const hci::EventPacket & event)1358 BrEdrConnectionManager::OnIoCapabilityResponse(const hci::EventPacket& event) {
1359 const auto params =
1360 event.view<pw::bluetooth::emboss::IoCapabilityResponseEventView>();
1361 const DeviceAddressBytes addr(params.bd_addr());
1362
1363 auto conn_pair = FindConnectionByAddress(addr);
1364 if (!conn_pair) {
1365 bt_log(INFO,
1366 "gap-bredr",
1367 "got %s for unconnected addr %s",
1368 __func__,
1369 bt_str(addr));
1370 return hci::CommandChannel::EventCallbackResult::kContinue;
1371 }
1372
1373 // If we receive an HCI_IO_Capability_Response event before interrogation is
1374 // complete, there will be no pairing state object so we need to create it
1375 // now. If we previously created a pairing state object because there was
1376 // already an HCI_IO_Capability_Request event, then this method will no-op.
1377 conn_pair->second->CreateOrUpdatePairingState(
1378 PairingStateType::kSecureSimplePairing,
1379 pairing_delegate_,
1380 security_mode());
1381
1382 conn_pair->second->pairing_state_manager().OnIoCapabilityResponse(
1383 params.io_capability().Read());
1384 return hci::CommandChannel::EventCallbackResult::kContinue;
1385 }
1386
1387 hci::CommandChannel::EventCallbackResult
OnLinkKeyRequest(const hci::EventPacket & event)1388 BrEdrConnectionManager::OnLinkKeyRequest(const hci::EventPacket& event) {
1389 const auto params =
1390 event.view<pw::bluetooth::emboss::LinkKeyRequestEventView>();
1391 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1392 DeviceAddressBytes(params.bd_addr()));
1393 Peer* peer = cache_->FindByAddress(addr);
1394 if (!peer) {
1395 bt_log(WARN, "gap-bredr", "no peer with address %s found", bt_str(addr));
1396 SendLinkKeyRequestNegativeReply(addr.value());
1397 return hci::CommandChannel::EventCallbackResult::kContinue;
1398 }
1399
1400 PeerId peer_id = peer->identifier();
1401
1402 std::optional<hci_spec::LinkKey> link_key = std::nullopt;
1403
1404 std::optional<BrEdrConnectionRequest*> connection_req =
1405 FindConnectionRequestById(peer_id);
1406 if (!connection_req.has_value()) {
1407 // The ACL connection is complete, so either generate a new link key if this
1408 // is a new connection, or try to get the current link key (if it is valid)
1409 auto conn_pair = FindConnectionById(peer_id);
1410 if (!conn_pair) {
1411 bt_log(WARN,
1412 "gap-bredr",
1413 "Can't find current connection or connection request for peer %s",
1414 bt_str(peer_id));
1415 SendLinkKeyRequestNegativeReply(addr.value());
1416 return hci::CommandChannel::EventCallbackResult::kContinue;
1417 }
1418 auto& [handle, conn] = *conn_pair;
1419
1420 // TODO(fxbug.dev/355466957): Pairing state type is unknown if a
1421 // link key request is received after ACL connection is complete but before
1422 // interrogation is complete. Default to using SSP for now.
1423 if (!conn->interrogation_complete()) {
1424 conn->CreateOrUpdatePairingState(PairingStateType::kSecureSimplePairing,
1425 pairing_delegate_,
1426 security_mode());
1427 }
1428
1429 link_key = conn->pairing_state_manager().OnLinkKeyRequest();
1430 } else {
1431 // Legacy Pairing may occur before the ACL connection between two devices is
1432 // complete. If a link key is requested during connection setup, a
1433 // HCI_Link_Key_Request event may be received prior to the
1434 // HCI_Connection_Complete event (so no connection object will exist yet)
1435 // (Core Spec v5.4, Vol 2, Part F, 3.1).
1436
1437 bool outgoing_connection = connection_req.value()->AwaitingOutgoing();
1438
1439 // The HCI link is not yet established, so |link|, |auth_cb|, and
1440 // |status_cb| are not created yet. After the connection is complete, they
1441 // are initialized in |PairingStateManager|'s constructor.
1442 std::unique_ptr<LegacyPairingState> legacy_pairing_state =
1443 std::make_unique<LegacyPairingState>(
1444 peer->GetWeakPtr(), pairing_delegate_, outgoing_connection);
1445
1446 connection_req.value()->set_legacy_pairing_state(
1447 std::move(legacy_pairing_state));
1448
1449 link_key =
1450 connection_req.value()->legacy_pairing_state()->OnLinkKeyRequest();
1451 }
1452
1453 // If there is no valid link key, we start the pairing process (exchange IO
1454 // capabilities for SSP, request PIN code for legacy pairing)
1455 if (!link_key.has_value()) {
1456 SendLinkKeyRequestNegativeReply(addr.value());
1457 } else {
1458 SendLinkKeyRequestReply(addr.value(), link_key.value());
1459 }
1460 return hci::CommandChannel::EventCallbackResult::kContinue;
1461 }
1462
1463 hci::CommandChannel::EventCallbackResult
OnLinkKeyNotification(const hci::EventPacket & event)1464 BrEdrConnectionManager::OnLinkKeyNotification(const hci::EventPacket& event) {
1465 const auto params =
1466 event.view<pw::bluetooth::emboss::LinkKeyNotificationEventView>();
1467
1468 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1469 DeviceAddressBytes(params.bd_addr()));
1470 pw::bluetooth::emboss::KeyType key_type = params.key_type().Read();
1471
1472 auto* peer = cache_->FindByAddress(addr);
1473 if (!peer) {
1474 bt_log(WARN,
1475 "gap-bredr",
1476 "no known peer with address %s found; link key not stored (key "
1477 "type: %u)",
1478 bt_str(addr),
1479 static_cast<uint8_t>(key_type));
1480 cache_->LogBrEdrBondingEvent(false);
1481 return hci::CommandChannel::EventCallbackResult::kContinue;
1482 }
1483
1484 if (!legacy_pairing_enabled_ &&
1485 key_type == pw::bluetooth::emboss::KeyType::COMBINATION) {
1486 bt_log(WARN,
1487 "gap-bredr",
1488 "Got %u key type in link key notification for peer %s but legacy "
1489 "pairing is not enabled",
1490 static_cast<uint8_t>(key_type),
1491 bt_str(peer->identifier()));
1492 cache_->LogBrEdrBondingEvent(false);
1493 return hci::CommandChannel::EventCallbackResult::kContinue;
1494 }
1495
1496 bt_log(INFO,
1497 "gap-bredr",
1498 "got link key notification (key type: %u, peer: %s)",
1499 static_cast<uint8_t>(key_type),
1500 bt_str(peer->identifier()));
1501
1502 sm::SecurityProperties sec_props;
1503 if (key_type == pw::bluetooth::emboss::KeyType::CHANGED_COMBINATION_KEY) {
1504 if (!peer->bredr() || !peer->bredr()->bonded()) {
1505 bt_log(WARN,
1506 "gap-bredr",
1507 "can't update link key of unbonded peer %s",
1508 bt_str(peer->identifier()));
1509 cache_->LogBrEdrBondingEvent(false);
1510 return hci::CommandChannel::EventCallbackResult::kContinue;
1511 }
1512
1513 // Reuse current properties
1514 PW_DCHECK(peer->bredr()->link_key());
1515 sec_props = peer->bredr()->link_key()->security();
1516 key_type =
1517 static_cast<pw::bluetooth::emboss::KeyType>(sec_props.GetLinkKeyType());
1518 } else {
1519 sec_props =
1520 sm::SecurityProperties(static_cast<hci_spec::LinkKeyType>(key_type));
1521 }
1522
1523 auto peer_id = peer->identifier();
1524
1525 UInt128 key_value;
1526 ::emboss::support::ReadWriteContiguousBuffer(&key_value)
1527 .CopyFrom(params.link_key().value().BackingStorage(), key_value.size());
1528
1529 hci_spec::LinkKey hci_key(key_value, 0, 0);
1530 sm::LTK key(sec_props, hci_key);
1531
1532 auto handle = FindConnectionById(peer_id);
1533 if (!handle) {
1534 std::optional<BrEdrConnectionRequest*> request =
1535 FindConnectionRequestById(peer_id);
1536 if (!request) {
1537 bt_log(WARN,
1538 "gap-bredr",
1539 "Can't find current connection or connection request for peer %s",
1540 bt_str(peer_id));
1541 } else {
1542 // The connection request's legacy pairing state object must exist at this
1543 // point since we created it in the request's constructor.
1544 PW_CHECK(request.value()->legacy_pairing_state());
1545 request.value()->legacy_pairing_state()->OnLinkKeyNotification(
1546 key_value, static_cast<hci_spec::LinkKeyType>(key_type));
1547 }
1548 } else {
1549 handle->second->link().set_link_key(
1550 hci_key, static_cast<hci_spec::LinkKeyType>(key_type));
1551 handle->second->pairing_state_manager().OnLinkKeyNotification(
1552 key_value,
1553 static_cast<hci_spec::LinkKeyType>(key_type),
1554 local_secure_connections_supported_);
1555 }
1556
1557 if (cache_->StoreBrEdrBond(addr, key)) {
1558 cache_->LogBrEdrBondingEvent(true);
1559 } else {
1560 cache_->LogBrEdrBondingEvent(false);
1561 bt_log(ERROR,
1562 "gap-bredr",
1563 "failed to cache bonding data (peer: %s)",
1564 bt_str(peer_id));
1565 }
1566 return hci::CommandChannel::EventCallbackResult::kContinue;
1567 }
1568
1569 hci::CommandChannel::EventCallbackResult
OnSimplePairingComplete(const hci::EventPacket & event_packet)1570 BrEdrConnectionManager::OnSimplePairingComplete(
1571 const hci::EventPacket& event_packet) {
1572 auto params =
1573 event_packet
1574 .view<pw::bluetooth::emboss::SimplePairingCompleteEventView>();
1575 DeviceAddressBytes bd_addr = DeviceAddressBytes(params.bd_addr());
1576
1577 auto conn_pair = FindConnectionByAddress(bd_addr);
1578 if (!conn_pair) {
1579 bt_log(WARN,
1580 "gap-bredr",
1581 "got Simple Pairing Complete (status: %s) for unconnected addr %s",
1582 bt_str(ToResult(params.status().Read())),
1583 bt_str(bd_addr));
1584 return hci::CommandChannel::EventCallbackResult::kContinue;
1585 }
1586 conn_pair->second->pairing_state_manager().OnSimplePairingComplete(
1587 params.status().Read());
1588 return hci::CommandChannel::EventCallbackResult::kContinue;
1589 }
1590
1591 hci::CommandChannel::EventCallbackResult
OnUserConfirmationRequest(const hci::EventPacket & event_packet)1592 BrEdrConnectionManager::OnUserConfirmationRequest(
1593 const hci::EventPacket& event_packet) {
1594 auto params =
1595 event_packet
1596 .view<pw::bluetooth::emboss::UserConfirmationRequestEventView>();
1597 DeviceAddressBytes bd_addr = DeviceAddressBytes(params.bd_addr());
1598
1599 auto conn_pair = FindConnectionByAddress(bd_addr);
1600 if (!conn_pair) {
1601 bt_log(WARN,
1602 "gap-bredr",
1603 "got %s for unconnected addr %s",
1604 __func__,
1605 bt_str(bd_addr));
1606 SendUserConfirmationRequestNegativeReply(bd_addr);
1607 return hci::CommandChannel::EventCallbackResult::kContinue;
1608 }
1609
1610 auto confirm_cb = [self = weak_self_.GetWeakPtr(), bd_addr](bool confirm) {
1611 if (!self.is_alive()) {
1612 return;
1613 }
1614
1615 if (confirm) {
1616 self->SendUserConfirmationRequestReply(bd_addr);
1617 } else {
1618 self->SendUserConfirmationRequestNegativeReply(bd_addr);
1619 }
1620 };
1621 conn_pair->second->pairing_state_manager().OnUserConfirmationRequest(
1622 params.numeric_value().Read(), std::move(confirm_cb));
1623 return hci::CommandChannel::EventCallbackResult::kContinue;
1624 }
1625
1626 hci::CommandChannel::EventCallbackResult
OnUserPasskeyRequest(const hci::EventPacket & event_packet)1627 BrEdrConnectionManager::OnUserPasskeyRequest(
1628 const hci::EventPacket& event_packet) {
1629 auto params =
1630 event_packet.view<pw::bluetooth::emboss::UserPasskeyRequestEventView>();
1631 DeviceAddressBytes bd_addr = DeviceAddressBytes(params.bd_addr());
1632
1633 auto conn_pair = FindConnectionByAddress(bd_addr);
1634 if (!conn_pair) {
1635 bt_log(WARN,
1636 "gap-bredr",
1637 "got %s for unconnected addr %s",
1638 __func__,
1639 bt_str(bd_addr));
1640 SendUserPasskeyRequestNegativeReply(bd_addr);
1641 return hci::CommandChannel::EventCallbackResult::kContinue;
1642 }
1643
1644 auto passkey_cb = [self = weak_self_.GetWeakPtr(),
1645 bd_addr](std::optional<uint32_t> passkey) {
1646 if (!self.is_alive()) {
1647 return;
1648 }
1649
1650 if (passkey) {
1651 self->SendUserPasskeyRequestReply(bd_addr, *passkey);
1652 } else {
1653 self->SendUserPasskeyRequestNegativeReply(bd_addr);
1654 }
1655 };
1656 conn_pair->second->pairing_state_manager().OnUserPasskeyRequest(
1657 std::move(passkey_cb));
1658 return hci::CommandChannel::EventCallbackResult::kContinue;
1659 }
1660
1661 hci::CommandChannel::EventCallbackResult
OnUserPasskeyNotification(const hci::EventPacket & event_packet)1662 BrEdrConnectionManager::OnUserPasskeyNotification(
1663 const hci::EventPacket& event_packet) {
1664 auto params =
1665 event_packet
1666 .view<pw::bluetooth::emboss::UserPasskeyNotificationEventView>();
1667 DeviceAddressBytes bd_addr = DeviceAddressBytes(params.bd_addr());
1668
1669 auto conn_pair = FindConnectionByAddress(bd_addr);
1670 if (!conn_pair) {
1671 bt_log(WARN,
1672 "gap-bredr",
1673 "got %s for unconnected addr %s",
1674 __func__,
1675 bt_str(bd_addr));
1676 return hci::CommandChannel::EventCallbackResult::kContinue;
1677 }
1678 conn_pair->second->pairing_state_manager().OnUserPasskeyNotification(
1679 params.passkey().Read());
1680 return hci::CommandChannel::EventCallbackResult::kContinue;
1681 }
1682
OnRoleChange(const hci::EventPacket & event)1683 hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnRoleChange(
1684 const hci::EventPacket& event) {
1685 const auto params = event.view<pw::bluetooth::emboss::RoleChangeEventView>();
1686 const DeviceAddress address(DeviceAddress::Type::kBREDR,
1687 DeviceAddressBytes(params.bd_addr()));
1688 Peer* peer = cache_->FindByAddress(address);
1689 if (!peer) {
1690 bt_log(WARN,
1691 "gap-bredr",
1692 "got %s for unknown peer (address: %s)",
1693 __func__,
1694 bt_str(address));
1695 return hci::CommandChannel::EventCallbackResult::kContinue;
1696 }
1697 PeerId peer_id = peer->identifier();
1698
1699 const pw::bluetooth::emboss::ConnectionRole new_role = params.role().Read();
1700
1701 // When a role change is requested in the HCI_Accept_Connection_Request
1702 // command, a HCI_Role_Change event may be received prior to the
1703 // HCI_Connection_Complete event (so no connection object will exist yet)
1704 // (Core Spec v5.2, Vol 2, Part F, Sec 3.1).
1705 auto request_iter = connection_requests_.find(peer_id);
1706 if (request_iter != connection_requests_.end()) {
1707 request_iter->second.set_role_change(new_role);
1708 return hci::CommandChannel::EventCallbackResult::kContinue;
1709 }
1710
1711 auto conn_pair = FindConnectionByAddress(address.value());
1712 if (!conn_pair) {
1713 bt_log(WARN,
1714 "gap-bredr",
1715 "got %s for unconnected peer %s",
1716 __func__,
1717 bt_str(peer_id));
1718 return hci::CommandChannel::EventCallbackResult::kContinue;
1719 }
1720
1721 if (HCI_IS_ERROR(event,
1722 WARN,
1723 "gap-bredr",
1724 "role change failed and remains %s (peer: %s)",
1725 hci_spec::ConnectionRoleToString(new_role).c_str(),
1726 bt_str(peer_id))) {
1727 return hci::CommandChannel::EventCallbackResult::kContinue;
1728 }
1729
1730 bt_log(DEBUG,
1731 "gap-bredr",
1732 "role changed to %s (peer: %s)",
1733 hci_spec::ConnectionRoleToString(new_role).c_str(),
1734 bt_str(peer_id));
1735 conn_pair->second->link().set_role(new_role);
1736
1737 return hci::CommandChannel::EventCallbackResult::kContinue;
1738 }
1739
1740 hci::CommandChannel::EventCallbackResult
OnPinCodeRequest(const hci::EventPacket & event)1741 BrEdrConnectionManager::OnPinCodeRequest(const hci::EventPacket& event) {
1742 const auto params =
1743 event.view<pw::bluetooth::emboss::PinCodeRequestEventView>();
1744 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1745 DeviceAddressBytes(params.bd_addr()));
1746 Peer* peer = cache_->FindByAddress(addr);
1747 if (!peer) {
1748 bt_log(WARN, "gap-bredr", "no peer with address %s found", bt_str(addr));
1749 SendPinCodeRequestNegativeReply(addr.value());
1750 return hci::CommandChannel::EventCallbackResult::kContinue;
1751 }
1752
1753 PeerId peer_id = peer->identifier();
1754
1755 auto pin_code_cb =
1756 [this, self = weak_self_.GetWeakPtr(), addr_as_bytes = addr.value()](
1757 std::optional<uint16_t> pin) {
1758 if (!self.is_alive()) {
1759 return;
1760 }
1761
1762 if (pin) {
1763 // TODO(fxbug.dev/348700005): Support exponential backoff
1764 SendPinCodeRequestReply(addr_as_bytes, pin.value());
1765 } else {
1766 SendPinCodeRequestNegativeReply(addr_as_bytes);
1767 }
1768 };
1769
1770 std::optional<BrEdrConnectionRequest*> connection_req =
1771 FindConnectionRequestById(peer_id);
1772 if (!connection_req.has_value()) {
1773 // The ACL connection is complete so get the PIN code
1774 auto conn_pair = FindConnectionByAddress(addr.value());
1775 if (!conn_pair.has_value()) {
1776 bt_log(WARN,
1777 "gap-bredr",
1778 "Can't find current connection or connection request for peer %s",
1779 bt_str(addr));
1780 SendPinCodeRequestNegativeReply(addr.value());
1781 return hci::CommandChannel::EventCallbackResult::kContinue;
1782 }
1783 auto [handle, conn_ptr] = *conn_pair;
1784
1785 if (conn_ptr->pairing_state_manager().secure_simple_pairing_state()) {
1786 // TODO(fxbug.dev/355466957): If a SecureSimplePairingState object
1787 // already exists for this connection, we have the following edge case: we
1788 // received an HCI_Link_Key_Request event after ACL connection was
1789 // complete but before interrogation was complete. We temporarily default
1790 // to SSP which causes this error when it is actually legacy pairing.
1791
1792 SendPinCodeRequestNegativeReply(addr.value());
1793 return hci::CommandChannel::EventCallbackResult::kContinue;
1794 }
1795
1796 // If we receive an HCI_PIN_Code_Request event before interrogation is
1797 // complete, there will be no pairing state object so we need to create it
1798 // now
1799 conn_ptr->CreateOrUpdatePairingState(
1800 PairingStateType::kLegacyPairing, pairing_delegate_, security_mode());
1801
1802 conn_ptr->pairing_state_manager().OnPinCodeRequest(std::move(pin_code_cb));
1803 } else {
1804 // Legacy Pairing may occur before the ACL connection between two devices is
1805 // complete. If a PIN code is requested during connection setup, a
1806 // HCI_PIN_Code_Request event may be received prior to the
1807 // HCI_Connection_Complete event (so no connection object will exist yet)
1808 // (Core Spec v5.4, Vol 2, Part F, Sec 3.1).
1809
1810 // If we already created a LegacyPairingState object in |OnLinkKeyRequest|,
1811 // don't recreate another one.
1812 if (!connection_req.value()->legacy_pairing_state()) {
1813 bool outgoing_connection = connection_req.value()->AwaitingOutgoing();
1814
1815 // The HCI link is not yet established, so |link|, |auth_cb|, and
1816 // |status_cb| are not created yet. After the connection is complete, they
1817 // are initialized in |PairingStateManager|'s constructor.
1818 std::unique_ptr<LegacyPairingState> legacy_pairing_state =
1819 std::make_unique<LegacyPairingState>(
1820 peer->GetWeakPtr(), pairing_delegate_, outgoing_connection);
1821
1822 connection_req.value()->set_legacy_pairing_state(
1823 std::move(legacy_pairing_state));
1824 }
1825
1826 connection_req.value()->legacy_pairing_state()->OnPinCodeRequest(
1827 std::move(pin_code_cb));
1828 }
1829
1830 return hci::CommandChannel::EventCallbackResult::kContinue;
1831 }
1832
HandleNonAclConnectionRequest(const DeviceAddress & addr,pw::bluetooth::emboss::LinkType link_type)1833 void BrEdrConnectionManager::HandleNonAclConnectionRequest(
1834 const DeviceAddress& addr, pw::bluetooth::emboss::LinkType link_type) {
1835 PW_DCHECK(link_type != pw::bluetooth::emboss::LinkType::ACL);
1836
1837 // Initialize the peer if it doesn't exist, to ensure we have allocated a
1838 // PeerId
1839 auto peer = FindOrInitPeer(addr);
1840 auto peer_id = peer->identifier();
1841
1842 if (link_type != pw::bluetooth::emboss::LinkType::SCO &&
1843 link_type != pw::bluetooth::emboss::LinkType::ESCO) {
1844 bt_log(WARN,
1845 "gap-bredr",
1846 "reject unsupported connection type %s (peer: %s, addr: %s)",
1847 hci_spec::LinkTypeToString(link_type),
1848 bt_str(peer_id),
1849 bt_str(addr));
1850 SendRejectConnectionRequest(
1851 addr,
1852 pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
1853 return;
1854 }
1855
1856 auto conn_pair = FindConnectionByAddress(addr.value());
1857 if (!conn_pair) {
1858 bt_log(WARN,
1859 "gap-bredr",
1860 "rejecting (e)SCO connection request for peer that is not connected "
1861 "(peer: %s, addr: %s)",
1862 bt_str(peer_id),
1863 bt_str(addr));
1864 SendRejectSynchronousRequest(
1865 addr,
1866 pw::bluetooth::emboss::StatusCode::UNACCEPTABLE_CONNECTION_PARAMETERS);
1867 return;
1868 }
1869
1870 // The ScoConnectionManager owned by the BrEdrConnection will respond.
1871 bt_log(DEBUG,
1872 "gap-bredr",
1873 "SCO request ignored, handled by ScoConnectionManager (peer: %s, "
1874 "addr: %s)",
1875 bt_str(peer_id),
1876 bt_str(addr));
1877 }
1878
Connect(PeerId peer_id,ConnectResultCallback on_connection_result)1879 bool BrEdrConnectionManager::Connect(
1880 PeerId peer_id, ConnectResultCallback on_connection_result) {
1881 Peer* peer = cache_->FindById(peer_id);
1882 if (!peer) {
1883 bt_log(WARN,
1884 "gap-bredr",
1885 "%s: peer not found (peer: %s)",
1886 __func__,
1887 bt_str(peer_id));
1888 return false;
1889 }
1890
1891 if (peer->technology() == TechnologyType::kLowEnergy) {
1892 bt_log(
1893 ERROR, "gap-bredr", "peer does not support BrEdr: %s", bt_str(*peer));
1894 return false;
1895 }
1896
1897 // Succeed immediately or after interrogation if there is already an active
1898 // connection.
1899 auto conn_pair = FindConnectionById(peer_id);
1900 if (conn_pair) {
1901 conn_pair->second->AddRequestCallback(std::move(on_connection_result));
1902 return true;
1903 }
1904
1905 // Actively trying to connect to this peer means we can remove it from the
1906 // denylist.
1907 deny_incoming_.remove(peer->address());
1908
1909 // If we are already waiting to connect to |peer_id| then we store
1910 // |on_connection_result| to be processed after the connection attempt
1911 // completes (in either success of failure).
1912 auto pending_iter = connection_requests_.find(peer_id);
1913 if (pending_iter != connection_requests_.end()) {
1914 pending_iter->second.AddCallback(std::move(on_connection_result));
1915 return true;
1916 }
1917 // If we are not already connected or pending, initiate a new connection
1918 auto [request_iter, _] = connection_requests_.try_emplace(
1919 peer_id,
1920 dispatcher_,
1921 peer->address(),
1922 peer_id,
1923 peer->MutBrEdr().RegisterInitializingConnection(),
1924 std::move(on_connection_result));
1925 request_iter->second.AttachInspect(
1926 inspect_properties_.requests_node_,
1927 inspect_properties_.requests_node_.UniqueName(
1928 kInspectRequestNodeNamePrefix));
1929
1930 TryCreateNextConnection();
1931
1932 return true;
1933 }
1934
TryCreateNextConnection()1935 void BrEdrConnectionManager::TryCreateNextConnection() {
1936 // There can only be one outstanding BrEdr CreateConnection request at a time
1937 if (pending_request_) {
1938 return;
1939 }
1940
1941 // Find next outgoing BR/EDR request if available
1942 auto is_bredr_and_outgoing = [this](const auto& key_val) {
1943 PeerId peer_id = key_val.first;
1944 const BrEdrConnectionRequest* request = &key_val.second;
1945 const Peer* peer = cache_->FindById(peer_id);
1946 return peer->bredr() && !request->HasIncoming();
1947 };
1948
1949 auto it = std::find_if(connection_requests_.begin(),
1950 connection_requests_.end(),
1951 is_bredr_and_outgoing);
1952 if (it == connection_requests_.end()) {
1953 return;
1954 }
1955
1956 PeerId peer_id = it->first;
1957 BrEdrConnectionRequest& request = it->second;
1958 const Peer* peer = cache_->FindById(peer_id);
1959
1960 auto self = weak_self_.GetWeakPtr();
1961 auto on_failure = [self, addr = request.address()](hci::Result<> status,
1962 PeerId id) {
1963 if (self.is_alive() && status.is_error()) {
1964 self->CompleteRequest(id, addr, status, /*handle=*/0);
1965 }
1966 };
1967 auto on_timeout = [self] {
1968 if (self.is_alive()) {
1969 self->OnRequestTimeout();
1970 }
1971 };
1972
1973 const std::optional<uint16_t> clock_offset = peer->bredr()->clock_offset();
1974 const std::optional<pw::bluetooth::emboss::PageScanRepetitionMode>
1975 page_scan_repetition_mode = peer->bredr()->page_scan_repetition_mode();
1976 pending_request_ =
1977 request.CreateHciConnectionRequest(hci_->command_channel(),
1978 clock_offset,
1979 page_scan_repetition_mode,
1980 std::move(on_timeout),
1981 std::move(on_failure),
1982 dispatcher_);
1983
1984 inspect_properties_.outgoing_.connection_attempts_.Add(1);
1985 }
1986
OnRequestTimeout()1987 void BrEdrConnectionManager::OnRequestTimeout() {
1988 if (pending_request_) {
1989 pending_request_->Timeout();
1990 SendCreateConnectionCancelCommand(pending_request_->peer_address());
1991 }
1992 }
1993
SendCreateConnectionCancelCommand(DeviceAddress addr)1994 void BrEdrConnectionManager::SendCreateConnectionCancelCommand(
1995 DeviceAddress addr) {
1996 auto cancel = hci::CommandPacket::New<
1997 pw::bluetooth::emboss::CreateConnectionCancelCommandWriter>(
1998 hci_spec::kCreateConnectionCancel);
1999 auto params = cancel.view_t();
2000 params.bd_addr().CopyFrom(addr.value().view());
2001 hci_->command_channel()->SendCommand(
2002 std::move(cancel), [](auto, const hci::EventPacket& event) {
2003 HCI_IS_ERROR(
2004 event, WARN, "hci-bredr", "failed to cancel connection request");
2005 });
2006 }
2007
SendAuthenticationRequested(hci_spec::ConnectionHandle handle,hci::ResultFunction<> cb)2008 void BrEdrConnectionManager::SendAuthenticationRequested(
2009 hci_spec::ConnectionHandle handle, hci::ResultFunction<> cb) {
2010 auto auth_request = hci::CommandPacket::New<
2011 pw::bluetooth::emboss::AuthenticationRequestedCommandWriter>(
2012 hci_spec::kAuthenticationRequested);
2013 auth_request.view_t().connection_handle().Write(handle);
2014
2015 // Complete on command status because Authentication Complete Event is already
2016 // registered.
2017 hci::CommandChannel::CommandCallback command_cb;
2018 if (cb) {
2019 command_cb = [callback = std::move(cb)](auto,
2020 const hci::EventPacket& event) {
2021 callback(event.ToResult());
2022 };
2023 }
2024 hci_->command_channel()->SendCommand(std::move(auth_request),
2025 std::move(command_cb),
2026 hci_spec::kCommandStatusEventCode);
2027 }
2028
SendIoCapabilityRequestReply(DeviceAddressBytes bd_addr,pw::bluetooth::emboss::IoCapability io_capability,pw::bluetooth::emboss::OobDataPresent oob_data_present,pw::bluetooth::emboss::AuthenticationRequirements auth_requirements,hci::ResultFunction<> cb)2029 void BrEdrConnectionManager::SendIoCapabilityRequestReply(
2030 DeviceAddressBytes bd_addr,
2031 pw::bluetooth::emboss::IoCapability io_capability,
2032 pw::bluetooth::emboss::OobDataPresent oob_data_present,
2033 pw::bluetooth::emboss::AuthenticationRequirements auth_requirements,
2034 hci::ResultFunction<> cb) {
2035 auto packet = hci::CommandPacket::New<
2036 pw::bluetooth::emboss::IoCapabilityRequestReplyCommandWriter>(
2037 hci_spec::kIOCapabilityRequestReply);
2038 auto params = packet.view_t();
2039 params.bd_addr().CopyFrom(bd_addr.view());
2040 params.io_capability().Write(io_capability);
2041 params.oob_data_present().Write(oob_data_present);
2042 params.authentication_requirements().Write(auth_requirements);
2043 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2044 }
2045
SendIoCapabilityRequestNegativeReply(DeviceAddressBytes bd_addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)2046 void BrEdrConnectionManager::SendIoCapabilityRequestNegativeReply(
2047 DeviceAddressBytes bd_addr,
2048 pw::bluetooth::emboss::StatusCode reason,
2049 hci::ResultFunction<> cb) {
2050 auto packet = hci::CommandPacket::New<
2051 pw::bluetooth::emboss::IoCapabilityRequestNegativeReplyCommandWriter>(
2052 hci_spec::kIOCapabilityRequestNegativeReply);
2053 auto params = packet.view_t();
2054 params.bd_addr().CopyFrom(bd_addr.view());
2055 params.reason().Write(reason);
2056 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2057 }
2058
SendUserConfirmationRequestReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)2059 void BrEdrConnectionManager::SendUserConfirmationRequestReply(
2060 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
2061 auto packet = hci::CommandPacket::New<
2062 pw::bluetooth::emboss::UserConfirmationRequestReplyCommandWriter>(
2063 hci_spec::kUserConfirmationRequestReply);
2064 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
2065 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2066 }
2067
SendUserConfirmationRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)2068 void BrEdrConnectionManager::SendUserConfirmationRequestNegativeReply(
2069 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
2070 auto packet = hci::CommandPacket::New<
2071 pw::bluetooth::emboss::UserConfirmationRequestNegativeReplyCommandWriter>(
2072 hci_spec::kUserConfirmationRequestNegativeReply);
2073 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
2074 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2075 }
2076
SendUserPasskeyRequestReply(DeviceAddressBytes bd_addr,uint32_t numeric_value,hci::ResultFunction<> cb)2077 void BrEdrConnectionManager::SendUserPasskeyRequestReply(
2078 DeviceAddressBytes bd_addr,
2079 uint32_t numeric_value,
2080 hci::ResultFunction<> cb) {
2081 auto packet = hci::CommandPacket::New<
2082 pw::bluetooth::emboss::UserPasskeyRequestReplyCommandWriter>(
2083 hci_spec::kUserPasskeyRequestReply);
2084 auto view = packet.view_t();
2085 view.bd_addr().CopyFrom(bd_addr.view());
2086 view.numeric_value().Write(numeric_value);
2087 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2088 }
2089
SendUserPasskeyRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)2090 void BrEdrConnectionManager::SendUserPasskeyRequestNegativeReply(
2091 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
2092 auto packet = hci::CommandPacket::New<
2093 pw::bluetooth::emboss::UserPasskeyRequestNegativeReplyCommandWriter>(
2094 hci_spec::kUserPasskeyRequestNegativeReply);
2095 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
2096 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2097 }
2098
SendLinkKeyRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)2099 void BrEdrConnectionManager::SendLinkKeyRequestNegativeReply(
2100 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
2101 auto negative_reply = hci::CommandPacket::New<
2102 pw::bluetooth::emboss::LinkKeyRequestNegativeReplyCommandWriter>(
2103 hci_spec::kLinkKeyRequestNegativeReply);
2104 auto negative_reply_params = negative_reply.view_t();
2105 negative_reply_params.bd_addr().CopyFrom(bd_addr.view());
2106 SendCommandWithStatusCallback(std::move(negative_reply), std::move(cb));
2107 }
2108
SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,hci_spec::LinkKey link_key,hci::ResultFunction<> cb)2109 void BrEdrConnectionManager::SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,
2110 hci_spec::LinkKey link_key,
2111 hci::ResultFunction<> cb) {
2112 auto reply = hci::CommandPacket::New<
2113 pw::bluetooth::emboss::LinkKeyRequestReplyCommandWriter>(
2114 hci_spec::kLinkKeyRequestReply);
2115 auto reply_params = reply.view_t();
2116 reply_params.bd_addr().CopyFrom(bd_addr.view());
2117
2118 auto link_key_value_view = link_key.view();
2119 reply_params.link_key().CopyFrom(link_key_value_view);
2120
2121 SendCommandWithStatusCallback(std::move(reply), std::move(cb));
2122 }
2123
2124 template <typename T>
SendCommandWithStatusCallback(T command_packet,hci::ResultFunction<> cb)2125 void BrEdrConnectionManager::SendCommandWithStatusCallback(
2126 T command_packet, hci::ResultFunction<> cb) {
2127 hci::CommandChannel::CommandCallback command_cb;
2128 if (cb) {
2129 command_cb = [callback = std::move(cb)](auto,
2130 const hci::EventPacket& event) {
2131 callback(event.ToResult());
2132 };
2133 }
2134 hci_->command_channel()->SendCommand(std::move(command_packet),
2135 std::move(command_cb));
2136 }
2137
SendAcceptConnectionRequest(DeviceAddressBytes addr,hci::ResultFunction<> cb)2138 void BrEdrConnectionManager::SendAcceptConnectionRequest(
2139 DeviceAddressBytes addr, hci::ResultFunction<> cb) {
2140 auto accept = hci::CommandPacket::New<
2141 pw::bluetooth::emboss::AcceptConnectionRequestCommandWriter>(
2142 hci_spec::kAcceptConnectionRequest);
2143 auto accept_params = accept.view_t();
2144 accept_params.bd_addr().CopyFrom(addr.view());
2145 // This role switch preference can fail. A HCI_Role_Change event will be
2146 // generated if the role switch is successful (Core Spec v5.2, Vol 2, Part F,
2147 // Sec 3.1).
2148 accept_params.role().Write(pw::bluetooth::emboss::ConnectionRole::CENTRAL);
2149
2150 hci::CommandChannel::CommandCallback command_cb;
2151 if (cb) {
2152 command_cb = [callback = std::move(cb)](auto,
2153 const hci::EventPacket& event) {
2154 callback(event.ToResult());
2155 };
2156 }
2157
2158 hci_->command_channel()->SendCommand(std::move(accept),
2159 std::move(command_cb),
2160 hci_spec::kCommandStatusEventCode);
2161 }
2162
SendRejectConnectionRequest(DeviceAddress addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)2163 void BrEdrConnectionManager::SendRejectConnectionRequest(
2164 DeviceAddress addr,
2165 pw::bluetooth::emboss::StatusCode reason,
2166 hci::ResultFunction<> cb) {
2167 auto reject = hci::CommandPacket::New<
2168 pw::bluetooth::emboss::RejectConnectionRequestCommandWriter>(
2169 hci_spec::kRejectConnectionRequest);
2170 auto reject_params = reject.view_t();
2171 reject_params.bd_addr().CopyFrom(addr.value().view());
2172 reject_params.reason().Write(reason);
2173
2174 hci::CommandChannel::CommandCallback command_cb;
2175 if (cb) {
2176 command_cb = [callback = std::move(cb)](auto,
2177 const hci::EventPacket& event) {
2178 callback(event.ToResult());
2179 };
2180 }
2181
2182 hci_->command_channel()->SendCommand(std::move(reject),
2183 std::move(command_cb),
2184 hci_spec::kCommandStatusEventCode);
2185 }
2186
SendRejectSynchronousRequest(DeviceAddress addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)2187 void BrEdrConnectionManager::SendRejectSynchronousRequest(
2188 DeviceAddress addr,
2189 pw::bluetooth::emboss::StatusCode reason,
2190 hci::ResultFunction<> cb) {
2191 auto reject = hci::CommandPacket::New<
2192 pw::bluetooth::emboss::RejectSynchronousConnectionRequestCommandWriter>(
2193 hci_spec::kRejectSynchronousConnectionRequest);
2194 auto reject_params = reject.view_t();
2195 reject_params.bd_addr().CopyFrom(addr.value().view());
2196 reject_params.reason().Write(reason);
2197
2198 hci::CommandChannel::CommandCallback command_cb;
2199 if (cb) {
2200 command_cb = [callback = std::move(cb)](auto,
2201 const hci::EventPacket& event) {
2202 callback(event.ToResult());
2203 };
2204 }
2205
2206 hci_->command_channel()->SendCommand(std::move(reject),
2207 std::move(command_cb),
2208 hci_spec::kCommandStatusEventCode);
2209 }
2210
SendPinCodeRequestReply(DeviceAddressBytes bd_addr,uint16_t pin_code,hci::ResultFunction<> cb)2211 void BrEdrConnectionManager::SendPinCodeRequestReply(DeviceAddressBytes bd_addr,
2212 uint16_t pin_code,
2213 hci::ResultFunction<> cb) {
2214 auto packet = hci::CommandPacket::New<
2215 pw::bluetooth::emboss::PinCodeRequestReplyCommandWriter>(
2216 hci_spec::kPinCodeRequestReply);
2217 auto params = packet.view_t();
2218 params.bd_addr().CopyFrom(bd_addr.view());
2219
2220 // 4-digit PIN codes are generated
2221 params.pin_code_length().Write(4);
2222
2223 MutableBufferView data_view(params.pin_code().BackingStorage().data(),
2224 params.pin_code().SizeInBytes());
2225 data_view.SetToZeros();
2226
2227 // Convert pin code int to string (4 digits + 1 digit for null character)
2228 pw::StringBuffer<5> builder;
2229 builder << pin_code;
2230 data_view.Write(BufferView(builder));
2231
2232 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2233 }
2234
SendPinCodeRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)2235 void BrEdrConnectionManager::SendPinCodeRequestNegativeReply(
2236 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
2237 auto packet = hci::CommandPacket::New<
2238 pw::bluetooth::emboss::PinCodeRequestNegativeReplyCommandWriter>(
2239 hci_spec::kPinCodeRequestNegativeReply);
2240 auto params = packet.view_t();
2241 params.bd_addr().CopyFrom(bd_addr.view());
2242 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
2243 }
2244
RecordDisconnectInspect(const BrEdrConnection & conn,DisconnectReason reason)2245 void BrEdrConnectionManager::RecordDisconnectInspect(
2246 const BrEdrConnection& conn, DisconnectReason reason) {
2247 // Add item to recent disconnections list.
2248 auto& inspect_item = inspect_properties_.last_disconnected_list.CreateItem();
2249 inspect_item.node.RecordString(kInspectLastDisconnectedItemPeerPropertyName,
2250 conn.peer_id().ToString());
2251 uint64_t conn_duration_s =
2252 std::chrono::duration_cast<std::chrono::seconds>(conn.duration()).count();
2253 inspect_item.node.RecordUint(kInspectLastDisconnectedItemDurationPropertyName,
2254 conn_duration_s);
2255
2256 int64_t time_ns = dispatcher_.now().time_since_epoch().count();
2257 inspect_item.node.RecordInt(kInspectTimestampPropertyName, time_ns);
2258
2259 switch (reason) {
2260 case DisconnectReason::kApiRequest:
2261 inspect_properties_.disconnect_local_api_request_count_.Add(1);
2262 break;
2263 case DisconnectReason::kInterrogationFailed:
2264 inspect_properties_.disconnect_interrogation_failed_count_.Add(1);
2265 break;
2266 case DisconnectReason::kPairingFailed:
2267 inspect_properties_.disconnect_pairing_failed_count_.Add(1);
2268 break;
2269 case DisconnectReason::kAclLinkError:
2270 inspect_properties_.disconnect_acl_link_error_count_.Add(1);
2271 break;
2272 case DisconnectReason::kPeerDisconnection:
2273 inspect_properties_.disconnect_peer_disconnection_count_.Add(1);
2274 break;
2275 default:
2276 break;
2277 }
2278 }
2279
2280 } // namespace bt::gap
2281