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