// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "bredr_connection_manager.h"

#include <lib/async/time.h>
#include <zircon/assert.h>

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/common/status.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/bredr_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/sequential_command_runner.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/status.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/types.h"

namespace bt::gap {

using std::unique_ptr;
using ConnectionState = Peer::ConnectionState;

namespace {

const char* const kInspectRequestsNodeName = "connection_requests";
const char* const kInspectRequestNodeNamePrefix = "request_";
const char* const kInspectConnectionsNodeName = "connections";
const char* const kInspectConnectionNodeNamePrefix = "connection_";
const char* const kInspectLastDisconnectedListName = "last_disconnected";
const char* const kInspectLastDisconnectedItemDurationPropertyName = "duration_s";
const char* const kInspectLastDisconnectedItemPeerPropertyName = "peer_id";
const char* const kInspectTimestampPropertyName = "@time";

std::string ReasonAsString(DisconnectReason reason) {
  switch (reason) {
    case DisconnectReason::kApiRequest:
      return "ApiRequest";
    case DisconnectReason::kInterrogationFailed:
      return "InterrogationFailed";
    case DisconnectReason::kPairingFailed:
      return "PairingFailed";
    case DisconnectReason::kAclLinkError:
      return "AclLinkError";
    default:
      return "<Unknown Reason>";
  }
}

// This procedure can continue to operate independently of the existence of an
// BrEdrConnectionManager instance, which will begin to disable Page Scan as it shuts down.
void SetPageScanEnabled(bool enabled, fxl::WeakPtr<hci::Transport> hci,
                        async_dispatcher_t* dispatcher, hci::StatusCallback cb) {
  ZX_DEBUG_ASSERT(cb);
  auto read_enable = hci::CommandPacket::New(hci::kReadScanEnable);
  auto finish_enable_cb = [enabled, hci, finish_cb = std::move(cb)](
                              auto, const hci::EventPacket& event) mutable {
    if (hci_is_error(event, WARN, "gap-bredr", "read scan enable failed")) {
      finish_cb(event.ToStatus());
      return;
    }

    auto params = event.return_params<hci::ReadScanEnableReturnParams>();
    uint8_t scan_type = params->scan_enable;
    if (enabled) {
      scan_type |= static_cast<uint8_t>(hci::ScanEnableBit::kPage);
    } else {
      scan_type &= ~static_cast<uint8_t>(hci::ScanEnableBit::kPage);
    }
    auto write_enable =
        hci::CommandPacket::New(hci::kWriteScanEnable, sizeof(hci::WriteScanEnableCommandParams));
    write_enable->mutable_payload<hci::WriteScanEnableCommandParams>()->scan_enable = scan_type;
    hci->command_channel()->SendCommand(
        std::move(write_enable),
        [cb = std::move(finish_cb)](auto, const hci::EventPacket& event) { cb(event.ToStatus()); });
  };
  hci->command_channel()->SendCommand(std::move(read_enable), std::move(finish_enable_cb));
}

}  // namespace

// An event signifying that a connection was completed by the controller
BrEdrConnectionManager::ConnectionComplete::ConnectionComplete(const hci::EventPacket& event) {
  ZX_ASSERT(event.event_code() == hci::kConnectionCompleteEventCode);
  const auto& params = event.params<hci::ConnectionCompleteEventParams>();
  handle = letoh16(params.connection_handle);
  addr = DeviceAddress(DeviceAddress::Type::kBREDR, params.bd_addr);
  status = hci::Status(params.status);
  link_type = params.link_type;
}

// An event signifying that an incoming connection is being requested by a peer
BrEdrConnectionManager::ConnectionRequestEvent::ConnectionRequestEvent(
    const hci::EventPacket& event) {
  ZX_ASSERT(event.event_code() == hci::kConnectionRequestEventCode);
  const auto& params = event.params<hci::ConnectionRequestEventParams>();
  addr = DeviceAddress(DeviceAddress::Type::kBREDR, params.bd_addr);
  link_type = params.link_type;
  class_of_device = params.class_of_device;
}

hci::CommandChannel::EventHandlerId BrEdrConnectionManager::AddEventHandler(
    const hci::EventCode& code, hci::CommandChannel::EventCallback cb) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto event_id = hci_->command_channel()->AddEventHandler(
      code, [self, callback = std::move(cb)](const auto& event) {
        if (self) {
          return callback(event);
        }
        return hci::CommandChannel::EventCallbackResult::kRemove;
      });
  ZX_DEBUG_ASSERT(event_id);
  event_handler_ids_.push_back(event_id);
  return event_id;
}

BrEdrConnectionManager::BrEdrConnectionManager(fxl::WeakPtr<hci::Transport> hci,
                                               PeerCache* peer_cache, DeviceAddress local_address,
                                               fbl::RefPtr<l2cap::L2cap> l2cap,
                                               bool use_interlaced_scan)
    : hci_(std::move(hci)),
      cache_(peer_cache),
      local_address_(local_address),
      l2cap_(l2cap),
      interrogator_(cache_, hci_),
      page_scan_interval_(0),
      page_scan_window_(0),
      use_interlaced_scan_(use_interlaced_scan),
      request_timeout_(kBrEdrCreateConnectionTimeout),
      dispatcher_(async_get_default_dispatcher()),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(hci_);
  ZX_DEBUG_ASSERT(cache_);
  ZX_DEBUG_ASSERT(l2cap_);
  ZX_DEBUG_ASSERT(dispatcher_);

  hci_cmd_runner_ = std::make_unique<hci::SequentialCommandRunner>(dispatcher_, hci_);

  // Register event handlers
  AddEventHandler(hci::kAuthenticationCompleteEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnAuthenticationComplete));
  AddEventHandler(hci::kConnectionCompleteEventCode, [this](const hci::EventPacket& event) {
    OnConnectionComplete(ConnectionComplete(event));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  });
  AddEventHandler(hci::kConnectionRequestEventCode, [this](const hci::EventPacket& event) {
    OnConnectionRequest(ConnectionRequestEvent(event));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  });
  AddEventHandler(hci::kIOCapabilityRequestEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnIoCapabilityRequest));
  AddEventHandler(hci::kIOCapabilityResponseEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnIoCapabilityResponse));
  AddEventHandler(hci::kLinkKeyRequestEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnLinkKeyRequest));
  AddEventHandler(hci::kLinkKeyNotificationEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnLinkKeyNotification));
  AddEventHandler(hci::kSimplePairingCompleteEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnSimplePairingComplete));
  AddEventHandler(hci::kUserConfirmationRequestEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnUserConfirmationRequest));
  AddEventHandler(hci::kUserPasskeyRequestEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnUserPasskeyRequest));
  AddEventHandler(hci::kUserPasskeyNotificationEventCode,
                  fit::bind_member(this, &BrEdrConnectionManager::OnUserPasskeyNotification));
}

BrEdrConnectionManager::~BrEdrConnectionManager() {
  if (pending_request_ && pending_request_->Cancel())
    SendCreateConnectionCancelCommand(pending_request_->peer_address());

  // Disconnect any connections that we're holding.
  connections_.clear();
  // Become unconnectable
  SetPageScanEnabled(/*enabled=*/false, hci_, dispatcher_, [](const auto) {});
  // Remove all event handlers
  for (auto handler_id : event_handler_ids_) {
    hci_->command_channel()->RemoveEventHandler(handler_id);
  }
}

void BrEdrConnectionManager::SetConnectable(bool connectable, hci::StatusCallback status_cb) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  if (!connectable) {
    auto not_connectable_cb = [self, cb = std::move(status_cb)](const auto& status) {
      if (self) {
        self->page_scan_interval_ = 0;
        self->page_scan_window_ = 0;
      } else if (status) {
        cb(hci::Status(HostError::kFailed));
        return;
      }
      cb(status);
    };
    SetPageScanEnabled(/*enabled=*/false, hci_, dispatcher_, std::move(not_connectable_cb));
    return;
  }

  WritePageScanSettings(
      hci::kPageScanR1Interval, hci::kPageScanR1Window, use_interlaced_scan_,
      [self, cb = std::move(status_cb)](const auto& status) mutable {
        if (bt_is_error(status, WARN, "gap-bredr", "Write Page Scan Settings failed")) {
          cb(status);
          return;
        }
        if (!self) {
          cb(hci::Status(HostError::kFailed));
          return;
        }
        SetPageScanEnabled(/*enabled=*/true, self->hci_, self->dispatcher_, std::move(cb));
      });
}

void BrEdrConnectionManager::SetPairingDelegate(fxl::WeakPtr<PairingDelegate> delegate) {
  pairing_delegate_ = std::move(delegate);
  for (auto& [handle, connection] : connections_) {
    connection.pairing_state().SetPairingDelegate(pairing_delegate_);
  }
}

PeerId BrEdrConnectionManager::GetPeerId(hci::ConnectionHandle handle) const {
  auto it = connections_.find(handle);
  if (it == connections_.end()) {
    return kInvalidPeerId;
  }

  auto* peer = cache_->FindByAddress(it->second.link().peer_address());
  ZX_DEBUG_ASSERT_MSG(peer, "Couldn't find peer for handle %#.4x", handle);
  return peer->identifier();
}

void BrEdrConnectionManager::Pair(PeerId peer_id, BrEdrSecurityRequirements security,
                                  hci::StatusCallback callback) {
  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "can't pair to peer_id %s: connection not found", bt_str(peer_id));
    callback(hci::Status(HostError::kNotFound));
    return;
  }
  auto& [handle, connection] = *conn_pair;
  auto pairing_callback = [pair_callback = std::move(callback)](auto, hci::Status status) {
    pair_callback(status);
  };
  connection->pairing_state().InitiatePairing(security, std::move(pairing_callback));
}

void BrEdrConnectionManager::OpenL2capChannel(PeerId peer_id, l2cap::PSM psm,
                                              BrEdrSecurityRequirements security_reqs,
                                              l2cap::ChannelParameters params,
                                              l2cap::ChannelCallback cb) {
  auto pairing_cb = [self = weak_ptr_factory_.GetWeakPtr(), peer_id, psm, params,
                     cb = std::move(cb)](auto status) mutable {
    bt_log(TRACE, "gap-bredr", "got pairing status %s, %sreturning socket to %s", bt_str(status),
           status ? "" : "not ", bt_str(peer_id));
    if (!status || !self) {
      // Report the failure to the user with a null channel.
      cb(nullptr);
      return;
    }

    auto conn_pair = self->FindConnectionById(peer_id);
    if (!conn_pair) {
      bt_log(INFO, "gap-bredr", "can't open l2cap channel: connection not found (peer: %s)",
             bt_str(peer_id));
      cb(nullptr);
      return;
    }
    auto& [handle, connection] = *conn_pair;

    connection->OpenL2capChannel(psm, params,
                                 [cb = std::move(cb)](auto chan) { cb(std::move(chan)); });
  };

  Pair(peer_id, security_reqs, std::move(pairing_cb));
}

BrEdrConnectionManager::SearchId BrEdrConnectionManager::AddServiceSearch(
    const UUID& uuid, std::unordered_set<sdp::AttributeId> attributes,
    BrEdrConnectionManager::SearchCallback callback) {
  auto on_service_discovered = [self = weak_ptr_factory_.GetWeakPtr(), uuid,
                                client_cb = std::move(callback)](PeerId peer_id, auto& attributes) {
    if (self) {
      Peer* const peer = self->cache_->FindById(peer_id);
      ZX_ASSERT(peer);
      peer->MutBrEdr().AddService(uuid);
    }
    client_cb(peer_id, attributes);
  };
  return discoverer_.AddSearch(uuid, std::move(attributes), std::move(on_service_discovered));
}

bool BrEdrConnectionManager::RemoveServiceSearch(SearchId id) {
  return discoverer_.RemoveSearch(id);
}

std::optional<BrEdrConnectionManager::ScoRequestHandle> BrEdrConnectionManager::OpenScoConnection(
    PeerId peer_id, bool initiator, hci::SynchronousConnectionParameters parameters,
    ScoConnectionCallback callback) {
  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "Can't open SCO connection to unconnected peer (peer: %s)",
           bt_str(peer_id));
    callback(fit::error(HostError::kNotFound));
    return std::nullopt;
  };

  return conn_pair->second->OpenScoConnection(initiator, parameters, std::move(callback));
}

bool BrEdrConnectionManager::Disconnect(PeerId peer_id, DisconnectReason reason) {
  bt_log(INFO, "gap-bredr", "Disconnect Requested (peer %s, reason %hhu - %s)", bt_str(peer_id),
         reason, ReasonAsString(reason).c_str());

  // TODO(fxbug.dev/65157) - If a disconnect request is received when we have a pending connection,
  // we should instead abort the connection, by either:
  //   * removing the request if it has not yet been processed
  //   * sending a cancel command to the controller and waiting for it to be processed
  //   * sending a cancel command, and if we already complete, then beginning a disconnect procedure
  if (connection_requests_.find(peer_id) != connection_requests_.end()) {
    bt_log(WARN, "gap-bredr", "Can't disconnect peer %s because it's being connected to",
           bt_str(peer_id));
    return false;
  }

  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(INFO, "gap-bredr", "No need to disconnect peer (id: %s): It is not connected",
           bt_str(peer_id));
    return true;
  }

  auto [handle, connection] = *conn_pair;
  CleanUpConnection(handle, std::move(connections_.extract(handle).mapped()));
  return true;
}

void BrEdrConnectionManager::AttachInspect(inspect::Node& parent, std::string name) {
  inspect_node_ = parent.CreateChild(name);

  inspect_properties_.connections_node_ = inspect_node_.CreateChild(kInspectConnectionsNodeName);
  inspect_properties_.last_disconnected_list.AttachInspect(inspect_node_,
                                                           kInspectLastDisconnectedListName);

  inspect_properties_.requests_node_ = inspect_node_.CreateChild(kInspectRequestsNodeName);
  for (auto& [_, req] : connection_requests_) {
    req.AttachInspect(inspect_properties_.requests_node_,
                      inspect_properties_.requests_node_.UniqueName(kInspectRequestNodeNamePrefix));
  }
}

void BrEdrConnectionManager::WritePageScanSettings(uint16_t interval, uint16_t window,
                                                   bool interlaced, hci::StatusCallback cb) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  if (!hci_cmd_runner_->IsReady()) {
    // TODO(jamuraa): could run the three "settings" commands in parallel and
    // remove the sequence runner.
    cb(hci::Status(HostError::kInProgress));
    return;
  }

  auto write_activity = hci::CommandPacket::New(hci::kWritePageScanActivity,
                                                sizeof(hci::WritePageScanActivityCommandParams));
  auto* activity_params =
      write_activity->mutable_payload<hci::WritePageScanActivityCommandParams>();
  activity_params->page_scan_interval = htole16(interval);
  activity_params->page_scan_window = htole16(window);

  hci_cmd_runner_->QueueCommand(
      std::move(write_activity), [self, interval, window](const hci::EventPacket& event) {
        if (!self || hci_is_error(event, WARN, "gap-bredr", "write page scan activity failed")) {
          return;
        }

        self->page_scan_interval_ = interval;
        self->page_scan_window_ = window;

        bt_log(TRACE, "gap-bredr", "page scan activity updated");
      });

  auto write_type =
      hci::CommandPacket::New(hci::kWritePageScanType, sizeof(hci::WritePageScanTypeCommandParams));
  auto* type_params = write_type->mutable_payload<hci::WritePageScanTypeCommandParams>();
  type_params->page_scan_type =
      (interlaced ? hci::PageScanType::kInterlacedScan : hci::PageScanType::kStandardScan);

  hci_cmd_runner_->QueueCommand(
      std::move(write_type), [self, interlaced](const hci::EventPacket& event) {
        if (!self || hci_is_error(event, WARN, "gap-bredr", "write page scan type failed")) {
          return;
        }

        self->page_scan_type_ =
            (interlaced ? hci::PageScanType::kInterlacedScan : hci::PageScanType::kStandardScan);

        bt_log(TRACE, "gap-bredr", "page scan type updated");
      });

  hci_cmd_runner_->RunCommands(std::move(cb));
}

std::optional<std::pair<hci::ConnectionHandle, BrEdrConnection*>>
BrEdrConnectionManager::FindConnectionById(PeerId peer_id) {
  auto it = std::find_if(connections_.begin(), connections_.end(),
                         [peer_id](const auto& c) { return c.second.peer_id() == peer_id; });

  if (it == connections_.end()) {
    return std::nullopt;
  }

  auto& [handle, conn] = *it;
  ZX_ASSERT(conn.link().ll_type() != hci::Connection::LinkType::kLE);

  return std::pair(handle, &conn);
}

std::optional<std::pair<hci::ConnectionHandle, BrEdrConnection*>>
BrEdrConnectionManager::FindConnectionByAddress(const DeviceAddressBytes& bd_addr) {
  auto* const peer = cache_->FindByAddress(DeviceAddress(DeviceAddress::Type::kBREDR, bd_addr));
  if (!peer) {
    return std::nullopt;
  }

  return FindConnectionById(peer->identifier());
}

Peer* BrEdrConnectionManager::FindOrInitPeer(DeviceAddress addr) {
  Peer* peer = cache_->FindByAddress(addr);
  if (!peer) {
    peer = cache_->NewPeer(addr, /*connectable*/ true);
  }
  return peer;
}

// Build connection state for a new connection and begin interrogation. L2CAP is not enabled for
// this link but pairing is allowed before interrogation completes.
void BrEdrConnectionManager::InitializeConnection(DeviceAddress addr,
                                                  hci::ConnectionHandle connection_handle) {
  // TODO(fxbug.dev/881): support non-master connections.
  auto link = hci::Connection::CreateACL(connection_handle, hci::Connection::Role::kMaster,
                                         local_address_, addr, hci_);
  Peer* const peer = FindOrInitPeer(addr);
  auto peer_id = peer->identifier();
  bt_log(INFO, "gap-bredr", "Beginning interrogation for peer %s", bt_str(peer_id));

  // We should never have more than one link to a given peer
  ZX_DEBUG_ASSERT(!FindConnectionById(peer_id));
  peer->MutBrEdr().SetConnectionState(ConnectionState::kInitializing);

  // The controller has completed the HCI connection procedure, so the connection request can no
  // longer be failed by a lower layer error. Now tie error reporting of the request to the lifetime
  // of the connection state object (BrEdrConnection RAII).
  auto node = connection_requests_.extract(peer_id);
  auto request = node ? std::optional(std::move(node.mapped())) : std::nullopt;

  const hci::ConnectionHandle handle = link->handle();
  auto send_auth_request_cb = [this, handle]() {
    this->SendAuthenticationRequested(handle, [handle](auto status) {
      bt_is_error(status, WARN, "gap-bredr", "authentication requested command failed for %#.4x",
                  handle);
    });
  };
  auto disconnect_cb = [this, peer_id] { Disconnect(peer_id, DisconnectReason::kPairingFailed); };
  auto on_peer_disconnect_cb =
      std::bind(&BrEdrConnectionManager::OnPeerDisconnect, this, link.get());
  auto [conn_iter, success] = connections_.try_emplace(
      handle, peer_id, std::move(link), std::move(send_auth_request_cb), std::move(disconnect_cb),
      std::move(on_peer_disconnect_cb), cache_, l2cap_, hci_, std::move(request));
  ZX_ASSERT(success);

  BrEdrConnection& connection = conn_iter->second;
  connection.pairing_state().SetPairingDelegate(pairing_delegate_);
  connection.AttachInspect(
      inspect_properties_.connections_node_,
      inspect_properties_.connections_node_.UniqueName(kInspectConnectionNodeNamePrefix));

  // Interrogate this peer to find out its version/capabilities.
  auto self = weak_ptr_factory_.GetWeakPtr();
  interrogator_.Start(peer->identifier(), handle, [peer, self, handle](auto status) {
    if (!self) {
      return;
    }
    bt_log_scope("peer: %s, handle: %#.4x", bt_str(peer->identifier()), handle);
    if (bt_is_error(status, WARN, "gap-bredr", "interrogation failed, dropping connection")) {
      // If this connection was locally requested, requester(s) are notified by the disconnection.
      self->Disconnect(peer->identifier(), DisconnectReason::kInterrogationFailed);
      return;
    }
    bt_log(INFO, "gap-bredr", "interrogation complete");
    self->CompleteConnectionSetup(peer, handle);
  });

  // If this was our in-flight request, close it
  if (pending_request_.has_value() && addr == pending_request_->peer_address()) {
    pending_request_.reset();
  }

  TryCreateNextConnection();
}

// Finish connection setup after a successful interrogation.
void BrEdrConnectionManager::CompleteConnectionSetup(Peer* peer, hci::ConnectionHandle handle) {
  auto self = weak_ptr_factory_.GetWeakPtr();

  auto connections_iter = connections_.find(handle);
  if (connections_iter == connections_.end()) {
    bt_log(WARN, "gap-bredr", "Connection to complete not found, handle: %#.4x", handle);
    return;
  }
  BrEdrConnection& conn_state = connections_iter->second;
  if (conn_state.peer_id() != peer->identifier()) {
    bt_log(WARN, "gap-bredr",
           "Connection %#.4x is no longer to peer %s (now to %s), ignoring interrogation result",
           handle, bt_str(peer->identifier()), bt_str(conn_state.peer_id()));
    return;
  }
  hci::Connection* const connection = &conn_state.link();

  auto error_handler = [self, peer_id = peer->identifier(), connection = connection->WeakPtr()] {
    if (!self || !connection)
      return;
    bt_log(WARN, "gap-bredr", "Link error received, closing connection (peer: %s, handle: %#.4x)",
           bt_str(peer_id), connection->handle());

    self->Disconnect(peer_id, DisconnectReason::kAclLinkError);
  };

  // TODO(fxbug.dev/37650): Implement this callback as a call to InitiatePairing().
  auto security_callback = [](hci::ConnectionHandle handle, sm::SecurityLevel level, auto cb) {
    bt_log(INFO, "gap-bredr", "Ignoring security upgrade request; not implemented");
    cb(sm::Status(HostError::kNotSupported));
  };

  // Register with L2CAP to handle services on the ACL signaling channel.
  l2cap_->AddACLConnection(handle, connection->role(), error_handler, std::move(security_callback));

  peer->MutBrEdr().SetConnectionState(ConnectionState::kConnected);

  if (discoverer_.search_count()) {
    l2cap_->OpenL2capChannel(handle, l2cap::kSDP, l2cap::ChannelParameters(),
                             [self, peer_id = peer->identifier()](auto channel) {
                               if (!self)
                                 return;

                               if (!channel) {
                                 bt_log(ERROR, "gap",
                                        "failed to create l2cap channel for SDP (peer id: %s)",
                                        bt_str(peer_id));
                                 return;
                               }

                               auto client = sdp::Client::Create(std::move(channel));
                               self->discoverer_.StartServiceDiscovery(peer_id, std::move(client));
                             });
  }

  conn_state.Start();
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnAuthenticationComplete(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kAuthenticationCompleteEventCode);
  const auto& params = event.params<hci::AuthenticationCompleteEventParams>();

  auto iter = connections_.find(params.connection_handle);
  if (iter == connections_.end()) {
    bt_log(INFO, "gap-bredr",
           "ignoring authentication complete for unknown connection handle %#.04x",
           params.connection_handle);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  hci::StatusCode status_code;
  event.ToStatusCode(&status_code);
  iter->second.pairing_state().OnAuthenticationComplete(status_code);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

bool BrEdrConnectionManager::ExistsIncomingRequest(PeerId id) {
  auto request = connection_requests_.find(id);
  return (request != connection_requests_.end() && request->second.HasIncoming());
}

void BrEdrConnectionManager::OnConnectionRequest(ConnectionRequestEvent event) {
  // Initialize the peer if it doesn't exist, to ensure we have allocated a PeerId
  auto peer = FindOrInitPeer(event.addr);
  auto peer_id = peer->identifier();
  bt_log_scope("peer: %s, addr: %s, link_type: %s, class: %s", bt_str(peer_id), bt_str(event.addr),
               LinkTypeToString(event.link_type).c_str(), bt_str(event.class_of_device));

  // In case of concurrent incoming requests from the same peer, reject all but the first
  if (ExistsIncomingRequest(peer_id)) {
    bt_log(WARN, "gap-bredr", "rejecting duplicate incoming connection request");
    SendRejectConnectionRequest(event.addr, hci::StatusCode::kConnectionRejectedBadBdAddr);
    return;
  }

  if (event.link_type == hci::LinkType::kACL) {
    // If we happen to be already connected (for example, if our outgoing raced, or we received
    // duplicate requests), we reject the request with 'ConnectionAlreadyExists'
    if (FindConnectionById(peer_id)) {
      bt_log(WARN, "gap-bredr", "rejecting incoming connection request; already connected");
      SendRejectConnectionRequest(event.addr, hci::StatusCode::kConnectionAlreadyExists);
      return;
    }

    // Accept the connection, performing a role switch. We receive a Connection Complete event
    // when the connection is complete, and finish the link then.
    bt_log(INFO, "gap-bredr", "accepting incoming connection");

    // Register that we're in the middle of an incoming request for this peer - create a new
    // request if one doesn't already exist
    auto [request, _ignore] = connection_requests_.try_emplace(peer_id, event.addr, peer_id);
    request->second.BeginIncoming();
    request->second.AttachInspect(
        inspect_properties_.requests_node_,
        inspect_properties_.requests_node_.UniqueName(kInspectRequestNodeNamePrefix));

    SendAcceptConnectionRequest(
        event.addr.value(),
        [addr = event.addr, self = weak_ptr_factory_.GetWeakPtr(), peer_id](auto status) {
          if (self && !status)
            self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
        });

    return;
  }

  if (event.link_type == hci::LinkType::kSCO || event.link_type == hci::LinkType::kExtendedSCO) {
    auto conn_pair = FindConnectionByAddress(event.addr.value());
    if (conn_pair) {
      // The ScoConnectionManager owned by the BrEdrConnection will respond.
      bt_log(INFO, "gap-bredr", "delegating incoming SCO connection to ScoConnectionManager");
      return;
    }
    bt_log(WARN, "gap-bredr", "rejecting (e)SCO connection request for peer that is not connected");
    SendRejectSynchronousRequest(event.addr, hci::StatusCode::kUnacceptableConnectionParameters);
  } else {
    auto link_type = static_cast<unsigned int>(event.link_type);
    bt_log(WARN, "gap-bredr", "reject unsupported connection type %u", link_type);
    SendRejectConnectionRequest(event.addr, hci::StatusCode::kUnsupportedFeatureOrParameter);
  }
}

void BrEdrConnectionManager::OnConnectionComplete(ConnectionComplete event) {
  if (event.link_type != hci::LinkType::kACL) {
    // Only ACL links are processed
    return;
  }

  // Initialize the peer if it doesn't exist, to ensure we have allocated a PeerId (we should
  // usually have a peer by this point)
  auto peer = FindOrInitPeer(event.addr);

  CompleteRequest(peer->identifier(), event.addr, event.status, event.handle);
}

// A request for a connection - from an upstream client _or_ a remote peer - completed, successfully
// or not. This may be due to a ConnectionComplete event being received, or due to a CommandStatus
// response being received in response to a CreateConnection command
void BrEdrConnectionManager::CompleteRequest(PeerId peer_id, DeviceAddress address,
                                             hci::Status status, hci::ConnectionHandle handle) {
  bt_log_scope("peer: %s, addr: %s, handle: %#.4x", bt_str(peer_id), bt_str(address), handle);

  auto req_iter = connection_requests_.find(peer_id);
  if (req_iter == connection_requests_.end()) {
    // This could potentially happen if the peer expired from the peer cache during the connection
    // procedure
    bt_log(INFO, "gap-bredr",
           "ConnectionComplete received for address with no known request (status: %s)",
           bt_str(status));
    return;
  }
  auto& request = req_iter->second;

  bool completed_request_was_outgoing =
      pending_request_ && pending_request_->peer_address() == address;
  bool failed = !status.is_success();

  const char* direction = completed_request_was_outgoing ? "outgoing" : "incoming";
  const char* result = status ? "complete" : "error";
  bt_log(INFO, "gap-bredr", "%s connection %s (status: %s)", direction, result, bt_str(status));

  if (completed_request_was_outgoing) {
    // Determine the modified status in case of cancellation or timeout
    status = pending_request_->CompleteRequest(status);
    pending_request_.reset();
  } else {
    // If this was an incoming attempt, clear it
    request.CompleteIncoming();
  }

  if (failed) {
    if (request.HasIncoming() || (!completed_request_was_outgoing && request.AwaitingOutgoing())) {
      // This request failed, but we're still waiting on either:
      // * an in-progress incoming request or
      // * to attempt our own outgoing request
      // Therefore we don't notify yet - instead take no action, and wait until we finish those
      // steps before completing the request and notifying callbacks
      TryCreateNextConnection();
      return;
    }
    request.NotifyCallbacks(status, [] { return nullptr; });
    connection_requests_.erase(req_iter);

    // The peer may no longer be in the cache by the time this function is called
    // TODO(fxbug.dev/70878): What if this request failed but a previous one succeeded? This is a
    // potential race condition in tracking peer state
    Peer* peer = cache_->FindByAddress(address);
    if (peer) {
      peer->MutBrEdr().SetConnectionState(ConnectionState::kNotConnected);
    }
  } else {
    // Callbacks will be notified when interrogation completes
    InitializeConnection(address, handle);
  }

  TryCreateNextConnection();
}

void BrEdrConnectionManager::OnPeerDisconnect(const hci::Connection* connection) {
  auto handle = connection->handle();

  auto it = connections_.find(handle);
  if (it == connections_.end()) {
    bt_log(WARN, "gap-bredr", "disconnect from unknown connection handle %#.4x", handle);
    return;
  }

  auto conn = std::move(it->second);
  connections_.erase(it);

  bt_log(INFO, "gap-bredr", "peer disconnected (peer: %s, handle: %#.4x)", bt_str(conn.peer_id()),
         handle);
  CleanUpConnection(handle, std::move(conn));
}

void BrEdrConnectionManager::CleanUpConnection(hci::ConnectionHandle handle, BrEdrConnection conn) {
  auto* peer = cache_->FindByAddress(conn.link().peer_address());
  ZX_DEBUG_ASSERT_MSG(peer, "Couldn't find peer for handle: %#.4x", handle);
  peer->MutBrEdr().SetConnectionState(ConnectionState::kNotConnected);

  l2cap_->RemoveConnection(handle);

  RecordDisconnectInspect(conn);

  // |conn| is destroyed when it goes out of scope.
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnIoCapabilityRequest(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kIOCapabilityRequestEventCode);
  const auto& params = event.params<hci::IOCapabilityRequestEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(ERROR, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    SendIoCapabilityRequestNegativeReply(params.bd_addr, hci::StatusCode::kPairingNotAllowed);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  auto [handle, conn_ptr] = *conn_pair;
  auto reply = conn_ptr->pairing_state().OnIoCapabilityRequest();

  if (!reply) {
    SendIoCapabilityRequestNegativeReply(params.bd_addr, hci::StatusCode::kPairingNotAllowed);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  const hci::IOCapability io_capability = *reply;

  // TODO(fxbug.dev/601): Add OOB status from PeerCache.
  const uint8_t oob_data_present = 0x00;  // None present.

  // TODO(fxbug.dev/1249): Determine this based on the service requirements.
  const hci::AuthRequirements auth_requirements =
      io_capability == hci::IOCapability::kNoInputNoOutput
          ? hci::AuthRequirements::kGeneralBonding
          : hci::AuthRequirements::kMITMGeneralBonding;

  SendIoCapabilityRequestReply(params.bd_addr, io_capability, oob_data_present, auth_requirements);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnIoCapabilityResponse(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kIOCapabilityResponseEventCode);
  const auto& params = event.params<hci::IOCapabilityResponseEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(INFO, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnIoCapabilityResponse(params.io_capability);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnLinkKeyRequest(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kLinkKeyRequestEventCode);
  const auto& params = event.params<hci::LinkKeyRequestParams>();

  DeviceAddress addr(DeviceAddress::Type::kBREDR, params.bd_addr);
  auto* peer = cache_->FindByAddress(addr);
  if (!peer) {
    bt_log(WARN, "gap-bredr", "no peer with address %s found", bt_str(addr));
    SendLinkKeyRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto peer_id = peer->identifier();
  auto conn_pair = FindConnectionById(peer_id);

  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "can't find connection for ltk (id: %s)", bt_str(peer_id));
    SendLinkKeyRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  auto& [handle, conn] = *conn_pair;

  auto link_key = conn->pairing_state().OnLinkKeyRequest(addr);
  if (!link_key.has_value()) {
    SendLinkKeyRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  SendLinkKeyRequestReply(params.bd_addr, link_key.value());
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnLinkKeyNotification(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kLinkKeyNotificationEventCode);
  const auto& params = event.params<hci::LinkKeyNotificationEventParams>();

  DeviceAddress addr(DeviceAddress::Type::kBREDR, params.bd_addr);

  auto* peer = cache_->FindByAddress(addr);
  if (!peer) {
    bt_log(WARN, "gap-bredr",
           "no known peer with address %s found; link key not stored (key type: %u)", bt_str(addr),
           params.key_type);
    cache_->LogBrEdrBondingEvent(false);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  bt_log(INFO, "gap-bredr", "got link key notification (key type: %u, peer: %s)", params.key_type,
         bt_str(peer->identifier()));

  auto key_type = hci::LinkKeyType{params.key_type};
  sm::SecurityProperties sec_props;
  if (key_type == hci::LinkKeyType::kChangedCombination) {
    if (!peer->bredr() || !peer->bredr()->bonded()) {
      bt_log(WARN, "gap-bredr", "can't update link key of unbonded peer %s",
             bt_str(peer->identifier()));
      cache_->LogBrEdrBondingEvent(false);
      return hci::CommandChannel::EventCallbackResult::kContinue;
    }

    // Reuse current properties
    ZX_DEBUG_ASSERT(peer->bredr()->link_key());
    sec_props = peer->bredr()->link_key()->security();
    key_type = *sec_props.GetLinkKeyType();
  } else {
    sec_props = sm::SecurityProperties(key_type);
  }

  auto peer_id = peer->identifier();

  if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
    bt_log(WARN, "gap-bredr", "link key for peer %s has insufficient security; not stored",
           bt_str(peer_id));
    cache_->LogBrEdrBondingEvent(false);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  UInt128 key_value;
  std::copy(params.link_key, &params.link_key[key_value.size()], key_value.begin());
  hci::LinkKey hci_key(key_value, 0, 0);
  sm::LTK key(sec_props, hci_key);

  auto handle = FindConnectionById(peer_id);
  if (!handle) {
    bt_log(WARN, "gap-bredr", "can't find current connection for ltk (peer: %s)", bt_str(peer_id));
  } else {
    handle->second->link().set_bredr_link_key(hci_key, key_type);
    handle->second->pairing_state().OnLinkKeyNotification(key_value, key_type);
  }

  if (cache_->StoreBrEdrBond(addr, key)) {
    cache_->LogBrEdrBondingEvent(true);
  } else {
    cache_->LogBrEdrBondingEvent(false);
    bt_log(ERROR, "gap-bredr", "failed to cache bonding data (peer: %s)", bt_str(peer_id));
  }
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnSimplePairingComplete(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kSimplePairingCompleteEventCode);
  const auto& params = event.params<hci::SimplePairingCompleteEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnSimplePairingComplete(params.status);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnUserConfirmationRequest(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kUserConfirmationRequestEventCode);
  const auto& params = event.params<hci::UserConfirmationRequestEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    SendUserConfirmationRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto confirm_cb = [this, self = weak_ptr_factory_.GetWeakPtr(),
                     bd_addr = params.bd_addr](bool confirm) {
    if (!self) {
      return;
    }

    if (confirm) {
      SendUserConfirmationRequestReply(bd_addr);
    } else {
      SendUserConfirmationRequestNegativeReply(bd_addr);
    }
  };
  conn_pair->second->pairing_state().OnUserConfirmationRequest(letoh32(params.numeric_value),
                                                               std::move(confirm_cb));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnUserPasskeyRequest(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kUserPasskeyRequestEventCode);
  const auto& params = event.params<hci::UserPasskeyRequestEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    SendUserPasskeyRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto passkey_cb = [this, self = weak_ptr_factory_.GetWeakPtr(),
                     bd_addr = params.bd_addr](std::optional<uint32_t> passkey) {
    if (!self) {
      return;
    }

    if (passkey) {
      SendUserPasskeyRequestReply(bd_addr, *passkey);
    } else {
      SendUserPasskeyRequestNegativeReply(bd_addr);
    }
  };
  conn_pair->second->pairing_state().OnUserPasskeyRequest(std::move(passkey_cb));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnUserPasskeyNotification(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kUserPasskeyNotificationEventCode);
  const auto& params = event.params<hci::UserPasskeyNotificationEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN, "gap-bredr", "got %s for unconnected addr %s", __func__, bt_str(params.bd_addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnUserPasskeyNotification(letoh32(params.numeric_value));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

bool BrEdrConnectionManager::Connect(PeerId peer_id, ConnectResultCallback on_connection_result) {
  Peer* peer = cache_->FindById(peer_id);
  if (!peer) {
    bt_log(WARN, "gap-bredr", "%s: peer not found (peer: %s)", __func__, bt_str(peer_id));
    return false;
  }

  if (peer->technology() == TechnologyType::kLowEnergy) {
    bt_log(ERROR, "gap-bredr", "peer does not support BrEdr: %s", bt_str(*peer));
    return false;
  }

  // Br/Edr peers should always be connectable by definition
  ZX_ASSERT(peer->connectable());

  // Succeed immediately or after interrogation if there is already an active connection.
  auto conn = FindConnectionById(peer_id);
  if (conn) {
    conn->second->AddRequestCallback(std::move(on_connection_result));
    return true;
  }

  // If we are already waiting to connect to |peer_id| then we store
  // |on_connection_result| to be processed after the connection attempt
  // completes (in either success of failure).
  auto pending_iter = connection_requests_.find(peer_id);
  if (pending_iter != connection_requests_.end()) {
    pending_iter->second.AddCallback(std::move(on_connection_result));
    return true;
  }
  // If we are not already connected or pending, initiate a new connection
  peer->MutBrEdr().SetConnectionState(ConnectionState::kInitializing);
  auto [request_iter, _] = connection_requests_.try_emplace(peer_id, peer->address(), peer_id,
                                                            std::move(on_connection_result));
  request_iter->second.AttachInspect(
      inspect_properties_.requests_node_,
      inspect_properties_.requests_node_.UniqueName(kInspectRequestNodeNamePrefix));

  TryCreateNextConnection();

  return true;
}

std::optional<BrEdrConnectionManager::CreateConnectionParams>
BrEdrConnectionManager::NextCreateConnectionParams() {
  if (connection_requests_.empty()) {
    bt_log(TRACE, "gap-bredr", "no pending requests remaining");
    return std::nullopt;
  }

  Peer* peer = nullptr;
  // We use a rough heuristic of ordering likely connection requests by presence in the peer cache.
  // If a peer is still in the cache, that implies it was seen more recently which is likely to
  // correlate with being physically close and therefore still in range when we attempt to connect.
  //
  // So first try a request for which we have a peer struct:
  for (auto& [identifier, request] : connection_requests_) {
    const auto& addr = request.address();
    peer = cache_->FindByAddress(addr);
    if (peer && peer->bredr() && !request.HasIncoming())
      return std::optional(CreateConnectionParams{peer->identifier(), addr,
                                                  peer->bredr()->clock_offset(),
                                                  peer->bredr()->page_scan_repetition_mode()});
  }

  // Otherwise, fall back to any other requests - it is entirely possible that while a connection is
  // pending, discovery has ended and the peer which was intended to be connected to has timed out
  // of the peer cache, but may still be in range and connectable.
  for (auto& [identifier, request] : connection_requests_) {
    if (!request.HasIncoming()) {
      return std::optional(
          CreateConnectionParams{identifier, request.address(), std::nullopt, std::nullopt});
    }
  }
  // Finally, if we didn't find a connection request we could process at this time:
  return std::nullopt;
}

void BrEdrConnectionManager::TryCreateNextConnection() {
  // There can only be one outstanding BrEdr CreateConnection request at a time
  if (pending_request_) {
    return;
  }

  auto next = NextCreateConnectionParams();
  if (next) {
    InitiatePendingConnection(*next);
  }
}

void BrEdrConnectionManager::InitiatePendingConnection(CreateConnectionParams params) {
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto on_failure = [self, addr = params.addr](hci::Status status, auto peer_id) {
    if (self && !status)
      self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
  };
  auto on_timeout = [self] {
    if (self)
      self->OnRequestTimeout();
  };
  pending_request_.emplace(params.peer_id, params.addr, on_timeout);
  pending_request_->CreateConnection(hci_->command_channel(), dispatcher_, params.clock_offset,
                                     params.page_scan_repetition_mode, request_timeout_,
                                     on_failure);
}

void BrEdrConnectionManager::OnRequestTimeout() {
  if (pending_request_) {
    pending_request_->Timeout();
    SendCreateConnectionCancelCommand(pending_request_->peer_address());
  }
}

void BrEdrConnectionManager::SendCreateConnectionCancelCommand(DeviceAddress addr) {
  auto cancel = hci::CommandPacket::New(hci::kCreateConnectionCancel,
                                        sizeof(hci::CreateConnectionCancelCommandParams));
  auto params = cancel->mutable_payload<hci::CreateConnectionCancelCommandParams>();
  params->bd_addr = addr.value();
  hci_->command_channel()->SendCommand(std::move(cancel), [](auto, const hci::EventPacket& event) {
    hci_is_error(event, WARN, "hci-bredr", "failed to cancel connection request");
  });
}

void BrEdrConnectionManager::SendAuthenticationRequested(hci::ConnectionHandle handle,
                                                         hci::StatusCallback cb) {
  auto auth_request = hci::CommandPacket::New(hci::kAuthenticationRequested,
                                              sizeof(hci::AuthenticationRequestedCommandParams));
  auth_request->mutable_payload<hci::AuthenticationRequestedCommandParams>()->connection_handle =
      htole16(handle);

  // Complete on command status because Authentication Complete Event is already registered.
  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToStatus());
    };
  }
  hci_->command_channel()->SendCommand(std::move(auth_request), std::move(command_cb),
                                       hci::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendIoCapabilityRequestReply(DeviceAddressBytes bd_addr,
                                                          hci::IOCapability io_capability,
                                                          uint8_t oob_data_present,
                                                          hci::AuthRequirements auth_requirements,
                                                          hci::StatusCallback cb) {
  auto packet = hci::CommandPacket::New(hci::kIOCapabilityRequestReply,
                                        sizeof(hci::IOCapabilityRequestReplyCommandParams));
  auto params = packet->mutable_payload<hci::IOCapabilityRequestReplyCommandParams>();
  params->bd_addr = bd_addr;
  params->io_capability = io_capability;
  params->oob_data_present = oob_data_present;
  params->auth_requirements = auth_requirements;
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendIoCapabilityRequestNegativeReply(DeviceAddressBytes bd_addr,
                                                                  hci::StatusCode reason,
                                                                  hci::StatusCallback cb) {
  auto packet = hci::CommandPacket::New(hci::kIOCapabilityRequestNegativeReply,
                                        sizeof(hci::IOCapabilityRequestNegativeReplyCommandParams));
  auto params = packet->mutable_payload<hci::IOCapabilityRequestNegativeReplyCommandParams>();
  params->bd_addr = bd_addr;
  params->reason = reason;
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserConfirmationRequestReply(DeviceAddressBytes bd_addr,
                                                              hci::StatusCallback cb) {
  auto packet = hci::CommandPacket::New(hci::kUserConfirmationRequestReply,
                                        sizeof(hci::UserConfirmationRequestReplyCommandParams));
  packet->mutable_payload<hci::UserConfirmationRequestReplyCommandParams>()->bd_addr = bd_addr;
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserConfirmationRequestNegativeReply(DeviceAddressBytes bd_addr,
                                                                      hci::StatusCallback cb) {
  auto packet =
      hci::CommandPacket::New(hci::kUserConfirmationRequestNegativeReply,
                              sizeof(hci::UserConfirmationRequestNegativeReplyCommandParams));
  packet->mutable_payload<hci::UserConfirmationRequestNegativeReplyCommandParams>()->bd_addr =
      bd_addr;
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserPasskeyRequestReply(DeviceAddressBytes bd_addr,
                                                         uint32_t numeric_value,
                                                         hci::StatusCallback cb) {
  auto packet = hci::CommandPacket::New(hci::kUserPasskeyRequestReply,
                                        sizeof(hci::UserPasskeyRequestReplyCommandParams));
  auto params = packet->mutable_payload<hci::UserPasskeyRequestReplyCommandParams>();
  params->bd_addr = bd_addr;
  params->numeric_value = htole32(numeric_value);
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserPasskeyRequestNegativeReply(DeviceAddressBytes bd_addr,
                                                                 hci::StatusCallback cb) {
  auto packet = hci::CommandPacket::New(hci::kUserPasskeyRequestNegativeReply,
                                        sizeof(hci::UserPasskeyRequestNegativeReplyCommandParams));
  packet->mutable_payload<hci::UserPasskeyRequestNegativeReplyCommandParams>()->bd_addr = bd_addr;
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendLinkKeyRequestNegativeReply(DeviceAddressBytes bd_addr,
                                                             hci::StatusCallback cb) {
  auto negative_reply = hci::CommandPacket::New(
      hci::kLinkKeyRequestNegativeReply, sizeof(hci::LinkKeyRequestNegativeReplyCommandParams));
  auto negative_reply_params =
      negative_reply->mutable_payload<hci::LinkKeyRequestNegativeReplyCommandParams>();
  negative_reply_params->bd_addr = bd_addr;
  SendCommandWithStatusCallback(std::move(negative_reply), std::move(cb));
}

void BrEdrConnectionManager::SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,
                                                     hci::LinkKey link_key,
                                                     hci::StatusCallback cb) {
  auto reply = hci::CommandPacket::New(hci::kLinkKeyRequestReply,
                                       sizeof(hci::LinkKeyRequestReplyCommandParams));
  auto reply_params = reply->mutable_payload<hci::LinkKeyRequestReplyCommandParams>();
  reply_params->bd_addr = bd_addr;
  const auto& key_value = link_key.value();
  std::copy(key_value.begin(), key_value.end(), reply_params->link_key);
  SendCommandWithStatusCallback(std::move(reply), std::move(cb));
}

void BrEdrConnectionManager::SendCommandWithStatusCallback(
    std::unique_ptr<hci::CommandPacket> command_packet, hci::StatusCallback cb) {
  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToStatus());
    };
  }
  hci_->command_channel()->SendCommand(std::move(command_packet), std::move(command_cb));
}

void BrEdrConnectionManager::SendAcceptConnectionRequest(DeviceAddressBytes addr,
                                                         hci::StatusCallback cb) {
  auto accept = hci::CommandPacket::New(hci::kAcceptConnectionRequest,
                                        sizeof(hci::AcceptConnectionRequestCommandParams));
  auto accept_params = accept->mutable_payload<hci::AcceptConnectionRequestCommandParams>();
  accept_params->bd_addr = addr;
  accept_params->role = hci::ConnectionRole::kMaster;

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToStatus());
    };
  }

  hci_->command_channel()->SendCommand(std::move(accept), std::move(command_cb),
                                       hci::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendRejectConnectionRequest(DeviceAddress addr, hci::StatusCode reason,
                                                         hci::StatusCallback cb) {
  auto reject = hci::CommandPacket::New(hci::kRejectConnectionRequest,
                                        sizeof(hci::RejectConnectionRequestCommandParams));
  auto reject_params = reject->mutable_payload<hci::RejectConnectionRequestCommandParams>();
  reject_params->bd_addr = addr.value();
  reject_params->reason = reason;

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToStatus());
    };
  }

  hci_->command_channel()->SendCommand(std::move(reject), std::move(command_cb),
                                       hci::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendRejectSynchronousRequest(DeviceAddress addr,
                                                          hci::StatusCode reason,
                                                          hci::StatusCallback cb) {
  auto reject =
      hci::CommandPacket::New(hci::kRejectSynchronousConnectionRequest,
                              sizeof(hci::RejectSynchronousConnectionRequestCommandParams));
  auto reject_params =
      reject->mutable_payload<hci::RejectSynchronousConnectionRequestCommandParams>();
  reject_params->bd_addr = addr.value();
  reject_params->reason = reason;

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToStatus());
    };
  }

  hci_->command_channel()->SendCommand(std::move(reject), std::move(command_cb),
                                       hci::kCommandStatusEventCode);
}

void BrEdrConnectionManager::RecordDisconnectInspect(const BrEdrConnection& conn) {
  // Add item to recent disconnections list.
  auto& inspect_item = inspect_properties_.last_disconnected_list.CreateItem();
  inspect_item.node.CreateString(kInspectLastDisconnectedItemPeerPropertyName,
                                 conn.peer_id().ToString(), &inspect_item.values);
  inspect_item.node.CreateUint(kInspectLastDisconnectedItemDurationPropertyName,
                               conn.duration().to_secs(), &inspect_item.values);
  inspect_item.node.CreateInt(kInspectTimestampPropertyName, async::Now(dispatcher_).get(),
                              &inspect_item.values);
}

}  // namespace bt::gap
