// 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 "profile_server.h"

#include <zircon/status.h>

#include "helpers.h"
#include "lib/fit/result.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/common/uuid.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/types.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sdp/status.h"

using fuchsia::bluetooth::ErrorCode;
using fuchsia::bluetooth::Status;

namespace fidlbredr = fuchsia::bluetooth::bredr;
using fidlbredr::DataElement;
using fidlbredr::Profile;

namespace bthost {

namespace {

bt::l2cap::ChannelParameters FidlToChannelParameters(const fidlbredr::ChannelParameters& fidl) {
  bt::l2cap::ChannelParameters params;
  if (fidl.has_channel_mode()) {
    switch (fidl.channel_mode()) {
      case fidlbredr::ChannelMode::BASIC:
        params.mode = bt::l2cap::ChannelMode::kBasic;
        break;
      case fidlbredr::ChannelMode::ENHANCED_RETRANSMISSION:
        params.mode = bt::l2cap::ChannelMode::kEnhancedRetransmission;
        break;
      default:
        ZX_PANIC("FIDL channel parameter contains invalid mode");
    }
  }
  if (fidl.has_max_rx_sdu_size()) {
    params.max_rx_sdu_size = fidl.max_rx_sdu_size();
  }
  if (fidl.has_flush_timeout()) {
    params.flush_timeout = zx::duration(fidl.flush_timeout());
  }
  return params;
}

fidlbredr::ChannelMode ChannelModeToFidl(bt::l2cap::ChannelMode mode) {
  switch (mode) {
    case bt::l2cap::ChannelMode::kBasic:
      return fidlbredr::ChannelMode::BASIC;
      break;
    case bt::l2cap::ChannelMode::kEnhancedRetransmission:
      return fidlbredr::ChannelMode::ENHANCED_RETRANSMISSION;
      break;
    default:
      ZX_PANIC("Could not convert channel parameter mode to unsupported FIDL mode");
  }
}

fidlbredr::ChannelParameters ChannelInfoToFidlChannelParameters(
    const bt::l2cap::ChannelInfo& info) {
  fidlbredr::ChannelParameters params;
  params.set_channel_mode(ChannelModeToFidl(info.mode));
  params.set_max_rx_sdu_size(info.max_rx_sdu_size);
  if (info.flush_timeout) {
    params.set_flush_timeout(info.flush_timeout.value().get());
  }
  return params;
}

fidlbredr::DataElementPtr DataElementToFidl(const bt::sdp::DataElement* in) {
  auto elem = fidlbredr::DataElement::New();
  bt_log(TRACE, "fidl", "DataElementToFidl: %s", in->ToString().c_str());
  ZX_DEBUG_ASSERT(in);
  switch (in->type()) {
    case bt::sdp::DataElement::Type::kUnsignedInt: {
      switch (in->size()) {
        case bt::sdp::DataElement::Size::kOneByte:
          elem->set_uint8(*in->Get<uint8_t>());
          break;
        case bt::sdp::DataElement::Size::kTwoBytes:
          elem->set_uint16(*in->Get<uint16_t>());
          break;
        case bt::sdp::DataElement::Size::kFourBytes:
          elem->set_uint32(*in->Get<uint32_t>());
          break;
        case bt::sdp::DataElement::Size::kEightBytes:
          elem->set_uint64(*in->Get<uint64_t>());
          break;
        default:
          bt_log(INFO, "fidl", "no 128-bit integer support in FIDL yet");
          return nullptr;
      }
      return elem;
    }
    case bt::sdp::DataElement::Type::kSignedInt: {
      switch (in->size()) {
        case bt::sdp::DataElement::Size::kOneByte:
          elem->set_int8(*in->Get<int8_t>());
          break;
        case bt::sdp::DataElement::Size::kTwoBytes:
          elem->set_int16(*in->Get<int16_t>());
          break;
        case bt::sdp::DataElement::Size::kFourBytes:
          elem->set_int32(*in->Get<int32_t>());
          break;
        case bt::sdp::DataElement::Size::kEightBytes:
          elem->set_int64(*in->Get<int64_t>());
          break;
        default:
          bt_log(INFO, "fidl", "no 128-bit integer support in FIDL yet");
          return nullptr;
      }
      return elem;
    }
    case bt::sdp::DataElement::Type::kUuid: {
      auto uuid = in->Get<bt::UUID>();
      ZX_DEBUG_ASSERT(uuid);
      elem->set_uuid(fidl_helpers::UuidToFidl(*uuid));
      return elem;
    }
    case bt::sdp::DataElement::Type::kString: {
      elem->set_str(*in->Get<std::string>());
      return elem;
    }
    case bt::sdp::DataElement::Type::kBoolean: {
      elem->set_b(*in->Get<bool>());
      return elem;
    }
    case bt::sdp::DataElement::Type::kSequence: {
      std::vector<fidlbredr::DataElementPtr> elems;
      const bt::sdp::DataElement* it;
      for (size_t idx = 0; (it = in->At(idx)); ++idx) {
        elems.emplace_back(DataElementToFidl(it));
      }
      elem->set_sequence(std::move(elems));
      return elem;
    }
    case bt::sdp::DataElement::Type::kAlternative: {
      std::vector<fidlbredr::DataElementPtr> elems;
      const bt::sdp::DataElement* it;
      for (size_t idx = 0; (it = in->At(idx)); ++idx) {
        elems.emplace_back(DataElementToFidl(it));
      }
      elem->set_alternatives(std::move(elems));
      return elem;
    }
    case bt::sdp::DataElement::Type::kUrl: {
      bt_log(INFO, "fidl", "no support for Url types in DataElement yet");
      return nullptr;
    }
    case bt::sdp::DataElement::Type::kNull: {
      bt_log(INFO, "fidl", "no support for null DataElement types in FIDL");
      return nullptr;
    }
  }
}

fidlbredr::ProtocolDescriptorPtr DataElementToProtocolDescriptor(const bt::sdp::DataElement* in) {
  auto desc = fidlbredr::ProtocolDescriptor::New();
  if (in->type() != bt::sdp::DataElement::Type::kSequence) {
    bt_log(DEBUG, "fidl", "DataElement type is not kSequence (in: %s)", bt_str(*in));
    return nullptr;
  }
  const auto protocol_uuid = in->At(0)->Get<bt::UUID>();
  if (!protocol_uuid) {
    bt_log(DEBUG, "fidl", "first DataElement in sequence is not type kUUID (in: %s)", bt_str(*in));
    return nullptr;
  }
  desc->protocol = fidlbredr::ProtocolIdentifier(*protocol_uuid->As16Bit());
  const bt::sdp::DataElement* it;
  for (size_t idx = 1; (it = in->At(idx)); ++idx) {
    desc->params.push_back(std::move(*DataElementToFidl(it)));
  }

  return desc;
}

bt::hci::AclPriority FidlToAclPriority(fidlbredr::A2dpDirectionPriority in) {
  switch (in) {
    case fidlbredr::A2dpDirectionPriority::SOURCE:
      return bt::hci::AclPriority::kSource;
    case fidlbredr::A2dpDirectionPriority::SINK:
      return bt::hci::AclPriority::kSink;
    default:
      return bt::hci::AclPriority::kNormal;
  }
}

}  // namespace

ProfileServer::ProfileServer(fxl::WeakPtr<bt::gap::Adapter> adapter,
                             fidl::InterfaceRequest<Profile> request)
    : ServerBase(this, std::move(request)),
      advertised_total_(0),
      searches_total_(0),
      adapter_(adapter),
      weak_ptr_factory_(this) {}

ProfileServer::~ProfileServer() {
  if (adapter()) {
    // Unregister anything that we have registered.
    for (const auto& it : current_advertised_) {
      adapter()->bredr()->UnregisterService(it.second.registration_handle);
      it.second.disconnection_cb(fit::ok());
    }
    for (const auto& it : searches_) {
      adapter()->bredr()->RemoveServiceSearch(it.second.search_id);
    }
  }
}

ProfileServer::L2capParametersExt::L2capParametersExt(
    fidl::InterfaceRequest<fuchsia::bluetooth::bredr::L2capParametersExt> request,
    fbl::RefPtr<bt::l2cap::Channel> channel)
    : ServerBase(this, std::move(request)), channel_(std::move(channel)) {}

void ProfileServer::L2capParametersExt::RequestParameters(
    fuchsia::bluetooth::bredr::ChannelParameters requested, RequestParametersCallback callback) {
  if (requested.has_flush_timeout()) {
    channel_->SetBrEdrAutomaticFlushTimeout(
        zx::duration(requested.flush_timeout()),
        [chan = channel_, cb = std::move(callback)](auto result) {
          if (result.is_ok()) {
            bt_log(DEBUG, "fidl",
                   "L2capParametersExt::RequestParameters: setting flush timeout succeeded");
          } else {
            bt_log(INFO, "fidl",
                   "L2capParametersExt::RequestParameters: setting flush timeout failed");
          }
          // Return the current parameters even if the request failed.
          // TODO(fxb/73039): set current security requirements in returned channel parameters
          cb(ChannelInfoToFidlChannelParameters(chan->info()));
        });
    return;
  }

  // No other channel parameters are  supported, so just return the current parameters.
  // TODO(fxb/73039): set current security requirements in returned channel parameters
  callback(ChannelInfoToFidlChannelParameters(channel_->info()));
}

void ProfileServer::Advertise(
    std::vector<fidlbredr::ServiceDefinition> definitions, fidlbredr::ChannelParameters parameters,
    fidl::InterfaceHandle<fuchsia::bluetooth::bredr::ConnectionReceiver> receiver,
    AdvertiseCallback callback) {
  // TODO: check that the service definition is valid for useful error messages

  std::vector<bt::sdp::ServiceRecord> registering;

  for (auto& definition : definitions) {
    auto rec = fidl_helpers::ServiceDefinitionToServiceRecord(definition);
    // Drop the receiver on error.
    if (rec.is_error()) {
      bt_log(WARN, "fidl", "%s: Failed to create service record from service defintion",
             __FUNCTION__);
      callback(fit::error(fuchsia::bluetooth::ErrorCode::INVALID_ARGUMENTS));
      return;
    }
    registering.emplace_back(std::move(rec.value()));
  }

  ZX_ASSERT(adapter());
  ZX_ASSERT(adapter()->bredr());

  uint64_t next = advertised_total_ + 1;

  auto registration_handle = adapter()->bredr()->RegisterService(
      std::move(registering), FidlToChannelParameters(parameters),
      [this, next](auto channel, const auto& protocol_list) {
        OnChannelConnected(next, std::move(channel), std::move(protocol_list));
      });

  if (!registration_handle) {
    bt_log(WARN, "fidl", "%s: Failed to register service", __FUNCTION__);
    callback(fit::error(fuchsia::bluetooth::ErrorCode::INVALID_ARGUMENTS));
    return;
  };

  auto receiverptr = receiver.Bind();

  receiverptr.set_error_handler(
      [this, next](zx_status_t status) { OnConnectionReceiverError(next, status); });

  current_advertised_.try_emplace(next, std::move(receiverptr), registration_handle,
                                  std::move(callback));
  advertised_total_ = next;
}

void ProfileServer::Search(
    fidlbredr::ServiceClassProfileIdentifier service_uuid, std::vector<uint16_t> attr_ids,
    fidl::InterfaceHandle<fuchsia::bluetooth::bredr::SearchResults> results) {
  bt::UUID search_uuid(static_cast<uint32_t>(service_uuid));
  std::unordered_set<bt::sdp::AttributeId> attributes(attr_ids.begin(), attr_ids.end());
  if (!attr_ids.empty()) {
    // Always request the ProfileDescriptor for the event
    attributes.insert(bt::sdp::kBluetoothProfileDescriptorList);
  }

  ZX_DEBUG_ASSERT(adapter());

  auto next = searches_total_ + 1;

  auto search_id = adapter()->bredr()->AddServiceSearch(
      search_uuid, std::move(attributes),
      [this, next](auto id, const auto& attrs) { OnServiceFound(next, id, attrs); });

  if (!search_id) {
    return;
  }

  auto results_ptr = results.Bind();
  results_ptr.set_error_handler(
      [this, next](zx_status_t status) { OnSearchResultError(next, status); });

  searches_.try_emplace(next, std::move(results_ptr), search_id);
  searches_total_ = next;
}

void ProfileServer::Connect(fuchsia::bluetooth::PeerId peer_id,
                            fidlbredr::ConnectParameters connection, ConnectCallback callback) {
  bt::PeerId id{peer_id.value};

  // Anything other than L2CAP is not supported by this server.
  if (!connection.is_l2cap()) {
    bt_log(WARN, "fidl", "%s: non-l2cap connections are not supported (is_rfcomm: %d, peer: %s)",
           __FUNCTION__, connection.is_rfcomm(), bt_str(id));
    callback(fit::error(fuchsia::bluetooth::ErrorCode::INVALID_ARGUMENTS));
    return;
  }

  // The L2CAP parameters must include a PSM. ChannelParameters are optional.
  auto l2cap_params = std::move(connection.l2cap());
  if (!l2cap_params.has_psm()) {
    bt_log(WARN, "fidl", "%s: missing l2cap psm (peer: %s)", __FUNCTION__, bt_str(id));
    callback(fit::error(fuchsia::bluetooth::ErrorCode::INVALID_ARGUMENTS));
    return;
  }
  uint16_t psm = l2cap_params.psm();

  fidlbredr::ChannelParameters parameters = std::move(*l2cap_params.mutable_parameters());

  auto connected_cb = [self = weak_ptr_factory_.GetWeakPtr(), cb = callback.share(), id,
                       func = __FUNCTION__](fbl::RefPtr<bt::l2cap::Channel> chan) {
    if (!chan) {
      bt_log(INFO, "fidl", "%s: Channel socket is empty, returning failed. (peer: %s)", func,
             bt_str(id));
      cb(fit::error(fuchsia::bluetooth::ErrorCode::FAILED));
      return;
    }

    if (!self) {
      cb(fit::error(fuchsia::bluetooth::ErrorCode::FAILED));
      return;
    }

    auto fidl_chan = self->ChannelToFidl(std::move(chan));

    cb(fit::ok(std::move(fidl_chan)));
  };
  ZX_DEBUG_ASSERT(adapter());

  adapter()->bredr()->OpenL2capChannel(
      id, psm, fidl_helpers::FidlToBrEdrSecurityRequirements(parameters),
      FidlToChannelParameters(parameters), std::move(connected_cb));
}

void ProfileServer::ConnectSco(
    ::fuchsia::bluetooth::PeerId fidl_peer_id, bool initiator,
    fuchsia::bluetooth::bredr::ScoConnectionParameters fidl_params,
    fidl::InterfaceHandle<fuchsia::bluetooth::bredr::ScoConnectionReceiver> receiver) {
  bt::PeerId peer_id(fidl_peer_id.value);
  auto client = receiver.Bind();

  auto params_result = fidl_helpers::FidlToScoParameters(fidl_params);
  if (params_result.is_error()) {
    bt_log(WARN, "fidl", "%s: invalid parameters (peer: %s)", __FUNCTION__, bt_str(peer_id));
    client->Error(fidlbredr::ScoErrorCode::INVALID_ARGUMENTS);
    return;
  }
  auto params = params_result.value();

  auto request = fbl::MakeRefCounted<ScoRequest>();
  client.set_error_handler([request](zx_status_t status) { request->request_handle.reset(); });
  request->receiver = std::move(client);

  auto callback = [self = weak_ptr_factory_.GetWeakPtr(), request](auto result) {
    // The connection may complete after this server is destroyed.
    if (!self) {
      // Prevent leaking connections.
      if (result.is_ok()) {
        result.value()->Deactivate();
      }
      return;
    }

    self->OnScoConnectionResult(request, std::move(result));
  };

  request->request_handle =
      adapter()->bredr()->OpenScoConnection(peer_id, initiator, params, std::move(callback));
}

void ProfileServer::OnChannelConnected(uint64_t ad_id, fbl::RefPtr<bt::l2cap::Channel> channel,
                                       const bt::sdp::DataElement& protocol_list) {
  auto it = current_advertised_.find(ad_id);
  if (it == current_advertised_.end()) {
    // The receiver has disappeared, do nothing.
    return;
  }

  ZX_DEBUG_ASSERT(adapter());
  auto handle = channel->link_handle();
  auto id = adapter()->bredr()->GetPeerId(handle);

  // The protocol that is connected should be L2CAP, because that is the only thing that
  // we can connect. We can't say anything about what the higher level protocols will be.
  auto prot_seq = protocol_list.At(0);
  ZX_ASSERT(prot_seq);

  fidlbredr::ProtocolDescriptorPtr desc = DataElementToProtocolDescriptor(prot_seq);
  ZX_ASSERT(desc);

  fuchsia::bluetooth::PeerId peer_id{id.value()};

  std::vector<fidlbredr::ProtocolDescriptor> list;
  list.emplace_back(std::move(*desc));

  auto fidl_chan = ChannelToFidl(std::move(channel));

  it->second.receiver->Connected(peer_id, std::move(fidl_chan), std::move(list));
}

void ProfileServer::OnConnectionReceiverError(uint64_t ad_id, zx_status_t status) {
  bt_log(DEBUG, "fidl", "Connection receiver closed, ending advertisement %lu", ad_id);

  auto it = current_advertised_.find(ad_id);

  if (it == current_advertised_.end() || !adapter()) {
    return;
  }

  adapter()->bredr()->UnregisterService(it->second.registration_handle);
  it->second.disconnection_cb(fit::ok());

  current_advertised_.erase(it);
}

void ProfileServer::OnSearchResultError(uint64_t search_id, zx_status_t status) {
  bt_log(DEBUG, "fidl", "Search result closed, ending search %lu reason %s", search_id,
         zx_status_get_string(status));

  auto it = searches_.find(search_id);

  if (it == searches_.end() || !adapter()) {
    return;
  }

  adapter()->bredr()->RemoveServiceSearch(it->second.search_id);

  searches_.erase(it);
}

void ProfileServer::OnServiceFound(
    uint64_t search_id, bt::PeerId peer_id,
    const std::map<bt::sdp::AttributeId, bt::sdp::DataElement>& attributes) {
  auto search_it = searches_.find(search_id);
  if (search_it == searches_.end()) {
    // Search was de-registered.
    return;
  }

  // Convert ProfileDescriptor Attribute
  auto it = attributes.find(bt::sdp::kProtocolDescriptorList);

  fidl::VectorPtr<fidlbredr::ProtocolDescriptor> descriptor_list;

  if (it != attributes.end()) {
    std::vector<fidlbredr::ProtocolDescriptor> list;
    size_t idx = 0;
    auto* sdp_list_element = it->second.At(idx);
    while (sdp_list_element != nullptr) {
      fidlbredr::ProtocolDescriptorPtr desc = DataElementToProtocolDescriptor(sdp_list_element);
      if (!desc) {
        break;
      }
      list.push_back(std::move(*desc));
      sdp_list_element = it->second.At(++idx);
    }
    descriptor_list = std::move(list);
  }

  // Add the rest of the attributes
  std::vector<fidlbredr::Attribute> fidl_attrs;

  for (const auto& it : attributes) {
    auto attr = fidlbredr::Attribute::New();
    attr->id = it.first;
    attr->element = std::move(*DataElementToFidl(&it.second));
    fidl_attrs.emplace_back(std::move(*attr));
  }

  fuchsia::bluetooth::PeerId fidl_peer_id{peer_id.value()};

  search_it->second.results->ServiceFound(fidl_peer_id, std::move(descriptor_list),
                                          std::move(fidl_attrs), []() {});
}

void ProfileServer::OnScoConnectionResult(fbl::RefPtr<ScoRequest> request,
                                          bt::sco::ScoConnectionManager::ConnectionResult result) {
  auto receiver = std::move(request->receiver);

  if (result.is_error()) {
    if (!receiver.is_bound()) {
      return;
    }

    bt_log(INFO, "fidl", "%s: SCO connection failed (status: %s)", __FUNCTION__,
           bt::HostErrorToString(result.error()).c_str());

    if (result.error() == bt::HostError::kCanceled) {
      receiver->Error(fuchsia::bluetooth::bredr::ScoErrorCode::CANCELLED);
      return;
    }
    receiver->Error(fuchsia::bluetooth::bredr::ScoErrorCode::FAILURE);
    return;
  }

  fidlbredr::ScoConnection connection;
  connection.set_socket(sco_socket_factory_.MakeSocketForChannel(result.value()));

  if (!receiver.is_bound()) {
    return;
  }
  receiver->Connected(std::move(connection));
}

void ProfileServer::OnAudioDirectionExtError(AudioDirectionExt* ext_server, zx_status_t status) {
  bt_log(DEBUG, "fidl", "audio direction ext server closed (reason: %s)",
         zx_status_get_string(status));

  auto it = audio_direction_ext_servers_.find(ext_server);
  if (it == audio_direction_ext_servers_.end()) {
    bt_log(WARN, "fidl", "could not find ext server in audio direction ext error callback");
    return;
  }

  audio_direction_ext_servers_.erase(it);
}

fidl::InterfaceHandle<fidlbredr::AudioDirectionExt> ProfileServer::BindAudioDirectionExtServer(
    fbl::RefPtr<bt::l2cap::Channel> channel) {
  fidl::InterfaceHandle<fidlbredr::AudioDirectionExt> client;

  auto audio_direction_ext_server =
      std::make_unique<AudioDirectionExt>(client.NewRequest(), std::move(channel));
  AudioDirectionExt* server_ptr = audio_direction_ext_server.get();

  audio_direction_ext_server->set_error_handler(
      [this, server_ptr](zx_status_t status) { OnAudioDirectionExtError(server_ptr, status); });

  audio_direction_ext_servers_[server_ptr] = std::move(audio_direction_ext_server);

  return client;
}

void ProfileServer::OnL2capParametersExtError(L2capParametersExt* ext_server, zx_status_t status) {
  bt_log(DEBUG, "fidl", "fidl parameters ext server closed (reason: %s)",
         zx_status_get_string(status));
  auto handle = l2cap_parameters_ext_servers_.extract(ext_server);
  ZX_ASSERT(handle);
}

fidl::InterfaceHandle<fidlbredr::L2capParametersExt> ProfileServer::BindL2capParametersExtServer(
    fbl::RefPtr<bt::l2cap::Channel> channel) {
  fidl::InterfaceHandle<fidlbredr::L2capParametersExt> client;

  auto l2cap_parameters_ext_server =
      std::make_unique<L2capParametersExt>(client.NewRequest(), std::move(channel));
  L2capParametersExt* server_ptr = l2cap_parameters_ext_server.get();

  l2cap_parameters_ext_server->set_error_handler(
      [this, server_ptr](zx_status_t status) { OnL2capParametersExtError(server_ptr, status); });

  l2cap_parameters_ext_servers_[server_ptr] = std::move(l2cap_parameters_ext_server);
  return client;
}

fuchsia::bluetooth::bredr::Channel ProfileServer::ChannelToFidl(
    fbl::RefPtr<bt::l2cap::Channel> channel) {
  ZX_ASSERT(channel);
  fidlbredr::Channel fidl_chan;
  fidl_chan.set_channel_mode(ChannelModeToFidl(channel->mode()));
  fidl_chan.set_max_tx_sdu_size(channel->max_tx_sdu_size());
  if (channel->info().flush_timeout) {
    fidl_chan.set_flush_timeout(channel->info().flush_timeout->get());
  }
  auto sock = l2cap_socket_factory_.MakeSocketForChannel(channel);
  fidl_chan.set_socket(std::move(sock));

  if (adapter()->state().vendor_features() & BT_VENDOR_FEATURES_SET_ACL_PRIORITY_COMMAND) {
    fidl_chan.set_ext_direction(BindAudioDirectionExtServer(channel));
  }

  fidl_chan.set_ext_l2cap(BindL2capParametersExtServer(std::move(channel)));
  return fidl_chan;
}

ProfileServer::AudioDirectionExt::AudioDirectionExt(
    fidl::InterfaceRequest<fidlbredr::AudioDirectionExt> request,
    fbl::RefPtr<bt::l2cap::Channel> channel)
    : ServerBase(this, std::move(request)), channel_(std::move(channel)) {}

void ProfileServer::AudioDirectionExt::SetPriority(
    fuchsia::bluetooth::bredr::A2dpDirectionPriority priority, SetPriorityCallback callback) {
  channel_->RequestAclPriority(FidlToAclPriority(priority),
                               [cb = std::move(callback)](auto result) {
                                 if (result.is_ok()) {
                                   cb(fit::ok());
                                   return;
                                 }
                                 bt_log(DEBUG, "fidl", "ACL priority request failed");
                                 cb(fit::error(fuchsia::bluetooth::ErrorCode::FAILED));
                               });
}

}  // namespace bthost
