xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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