// Copyright 2017 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 "fake_controller.h"

#include <endian.h>
#include <lib/async/cpp/task.h>

#include "garnet/drivers/bluetooth/lib/common/packet_view.h"
#include "garnet/drivers/bluetooth/lib/hci/defaults.h"
#include "garnet/drivers/bluetooth/lib/hci/hci.h"
#include "garnet/drivers/bluetooth/lib/hci/util.h"
#include "garnet/drivers/bluetooth/lib/testing/fake_device.h"
#include "lib/fxl/strings/string_printf.h"

namespace btlib {

using common::BufferView;
using common::ByteBuffer;
using common::StaticByteBuffer;

namespace testing {
namespace {

template <typename NUM_TYPE, typename ENUM_TYPE>
void SetBit(NUM_TYPE* num_type, ENUM_TYPE bit) {
  *num_type |= static_cast<NUM_TYPE>(bit);
}

template <typename NUM_TYPE, typename ENUM_TYPE>
void UnsetBit(NUM_TYPE* num_type, ENUM_TYPE bit) {
  *num_type &= ~static_cast<NUM_TYPE>(bit);
}

template <typename NUM_TYPE, typename ENUM_TYPE>
bool CheckBit(NUM_TYPE num_type, ENUM_TYPE bit) {
  return (num_type & static_cast<NUM_TYPE>(bit));
}

hci::LEPeerAddressType ToPeerAddrType(common::DeviceAddress::Type type) {
  hci::LEPeerAddressType result = hci::LEPeerAddressType::kAnonymous;

  switch (type) {
    case common::DeviceAddress::Type::kLEPublic:
      result = hci::LEPeerAddressType::kPublic;
      break;
    case common::DeviceAddress::Type::kLERandom:
      result = hci::LEPeerAddressType::kRandom;
      break;
    default:
      break;
  }

  return result;
}

}  // namespace

FakeController::Settings::Settings() {
  std::memset(this, 0, sizeof(*this));
  hci_version = hci::HCIVersion::k5_0;
  num_hci_command_packets = 250;
}

void FakeController::Settings::ApplyDualModeDefaults() {
  std::memset(this, 0, sizeof(*this));
  hci_version = hci::HCIVersion::k5_0;
  num_hci_command_packets = 250;

  acl_data_packet_length = 512;
  total_num_acl_data_packets = 1;
  le_acl_data_packet_length = 512;
  le_total_num_acl_data_packets = 1;

  SetBit(&lmp_features_page0, hci::LMPFeature::kLESupported);
  SetBit(&lmp_features_page0, hci::LMPFeature::kSimultaneousLEAndBREDR);
  SetBit(&lmp_features_page0, hci::LMPFeature::kExtendedFeatures);
  SetBit(&lmp_features_page0, hci::LMPFeature::kRSSIwithInquiryResults);
  SetBit(&lmp_features_page0, hci::LMPFeature::kExtendedInquiryResponse);

  AddBREDRSupportedCommands();
  AddLESupportedCommands();
}

void FakeController::Settings::ApplyLEOnlyDefaults() {
  ApplyDualModeDefaults();

  UnsetBit(&lmp_features_page0, hci::LMPFeature::kSimultaneousLEAndBREDR);
  SetBit(&lmp_features_page0, hci::LMPFeature::kBREDRNotSupported);

  std::memset(supported_commands, 0, sizeof(supported_commands));
  AddLESupportedCommands();
}

void FakeController::Settings::AddBREDRSupportedCommands() {
  SetBit(supported_commands + 7, hci::SupportedCommand::kWriteLocalName);
  SetBit(supported_commands + 7, hci::SupportedCommand::kReadLocalName);
  SetBit(supported_commands + 7, hci::SupportedCommand::kReadScanEnable);
  SetBit(supported_commands + 7, hci::SupportedCommand::kWriteScanEnable);
  SetBit(supported_commands + 8, hci::SupportedCommand::kReadPageScanActivity);
  SetBit(supported_commands + 8, hci::SupportedCommand::kWritePageScanActivity);
  SetBit(supported_commands + 12, hci::SupportedCommand::kReadInquiryMode);
  SetBit(supported_commands + 12, hci::SupportedCommand::kWriteInquiryMode);
  SetBit(supported_commands + 13, hci::SupportedCommand::kReadPageScanType);
  SetBit(supported_commands + 13, hci::SupportedCommand::kWritePageScanType);
  SetBit(supported_commands + 14, hci::SupportedCommand::kReadBufferSize);
  SetBit(supported_commands + 17,
         hci::SupportedCommand::kReadSimplePairingMode);
  SetBit(supported_commands + 17,
         hci::SupportedCommand::kWriteSimplePairingMode);
}

void FakeController::Settings::AddLESupportedCommands() {
  SetBit(supported_commands, hci::SupportedCommand::kDisconnect);
  SetBit(supported_commands + 5, hci::SupportedCommand::kSetEventMask);
  SetBit(supported_commands + 5, hci::SupportedCommand::kReset);
  SetBit(supported_commands + 14,
         hci::SupportedCommand::kReadLocalVersionInformation);
  SetBit(supported_commands + 14,
         hci::SupportedCommand::kReadLocalSupportedFeatures);
  SetBit(supported_commands + 14,
         hci::SupportedCommand::kReadLocalExtendedFeatures);
  SetBit(supported_commands + 24, hci::SupportedCommand::kWriteLEHostSupport);
  SetBit(supported_commands + 25, hci::SupportedCommand::kLESetEventMask);
  SetBit(supported_commands + 25, hci::SupportedCommand::kLEReadBufferSize);
  SetBit(supported_commands + 25,
         hci::SupportedCommand::kLEReadLocalSupportedFeatures);
  SetBit(supported_commands + 25, hci::SupportedCommand::kLESetRandomAddress);
  SetBit(supported_commands + 25,
         hci::SupportedCommand::kLESetAdvertisingParameters);
  SetBit(supported_commands + 25, hci::SupportedCommand::kLESetAdvertisingData);
  SetBit(supported_commands + 26,
         hci::SupportedCommand::kLESetScanResponseData);
  SetBit(supported_commands + 26,
         hci::SupportedCommand::kLESetAdvertisingEnable);
  SetBit(supported_commands + 26, hci::SupportedCommand::kLECreateConnection);
  SetBit(supported_commands + 26,
         hci::SupportedCommand::kLECreateConnectionCancel);
  SetBit(supported_commands + 27, hci::SupportedCommand::kLEConnectionUpdate);
}

void FakeController::Settings::ApplyLegacyLEConfig() {
  ApplyLEOnlyDefaults();

  hci_version = hci::HCIVersion::k4_2;

  SetBit(supported_commands + 26, hci::SupportedCommand::kLESetScanParameters);
  SetBit(supported_commands + 26, hci::SupportedCommand::kLESetScanEnable);
}

void FakeController::Settings::ApplyLEConfig() {
  ApplyLEOnlyDefaults();

  SetBit(&le_features, hci::LESupportedFeature::kLEExtendedAdvertising);
}

FakeController::LEScanState::LEScanState()
    : enabled(false),
      scan_type(hci::LEScanType::kPassive),
      scan_interval(0),
      scan_window(0),
      filter_duplicates(false),
      filter_policy(hci::LEScanFilterPolicy::kNoWhiteList) {}

FakeController::LEAdvertisingState::LEAdvertisingState()
    : enabled(false), interval(0), data_length(0), scan_rsp_length(0) {
  std::memset(data, 0, sizeof(data));
  std::memset(scan_rsp_data, 0, sizeof(scan_rsp_data));
}

FakeController::FakeController()
    : page_scan_type_(hci::PageScanType::kStandardScan),
      page_scan_interval_(0x0800),
      page_scan_window_(0x0012),
      next_conn_handle_(0u),
      le_connect_pending_(false),
      next_le_sig_id_(1u),
      scan_state_cb_dispatcher_(nullptr),
      advertising_state_cb_dispatcher_(nullptr),
      conn_state_cb_dispatcher_(nullptr),
      le_conn_params_cb_dispatcher_(nullptr) {}

FakeController::~FakeController() { Stop(); }

void FakeController::SetDefaultResponseStatus(hci::OpCode opcode,
                                              hci::StatusCode status) {
  FXL_DCHECK(status != hci::StatusCode::kSuccess);
  default_status_map_[opcode] = status;
}

void FakeController::ClearDefaultResponseStatus(hci::OpCode opcode) {
  default_status_map_.erase(opcode);
}

void FakeController::AddDevice(std::unique_ptr<FakeDevice> device) {
  device->set_ctrl(this);
  devices_.push_back(std::move(device));
}

void FakeController::SetScanStateCallback(
    ScanStateCallback callback,
    async_dispatcher_t* dispatcher) {
  FXL_DCHECK(callback);
  FXL_DCHECK(dispatcher);

  scan_state_cb_ = std::move(callback);
  scan_state_cb_dispatcher_ = dispatcher;
}

void FakeController::SetAdvertisingStateCallback(
    fit::closure callback,
    async_dispatcher_t* dispatcher) {
  FXL_DCHECK(callback);
  FXL_DCHECK(dispatcher);

  advertising_state_cb_ = std::move(callback);
  advertising_state_cb_dispatcher_ = dispatcher;
}

void FakeController::SetConnectionStateCallback(
    ConnectionStateCallback callback,
    async_dispatcher_t* dispatcher) {
  FXL_DCHECK(callback);
  FXL_DCHECK(dispatcher);

  conn_state_cb_ = std::move(callback);
  conn_state_cb_dispatcher_ = dispatcher;
}

void FakeController::SetLEConnectionParametersCallback(
    LEConnectionParametersCallback callback,
    async_dispatcher_t* dispatcher) {
  FXL_DCHECK(callback);
  FXL_DCHECK(dispatcher);

  le_conn_params_cb_ = std::move(callback);
  le_conn_params_cb_dispatcher_ = dispatcher;
}

FakeDevice* FakeController::FindDeviceByAddress(
    const common::DeviceAddress& addr) {
  for (auto& dev : devices_) {
    if (dev->address() == addr)
      return dev.get();
  }
  return nullptr;
}

FakeDevice* FakeController::FindDeviceByConnHandle(
    hci::ConnectionHandle handle) {
  for (auto& dev : devices_) {
    if (dev->HasLink(handle))
      return dev.get();
  }
  return nullptr;
}

uint8_t FakeController::NextL2CAPCommandId() {
  // TODO(armansito): Guard against overflow?
  return next_le_sig_id_++;
}

void FakeController::RespondWithCommandComplete(hci::OpCode opcode,
                                                const ByteBuffer& params) {
  common::DynamicByteBuffer buffer(sizeof(hci::CommandCompleteEventParams) +
                                   params.size());
  common::MutablePacketView<hci::CommandCompleteEventParams> event(
      &buffer, params.size());

  event.mutable_header()->num_hci_command_packets =
      settings_.num_hci_command_packets;
  event.mutable_header()->command_opcode = htole16(opcode);
  event.mutable_payload_data().Write(params);

  SendEvent(hci::kCommandCompleteEventCode, buffer);
}

void FakeController::RespondWithSuccess(hci::OpCode opcode) {
  hci::SimpleReturnParams out_params;
  out_params.status = hci::StatusCode::kSuccess;
  RespondWithCommandComplete(opcode,
                             BufferView(&out_params, sizeof(out_params)));
}

void FakeController::RespondWithCommandStatus(hci::OpCode opcode,
                                              hci::StatusCode status) {
  common::StaticByteBuffer<sizeof(hci::CommandStatusEventParams)> buffer;
  common::MutablePacketView<hci::CommandStatusEventParams> event(&buffer);

  event.mutable_header()->status = status;
  event.mutable_header()->num_hci_command_packets =
      settings_.num_hci_command_packets;
  event.mutable_header()->command_opcode = htole16(opcode);

  SendEvent(hci::kCommandStatusEventCode, buffer);
}

void FakeController::SendEvent(hci::EventCode event_code,
                               const ByteBuffer& payload) {
  common::DynamicByteBuffer buffer(sizeof(hci::EventHeader) + payload.size());
  common::MutablePacketView<hci::EventHeader> event(&buffer, payload.size());

  event.mutable_header()->event_code = event_code;
  event.mutable_header()->parameter_total_size = payload.size();
  event.mutable_payload_data().Write(payload);

  SendCommandChannelPacket(buffer);
}

void FakeController::SendLEMetaEvent(hci::EventCode subevent_code,
                                     const ByteBuffer& payload) {
  common::DynamicByteBuffer buffer(sizeof(hci::LEMetaEventParams) +
                                   payload.size());
  buffer[0] = subevent_code;
  buffer.Write(payload, 1);

  SendEvent(hci::kLEMetaEventCode, buffer);
}

void FakeController::SendACLPacket(hci::ConnectionHandle handle,
                                   const ByteBuffer& payload) {
  FXL_DCHECK(payload.size() <= hci::kMaxACLPayloadSize);

  common::DynamicByteBuffer buffer(sizeof(hci::ACLDataHeader) + payload.size());
  common::MutablePacketView<hci::ACLDataHeader> acl(&buffer, payload.size());

  acl.mutable_header()->handle_and_flags = htole16(handle);
  acl.mutable_header()->data_total_length =
      htole16(static_cast<uint16_t>(payload.size()));
  acl.mutable_payload_data().Write(payload);

  SendACLDataChannelPacket(buffer);
}

void FakeController::SendL2CAPBFrame(hci::ConnectionHandle handle,
                                     l2cap::ChannelId channel_id,
                                     const ByteBuffer& payload) {
  FXL_DCHECK(payload.size() <=
             hci::kMaxACLPayloadSize - sizeof(l2cap::BasicHeader));

  common::DynamicByteBuffer buffer(sizeof(l2cap::BasicHeader) + payload.size());
  common::MutablePacketView<l2cap::BasicHeader> bframe(&buffer, payload.size());

  bframe.mutable_header()->length = htole16(payload.size());
  bframe.mutable_header()->channel_id = htole16(channel_id);
  bframe.mutable_payload_data().Write(payload);

  SendACLPacket(handle, buffer);
}

void FakeController::SendL2CAPCFrame(hci::ConnectionHandle handle, bool is_le,
                                     l2cap::CommandCode code, uint8_t id,
                                     const ByteBuffer& payload) {
  common::DynamicByteBuffer buffer(sizeof(l2cap::CommandHeader) +
                                   payload.size());
  common::MutablePacketView<l2cap::CommandHeader> cframe(&buffer,
                                                         payload.size());

  cframe.mutable_header()->code = code;
  cframe.mutable_header()->id = id;
  cframe.mutable_header()->length = payload.size();
  cframe.mutable_payload_data().Write(payload);

  SendL2CAPBFrame(
      handle, is_le ? l2cap::kLESignalingChannelId : l2cap::kSignalingChannelId,
      buffer);
}

void FakeController::SendNumberOfCompletedPacketsEvent(
    hci::ConnectionHandle handle, uint16_t num) {
  StaticByteBuffer<sizeof(hci::NumberOfCompletedPacketsEventParams) +
                   sizeof(hci::NumberOfCompletedPacketsEventData)>
      buffer;

  auto* params = reinterpret_cast<hci::NumberOfCompletedPacketsEventParams*>(
      buffer.mutable_data());
  params->number_of_handles = 1;
  params->data->connection_handle = htole16(handle);
  params->data->hc_num_of_completed_packets = htole16(num);

  SendEvent(hci::kNumberOfCompletedPacketsEventCode, buffer);
}

void FakeController::ConnectLowEnergy(const common::DeviceAddress& addr,
                                      hci::ConnectionRole role) {
  async::PostTask(dispatcher(), [addr, role, this] {
    FakeDevice* dev = FindDeviceByAddress(addr);
    if (!dev) {
      FXL_LOG(WARNING) << "bt-hci (fake): no device found with address: "
                       << addr.ToString();
      return;
    }

    // TODO(armansito): Don't worry about managing multiple links per device
    // until this supports Bluetooth classic.
    if (dev->connected()) {
      FXL_LOG(WARNING) << "bt-hci (fake): device already connected";
      return;
    }

    dev->set_connected(true);
    hci::ConnectionHandle handle = ++next_conn_handle_;
    dev->AddLink(handle);

    NotifyConnectionState(addr, true);

    auto interval_min = hci::defaults::kLEConnectionIntervalMin;
    auto interval_max = hci::defaults::kLEConnectionIntervalMax;

    hci::LEConnectionParameters conn_params(
        interval_min + ((interval_max - interval_min) / 2), 0,
        hci::defaults::kLESupervisionTimeout);
    dev->set_le_params(conn_params);

    hci::LEConnectionCompleteSubeventParams params;
    std::memset(&params, 0, sizeof(params));

    params.status = hci::StatusCode::kSuccess;
    params.peer_address = addr.value();
    params.peer_address_type = ToPeerAddrType(addr.type());
    params.conn_latency = htole16(conn_params.latency());
    params.conn_interval = htole16(conn_params.interval());
    params.supervision_timeout = htole16(conn_params.supervision_timeout());
    params.role = role;
    params.connection_handle = htole16(handle);

    SendLEMetaEvent(hci::kLEConnectionCompleteSubeventCode,
                    BufferView(&params, sizeof(params)));
  });
}

void FakeController::L2CAPConnectionParameterUpdate(
    const common::DeviceAddress& addr,
    const hci::LEPreferredConnectionParameters& params) {
      async::PostTask(dispatcher(), [addr, params, this] {
        FakeDevice* dev = FindDeviceByAddress(addr);
        if (!dev) {
          FXL_LOG(WARNING) << "bt-hci (fake): no device found with address: "
                           << addr.ToString();
          return;
        }

        if (!dev->connected()) {
          FXL_LOG(WARNING) << "bt-hci (fake): device not connected";
          return;
        }

        FXL_DCHECK(!dev->logical_links().empty());

        l2cap::ConnectionParameterUpdateRequestPayload payload;
        payload.interval_min = htole16(params.min_interval());
        payload.interval_max = htole16(params.max_interval());
        payload.slave_latency = htole16(params.max_latency());
        payload.timeout_multiplier = htole16(params.supervision_timeout());

        // TODO(armansito): Instead of picking the first handle we should pick
        // the handle that matches the current LE-U link.
        SendL2CAPCFrame(*dev->logical_links().begin(), true,
                        l2cap::kConnectionParameterUpdateRequest,
                        NextL2CAPCommandId(),
                        BufferView(&payload, sizeof(payload)));
      });
}

void FakeController::Disconnect(const common::DeviceAddress& addr) {
  async::PostTask(dispatcher(), [addr, this] {
    FakeDevice* dev = FindDeviceByAddress(addr);
    if (!dev || !dev->connected()) {
      FXL_LOG(WARNING)
          << "bt-hci (fake): no connected device found with address: "
          << addr.ToString();
      return;
    }

    auto links = dev->Disconnect();
    FXL_DCHECK(!dev->connected());
    FXL_DCHECK(!links.empty());

    NotifyConnectionState(addr, false);

    for (auto link : links) {
      hci::DisconnectionCompleteEventParams params;
      params.status = hci::StatusCode::kSuccess;
      params.connection_handle = htole16(link);
      params.reason = hci::StatusCode::kRemoteUserTerminatedConnection;
      SendEvent(hci::kDisconnectionCompleteEventCode,
                BufferView(&params, sizeof(params)));
    }
  });
}

bool FakeController::MaybeRespondWithDefaultStatus(hci::OpCode opcode) {
  auto iter = default_status_map_.find(opcode);
  if (iter == default_status_map_.end())
    return false;

  FXL_LOG(INFO) << fxl::StringPrintf(
      "hci: bt-hci (fake): Responding with error (command: 0x%04x, status: "
      "0x%02x",
      opcode, iter->second);

  hci::SimpleReturnParams params;
  params.status = iter->second;
  RespondWithCommandComplete(opcode, BufferView(&params, sizeof(params)));
  return true;
}

void FakeController::SendInquiryResponses() {
  // TODO(jamuraa): combine some of these into a single response event
  for (const auto& device : devices_) {
    if (!device->has_inquiry_response()) {
      continue;
    }

    SendCommandChannelPacket(device->CreateInquiryResponseEvent(inquiry_mode_));
    inquiry_num_responses_left_--;
    if (inquiry_num_responses_left_ == 0) {
      break;
    }
  }
}

void FakeController::SendAdvertisingReports() {
  if (!le_scan_state_.enabled || devices_.empty())
    return;

  for (const auto& device : devices_) {
    if (!device->has_advertising_reports()) {
      continue;
    }
    // We want to send scan response packets only during an active scan and if
    // the device is scannable.
    bool need_scan_rsp =
        (le_scan_state().scan_type == hci::LEScanType::kActive) &&
        device->scannable();
    SendCommandChannelPacket(device->CreateAdvertisingReportEvent(
        need_scan_rsp && device->should_batch_reports()));

    // If the original report did not include a scan response then we send it as
    // a separate event.
    if (need_scan_rsp && !device->should_batch_reports()) {
      SendCommandChannelPacket(device->CreateScanResponseReportEvent());
    }
  }

  // We'll send new reports for the same devices if duplicate filtering is
  // disabled.
  if (!le_scan_state_.filter_duplicates) {
    async::PostTask(dispatcher(), [this] { SendAdvertisingReports(); });
  }
}

void FakeController::NotifyAdvertisingState() {
  if (!advertising_state_cb_) {
    return;
  }

  FXL_DCHECK(advertising_state_cb_dispatcher_);
  async::PostTask(advertising_state_cb_dispatcher_, advertising_state_cb_.share());
}

void FakeController::NotifyConnectionState(const common::DeviceAddress& addr,
                                           bool connected,
                                           bool canceled) {
  if (!conn_state_cb_)
    return;

  FXL_DCHECK(conn_state_cb_dispatcher_);
  async::PostTask(conn_state_cb_dispatcher_, [
    addr, connected, canceled, cb = conn_state_cb_.share()
  ] { cb(addr, connected, canceled); });
}

void FakeController::NotifyLEConnectionParameters(
    const common::DeviceAddress& addr,
    const hci::LEConnectionParameters& params) {
  if (!le_conn_params_cb_)
    return;

  FXL_DCHECK(le_conn_params_cb_dispatcher_);
  async::PostTask(le_conn_params_cb_dispatcher_,
      [addr, params, cb = le_conn_params_cb_.share()] { cb(addr, params); });
}

void FakeController::OnLECreateConnectionCommandReceived(
    const hci::LECreateConnectionCommandParams& params) {
  // Cannot issue this command while a request is already pending.
  if (le_connect_pending_) {
    RespondWithCommandStatus(hci::kLECreateConnection,
                             hci::StatusCode::kCommandDisallowed);
    return;
  }

  common::DeviceAddress::Type addr_type =
      hci::AddressTypeFromHCI(params.peer_address_type);
  FXL_DCHECK(addr_type != common::DeviceAddress::Type::kBREDR);

  const common::DeviceAddress peer_address(addr_type, params.peer_address);
  hci::StatusCode status = hci::StatusCode::kSuccess;

  // Find the device that matches the requested address.
  FakeDevice* device = FindDeviceByAddress(peer_address);
  if (device) {
    if (device->connected())
      status = hci::StatusCode::kConnectionAlreadyExists;
    else
      status = device->connect_status();
  }

  // First send the Command Status response.
  RespondWithCommandStatus(hci::kLECreateConnection, status);

  // If we just sent back an error status then the operation is complete.
  if (status != hci::StatusCode::kSuccess)
    return;

  le_connect_pending_ = true;
  pending_le_connect_addr_ = peer_address;

  // The procedure was initiated successfully but the device cannot be connected
  // because it either doesn't exist or isn't connectable.
  if (!device || !device->connectable()) {
    FXL_LOG(INFO)
        << "Requested fake device cannot be connected; request will time out";
    return;
  }

  if (next_conn_handle_ == 0x0FFF) {
    // Ran out of handles
    status = hci::StatusCode::kConnectionLimitExceeded;
  } else {
    status = device->connect_response();
  }

  hci::LEConnectionCompleteSubeventParams response;
  std::memset(&response, 0, sizeof(response));

  response.status = status;
  response.peer_address = params.peer_address;
  response.peer_address_type = ToPeerAddrType(addr_type);

  if (status == hci::StatusCode::kSuccess) {
    uint16_t interval_min = le16toh(params.conn_interval_min);
    uint16_t interval_max = le16toh(params.conn_interval_max);
    uint16_t interval = interval_min + ((interval_max - interval_min) / 2);

    hci::LEConnectionParameters conn_params(
        interval, le16toh(params.conn_latency),
        le16toh(params.supervision_timeout));
    device->set_le_params(conn_params);

    response.conn_latency = params.conn_latency;
    response.conn_interval = le16toh(interval);
    response.supervision_timeout = params.supervision_timeout;

    response.role = hci::ConnectionRole::kMaster;

    hci::ConnectionHandle handle = ++next_conn_handle_;
    response.connection_handle = htole16(handle);
  }

  // Don't send a connection event if we were asked to force the request to
  // remain pending. This is used by test cases that operate during the pending
  // state.
  if (device->force_pending_connect())
    return;

  pending_le_connect_rsp_.Reset([response, device, this] {
    le_connect_pending_ = false;

    if (response.status == hci::StatusCode::kSuccess) {
      bool notify = !device->connected();
      device->AddLink(le16toh(response.connection_handle));
      if (notify && device->connected())
        NotifyConnectionState(device->address(), true);
    }

    SendLEMetaEvent(hci::kLEConnectionCompleteSubeventCode,
                    BufferView(&response, sizeof(response)));
  });
  async::PostTask(dispatcher(),
      [cb = pending_le_connect_rsp_.callback()] { cb(); });
}

void FakeController::OnLEConnectionUpdateCommandReceived(
    const hci::LEConnectionUpdateCommandParams& params) {
  hci::ConnectionHandle handle = le16toh(params.connection_handle);
  FakeDevice* device = FindDeviceByConnHandle(handle);
  if (!device) {
    RespondWithCommandStatus(hci::kLEConnectionUpdate,
                             hci::StatusCode::kUnknownConnectionId);
    return;
  }

  FXL_DCHECK(device->connected());

  uint16_t min_interval = le16toh(params.conn_interval_min);
  uint16_t max_interval = le16toh(params.conn_interval_max);
  uint16_t max_latency = le16toh(params.conn_latency);
  uint16_t supv_timeout = le16toh(params.supervision_timeout);

  if (min_interval > max_interval) {
    RespondWithCommandStatus(hci::kLEConnectionUpdate,
                             hci::StatusCode::kInvalidHCICommandParameters);
    return;
  }

  RespondWithCommandStatus(hci::kLEConnectionUpdate, hci::StatusCode::kSuccess);

  hci::LEConnectionParameters conn_params(
      min_interval + ((max_interval - min_interval) / 2), max_latency,
      supv_timeout);
  device->set_le_params(conn_params);

  hci::LEConnectionUpdateCompleteSubeventParams reply;
  reply.status = hci::StatusCode::kSuccess;
  reply.connection_handle = params.connection_handle;
  reply.conn_interval = htole16(conn_params.interval());
  reply.conn_latency = params.conn_latency;
  reply.supervision_timeout = params.supervision_timeout;

  SendLEMetaEvent(hci::kLEConnectionUpdateCompleteSubeventCode,
                  BufferView(&reply, sizeof(reply)));

  NotifyLEConnectionParameters(device->address(), conn_params);
}

void FakeController::OnDisconnectCommandReceived(
    const hci::DisconnectCommandParams& params) {
  hci::ConnectionHandle handle = le16toh(params.connection_handle);

  // Find the device that matches the disconnected handle.
  FakeDevice* device = FindDeviceByConnHandle(handle);
  if (!device) {
    RespondWithCommandStatus(hci::kDisconnect,
                             hci::StatusCode::kUnknownConnectionId);
    return;
  }

  FXL_DCHECK(device->connected());

  RespondWithCommandStatus(hci::kDisconnect, hci::StatusCode::kSuccess);

  bool notify = device->connected();
  device->RemoveLink(handle);
  if (notify && !device->connected())
    NotifyConnectionState(device->address(), false);

  hci::DisconnectionCompleteEventParams reply;
  reply.status = hci::StatusCode::kSuccess;
  reply.connection_handle = params.connection_handle;
  reply.reason = hci::StatusCode::kConnectionTerminatedByLocalHost;
  SendEvent(hci::kDisconnectionCompleteEventCode,
            BufferView(&reply, sizeof(reply)));
}

void FakeController::OnCommandPacketReceived(
    const common::PacketView<hci::CommandHeader>& command_packet) {
  hci::OpCode opcode = le16toh(command_packet.header().opcode);
  if (MaybeRespondWithDefaultStatus(opcode))
    return;

  // TODO(NET-825): Validate size of payload to be the correct length below.
  switch (opcode) {
    case hci::kReadLocalVersionInfo: {
      hci::ReadLocalVersionInfoReturnParams params;
      std::memset(&params, 0, sizeof(params));
      params.hci_version = settings_.hci_version;
      RespondWithCommandComplete(hci::kReadLocalVersionInfo,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kReadLocalSupportedCommands: {
      hci::ReadLocalSupportedCommandsReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      std::memcpy(params.supported_commands, settings_.supported_commands,
                  sizeof(params.supported_commands));
      RespondWithCommandComplete(hci::kReadLocalSupportedCommands,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kReadLocalSupportedFeatures: {
      hci::ReadLocalSupportedFeaturesReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.lmp_features = htole64(settings_.lmp_features_page0);
      RespondWithCommandComplete(hci::kReadLocalSupportedFeatures,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kLESetRandomAddress: {
      const auto& in_params =
          command_packet.payload<hci::LESetRandomAddressCommandParams>();
      le_random_address_ = common::DeviceAddress(
          common::DeviceAddress::Type::kLERandom, in_params.random_address);

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kLESetAdvertisingParameters: {
      const auto& in_params =
          command_packet
              .payload<hci::LESetAdvertisingParametersCommandParams>();
      // TODO(jamuraa): when we parse advertising params, return Invalid HCI
      // Command Parameters when apporopriate (Vol 2, Part E, 7.8.9 p1259)
      if (le_adv_state_.enabled) {
        hci::SimpleReturnParams out_params;
        out_params.status = hci::StatusCode::kCommandDisallowed;
        RespondWithCommandComplete(opcode,
                                   BufferView(&out_params, sizeof(out_params)));
        return;
      }

      uint32_t interval_min = le16toh(in_params.adv_interval_min);
      uint32_t interval_max = le16toh(in_params.adv_interval_max);

      // Just assign the average for the interval.
      le_adv_state_.interval = (interval_min + interval_max) / 2;
      le_adv_state_.adv_type = in_params.adv_type;

      RespondWithSuccess(opcode);
      NotifyAdvertisingState();
      break;
    }
    case hci::kLESetAdvertisingData: {
      const auto& in_params =
          command_packet.payload<hci::LESetAdvertisingDataCommandParams>();
      le_adv_state_.data_length = in_params.adv_data_length;
      std::memcpy(le_adv_state_.data, in_params.adv_data,
                  le_adv_state_.data_length);

      RespondWithSuccess(opcode);
      NotifyAdvertisingState();
      break;
    }
    case hci::kLESetScanResponseData: {
      const auto& in_params =
          command_packet.payload<hci::LESetScanResponseDataCommandParams>();
      le_adv_state_.scan_rsp_length = in_params.scan_rsp_data_length;
      std::memcpy(le_adv_state_.scan_rsp_data, in_params.scan_rsp_data,
                  le_adv_state_.scan_rsp_length);

      RespondWithSuccess(opcode);
      NotifyAdvertisingState();
      break;
    }
    case hci::kLESetAdvertisingEnable: {
      const auto& in_params =
          command_packet.payload<hci::LESetAdvertisingEnableCommandParams>();
      le_adv_state_.enabled =
          (in_params.advertising_enable == hci::GenericEnableParam::kEnable);

      RespondWithSuccess(opcode);
      NotifyAdvertisingState();
      break;
    }
    case hci::kReadBDADDR: {
      hci::ReadBDADDRReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.bd_addr = settings_.bd_addr.value();
      RespondWithCommandComplete(hci::kReadBDADDR,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kReadBufferSize: {
      hci::ReadBufferSizeReturnParams params;
      std::memset(&params, 0, sizeof(params));
      params.hc_acl_data_packet_length =
          htole16(settings_.acl_data_packet_length);
      params.hc_total_num_acl_data_packets =
          settings_.total_num_acl_data_packets;
      RespondWithCommandComplete(hci::kReadBufferSize,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kDisconnect: {
      OnDisconnectCommandReceived(
          command_packet.payload<hci::DisconnectCommandParams>());
      break;
    }
    case hci::kWriteLocalName: {
      const auto& in_params =
          command_packet.payload<hci::WriteLocalNameCommandParams>();
      local_name_ = std::string(in_params.local_name,
                                in_params.local_name + hci::kMaxNameLength);
      RespondWithSuccess(opcode);
      break;
    }
    case hci::kReadLocalName: {
      hci::ReadLocalNameReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      auto mut_view =
          common::MutableBufferView(params.local_name, hci::kMaxNameLength);
      mut_view.Write((uint8_t*)(local_name_.c_str()), hci::kMaxNameLength);
      RespondWithCommandComplete(hci::kReadLocalName,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kReadScanEnable: {
      hci::ReadScanEnableReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.scan_enable = bredr_scan_state_;

      RespondWithCommandComplete(hci::kReadScanEnable,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kWriteScanEnable: {
      const auto& in_params =
          command_packet.payload<hci::WriteScanEnableCommandParams>();
      bredr_scan_state_ = in_params.scan_enable;

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kReadPageScanActivity: {
      hci::ReadPageScanActivityReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.page_scan_interval = htole16(page_scan_interval_);
      params.page_scan_window = htole16(page_scan_window_);

      RespondWithCommandComplete(hci::kReadPageScanActivity,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kWritePageScanActivity: {
      const auto& in_params =
          command_packet.payload<hci::WritePageScanActivityCommandParams>();
      page_scan_interval_ = letoh16(in_params.page_scan_interval);
      page_scan_window_ = letoh16(in_params.page_scan_window);

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kReadInquiryMode: {
      hci::ReadInquiryModeReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.inquiry_mode = inquiry_mode_;
      RespondWithCommandComplete(hci::kReadInquiryMode,
                                 common::BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kWriteInquiryMode: {
      const auto& in_params =
          command_packet.payload<hci::WriteInquiryModeCommandParams>();
      inquiry_mode_ = in_params.inquiry_mode;
      RespondWithSuccess(opcode);
      break;
    };
    case hci::kReadPageScanType: {
      hci::ReadPageScanTypeReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.page_scan_type = page_scan_type_;

      RespondWithCommandComplete(hci::kReadPageScanType,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kWritePageScanType: {
      const auto& in_params =
          command_packet.payload<hci::WritePageScanTypeCommandParams>();
      page_scan_type_ = in_params.page_scan_type;

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kReadSimplePairingMode: {
      hci::ReadSimplePairingModeReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      if (CheckBit(settings_.lmp_features_page1,
                   hci::LMPFeature::kSecureSimplePairingHostSupport)) {
        params.simple_pairing_mode = hci::GenericEnableParam::kEnable;
      }

      RespondWithCommandComplete(hci::kReadSimplePairingMode,
                                 common::BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kWriteSimplePairingMode: {
      const auto& in_params =
          command_packet.payload<hci::WriteSimplePairingModeCommandParams>();
      // "A host shall not set the Simple Pairing Mode to 'disabled'"
      // Spec 5.0 Vol 2 Part E Sec 7.3.59
      if (in_params.simple_pairing_mode != hci::GenericEnableParam::kEnable) {
        hci::SimpleReturnParams params;
        params.status = hci::StatusCode::kInvalidHCICommandParameters;
        RespondWithCommandComplete(hci::kWriteSimplePairingMode,
                                   common::BufferView(&params, sizeof(params)));
        break;
      }

      SetBit(&settings_.lmp_features_page1,
             hci::LMPFeature::kSecureSimplePairingHostSupport);

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kLEConnectionUpdate: {
      OnLEConnectionUpdateCommandReceived(
          command_packet.payload<hci::LEConnectionUpdateCommandParams>());
      break;
    }
    case hci::kLECreateConnection: {
      OnLECreateConnectionCommandReceived(
          command_packet.payload<hci::LECreateConnectionCommandParams>());
      break;
    }
    case hci::kLECreateConnectionCancel: {
      hci::SimpleReturnParams params;
      params.status = hci::StatusCode::kSuccess;

      if (!le_connect_pending_) {
        // No request is currently pending.
        params.status = hci::StatusCode::kCommandDisallowed;
        RespondWithCommandComplete(hci::kLECreateConnectionCancel,
                                   BufferView(&params, sizeof(params)));
        return;
      }

      le_connect_pending_ = false;
      pending_le_connect_rsp_.Cancel();

      NotifyConnectionState(pending_le_connect_addr_, false, true);

      hci::LEConnectionCompleteSubeventParams response;
      std::memset(&response, 0, sizeof(response));

      response.status = hci::StatusCode::kUnknownConnectionId;
      response.peer_address = pending_le_connect_addr_.value();
      response.peer_address_type =
          ToPeerAddrType(pending_le_connect_addr_.type());

      RespondWithCommandComplete(hci::kLECreateConnectionCancel,
                                 BufferView(&params, sizeof(params)));
      SendLEMetaEvent(hci::kLEConnectionCompleteSubeventCode,
                      BufferView(&response, sizeof(response)));
      break;
    }
    case hci::kLEReadLocalSupportedFeatures: {
      hci::LEReadLocalSupportedFeaturesReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.le_features = htole64(settings_.le_features);
      RespondWithCommandComplete(hci::kLEReadLocalSupportedFeatures,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kLEReadSupportedStates: {
      hci::LEReadSupportedStatesReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.le_states = htole64(settings_.le_supported_states);
      RespondWithCommandComplete(hci::kLEReadSupportedStates,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kLEReadBufferSize: {
      hci::LEReadBufferSizeReturnParams params;
      params.status = hci::StatusCode::kSuccess;
      params.hc_le_acl_data_packet_length =
          htole16(settings_.le_acl_data_packet_length);
      params.hc_total_num_le_acl_data_packets =
          settings_.le_total_num_acl_data_packets;
      RespondWithCommandComplete(hci::kLEReadBufferSize,
                                 BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kSetEventMask: {
      const auto& in_params =
          command_packet.payload<hci::SetEventMaskCommandParams>();
      settings_.event_mask = le64toh(in_params.event_mask);

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kLESetEventMask: {
      const auto& in_params =
          command_packet.payload<hci::LESetEventMaskCommandParams>();
      settings_.le_event_mask = le64toh(in_params.le_event_mask);

      RespondWithSuccess(opcode);
      break;
    }
    case hci::kReadLocalExtendedFeatures: {
      const auto& in_params =
          command_packet.payload<hci::ReadLocalExtendedFeaturesCommandParams>();

      hci::ReadLocalExtendedFeaturesReturnParams out_params;
      out_params.page_number = in_params.page_number;
      out_params.maximum_page_number = 2;

      if (in_params.page_number > 2) {
        out_params.status = hci::StatusCode::kInvalidHCICommandParameters;
      } else {
        out_params.status = hci::StatusCode::kSuccess;

        switch (in_params.page_number) {
          case 0:
            out_params.extended_lmp_features =
                htole64(settings_.lmp_features_page0);
            break;
          case 1:
            out_params.extended_lmp_features =
                htole64(settings_.lmp_features_page1);
            break;
          case 2:
            out_params.extended_lmp_features =
                htole64(settings_.lmp_features_page2);
            break;
        }
      }
      RespondWithCommandComplete(hci::kReadLocalExtendedFeatures,
                                 BufferView(&out_params, sizeof(out_params)));
      break;
    }
    case hci::kLESetScanParameters: {
      const auto& in_params =
          command_packet.payload<hci::LESetScanParametersCommandParams>();

      hci::SimpleReturnParams out_params;
      if (le_scan_state_.enabled) {
        out_params.status = hci::StatusCode::kCommandDisallowed;
      } else {
        out_params.status = hci::StatusCode::kSuccess;
        le_scan_state_.scan_type = in_params.scan_type;
        le_scan_state_.scan_interval = le16toh(in_params.scan_interval);
        le_scan_state_.scan_window = le16toh(in_params.scan_window);
        le_scan_state_.own_address_type = in_params.own_address_type;
        le_scan_state_.filter_policy = in_params.filter_policy;
      }

      RespondWithCommandComplete(opcode,
                                 BufferView(&out_params, sizeof(out_params)));
      break;
    }
    case hci::kLESetScanEnable: {
      const auto& in_params =
          command_packet.payload<hci::LESetScanEnableCommandParams>();

      le_scan_state_.enabled =
          (in_params.scanning_enabled == hci::GenericEnableParam::kEnable);
      le_scan_state_.filter_duplicates =
          (in_params.filter_duplicates == hci::GenericEnableParam::kEnable);

      // Post the scan state update before scheduling the HCI Command Complete
      // event. This guarantees that single-threaded unit tests receive the scan
      // state update BEFORE the HCI command sequence terminates.
      if (scan_state_cb_) {
        FXL_DCHECK(scan_state_cb_dispatcher_);
        async::PostTask(scan_state_cb_dispatcher_, [
          cb = scan_state_cb_.share(), enabled = le_scan_state_.enabled
        ] { cb(enabled); });
      }

      RespondWithSuccess(opcode);

      if (le_scan_state_.enabled)
        SendAdvertisingReports();
      break;
    }

    case hci::kInquiry: {
      const auto& in_params =
          command_packet.payload<hci::InquiryCommandParams>();

      if (in_params.lap != hci::kGIAC && in_params.lap != hci::kLIAC) {
        RespondWithCommandStatus(opcode, hci::kInvalidHCICommandParameters);
        break;
      }

      if (in_params.inquiry_length == 0x00 ||
          in_params.inquiry_length > hci::kInquiryLengthMax) {
        RespondWithCommandStatus(opcode, hci::kInvalidHCICommandParameters);
        break;
      }

      inquiry_num_responses_left_ = in_params.num_responses;
      if (in_params.num_responses == 0) {
        inquiry_num_responses_left_ = -1;
      }

      RespondWithCommandStatus(opcode, hci::kSuccess);

      FXL_LOG(INFO) << "FakeController: sending inquiry responses..";
      SendInquiryResponses();

      // TODO(jamuraa): do this after an appropriate amount of time?
      hci::InquiryCompleteEventParams params;
      params.status = hci::kSuccess;
      SendEvent(hci::kInquiryCompleteEventCode,
                common::BufferView(&params, sizeof(params)));
      break;
    }
    case hci::kReset: {
      // TODO(jamuraa): actually do some resetting of stuff here
      RespondWithSuccess(opcode);
      break;
    }
    case hci::kWriteLEHostSupport: {
      const auto& in_params =
          command_packet.payload<hci::WriteLEHostSupportCommandParams>();

      if (in_params.le_supported_host == hci::GenericEnableParam::kEnable) {
        SetBit(&settings_.lmp_features_page1,
               hci::LMPFeature::kLESupportedHost);
      } else {
        UnsetBit(&settings_.lmp_features_page1,
                 hci::LMPFeature::kLESupportedHost);
      }
      RespondWithSuccess(opcode);
      break;
    }
    default: {
      hci::SimpleReturnParams params;
      params.status = hci::StatusCode::kUnknownCommand;
      RespondWithCommandComplete(opcode, BufferView(&params, sizeof(params)));
      break;
    }
  }
}

void FakeController::OnACLDataPacketReceived(
    const ByteBuffer& acl_data_packet) {
  if (acl_data_packet.size() < sizeof(hci::ACLDataHeader)) {
    FXL_LOG(WARNING) << "bt-hci (fake): Malformed ACL packet!";
    return;
  }

  const auto& header = acl_data_packet.As<hci::ACLDataHeader>();
  hci::ConnectionHandle handle = le16toh(header.handle_and_flags) & 0x0FFFF;
  FakeDevice* dev = FindDeviceByConnHandle(handle);
  if (!dev) {
    FXL_LOG(WARNING) << "bt-hci (fake): ACL data received for unknown handle!";
    return;
  }

  SendNumberOfCompletedPacketsEvent(handle, 1);
  dev->OnRxL2CAP(handle, acl_data_packet.view(sizeof(hci::ACLDataHeader)));
}

}  // namespace testing
}  // namespace btlib
