// Copyright 2022 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 "bt_hci_broadcom.h"

#include <fidl/fuchsia.hardware.bluetooth/cpp/wire.h>
#include <lib/async/cpp/task.h>
#include <lib/async/cpp/wait.h>
#include <lib/async_patterns/testing/cpp/dispatcher_bound.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/ddk/metadata.h>
#include <lib/ddk/platform-defs.h>
#include <lib/driver/compat/cpp/device_server.h>
#include <lib/driver/outgoing/cpp/outgoing_directory.h>
#include <lib/driver/testing/cpp/fixtures/gtest_fixture.h>
#include <lib/sync/cpp/completion.h>

#include "src/storage/lib/vfs/cpp/pseudo_dir.h"
#include "src/storage/lib/vfs/cpp/synchronous_vfs.h"
#include "src/storage/lib/vfs/cpp/vmo_file.h"

namespace bt_hci_broadcom {

namespace {

// Firmware binaries are a sequence of HCI commands containing the firmware as payloads. For
// testing, we use 1 HCI command with a 1 byte payload.
const std::vector<uint8_t> kFirmware = {
    0x01, 0x02,  // arbitrary "firmware opcode"
    0x01,        // parameter_total_size
    0x03         // payload
};
const char* kFirmwarePath = "BCM4345C5.hcd";

const std::vector<uint8_t> kMacAddress = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};

const std::array<uint8_t, 6> kCommandCompleteEvent = {
    0x0e,        // command complete event code
    0x04,        // parameter_total_size
    0x01,        // num_hci_command_packets
    0x00, 0x00,  // command opcode (hardcoded for simplicity since this isn't checked by the driver)
    0x00,        // return_code (success)
};

class FakeTransportDevice : public fidl::WireServer<fuchsia_hardware_bluetooth::Hci>,
                            public fdf::WireServer<fuchsia_hardware_serialimpl::Device> {
 public:
  explicit FakeTransportDevice() = default;

  fuchsia_hardware_serialimpl::Service::InstanceHandler GetSerialInstanceHandler() {
    return fuchsia_hardware_serialimpl::Service::InstanceHandler({
        .device = serial_binding_group_.CreateHandler(this, fdf::Dispatcher::GetCurrent()->get(),
                                                      fidl::kIgnoreBindingClosure),
    });
  }
  fuchsia_hardware_bluetooth::HciService::InstanceHandler GetHciInstanceHandler() {
    return fuchsia_hardware_bluetooth::HciService::InstanceHandler({
        .hci = hci_binding_group_.CreateHandler(
            this, fdf::Dispatcher::GetCurrent()->async_dispatcher(), fidl::kIgnoreBindingClosure),
    });
  }

  // Set a custom handler for commands. If null, command complete events will be automatically sent.
  void SetCommandHandler(fit::function<void(std::vector<uint8_t>)> command_callback) {
    command_callback_ = std::move(command_callback);
  }

  zx::channel& command_chan() { return command_channel_; }

  // fucshia_hardware_bluetooth::Hci request handler implementations:
  void OpenCommandChannel(OpenCommandChannelRequestView request,
                          OpenCommandChannelCompleter::Sync& completer) override {
    command_channel_ = std::move(request->channel);
    cmd_chan_wait_.set_object(command_channel_.get());
    cmd_chan_wait_.set_trigger(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED);
    cmd_chan_wait_.Begin(fdf::Dispatcher::GetCurrent()->async_dispatcher());
    completer.ReplySuccess();
  }
  void OpenAclDataChannel(OpenAclDataChannelRequestView request,
                          OpenAclDataChannelCompleter::Sync& completer) override {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }
  void OpenScoDataChannel(OpenScoDataChannelRequestView request,
                          OpenScoDataChannelCompleter::Sync& completer) override {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }
  void ConfigureSco(ConfigureScoRequestView request,
                    ConfigureScoCompleter::Sync& completer) override {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }
  void ResetSco(ResetScoCompleter::Sync& completer) override {}
  void OpenIsoDataChannel(OpenIsoDataChannelRequestView request,
                          OpenIsoDataChannelCompleter::Sync& completer) override {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }
  void OpenSnoopChannel(OpenSnoopChannelRequestView request,
                        OpenSnoopChannelCompleter::Sync& completer) override {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
  }

  void handle_unknown_method(fidl::UnknownMethodMetadata<fuchsia_hardware_bluetooth::Hci> metadata,
                             fidl::UnknownMethodCompleter::Sync& completer) override {
    ZX_PANIC("Unknown method in HCI requests");
  }

  // fuchsia_hardware_serialimpl::Device FIDL request handler implementation.
  void GetInfo(fdf::Arena& arena, GetInfoCompleter::Sync& completer) override {
    fuchsia_hardware_serial::wire::SerialPortInfo info = {
        .serial_class = fuchsia_hardware_serial::Class::kBluetoothHci,
        .serial_pid = PDEV_PID_BCM43458,
    };

    completer.buffer(arena).ReplySuccess(info);
  }
  void Config(ConfigRequestView request, fdf::Arena& arena,
              ConfigCompleter::Sync& completer) override {
    completer.buffer(arena).ReplySuccess();
  }
  void Enable(EnableRequestView request, fdf::Arena& arena,
              EnableCompleter::Sync& completer) override {
    completer.buffer(arena).ReplySuccess();
  }
  void Read(fdf::Arena& arena, ReadCompleter::Sync& completer) override {
    fidl::VectorView<uint8_t> data;
    completer.buffer(arena).ReplySuccess(data);
  }
  void Write(WriteRequestView request, fdf::Arena& arena,
             WriteCompleter::Sync& completer) override {
    completer.buffer(arena).ReplySuccess();
  }
  void CancelAll(fdf::Arena& arena, CancelAllCompleter::Sync& completer) override {}

  void handle_unknown_method(
      fidl::UnknownMethodMetadata<fuchsia_hardware_serialimpl::Device> metadata,
      fidl::UnknownMethodCompleter::Sync& completer) override {
    ZX_PANIC("Unknown method in Serial requests");
  }

 private:
  void OnCommandChannelSignal(async_dispatcher_t*, async::WaitBase* wait, zx_status_t status,
                              const zx_packet_signal_t* signal) {
    ASSERT_EQ(status, ZX_OK);
    if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
      command_channel_.reset();
      return;
    }
    ASSERT_TRUE(signal->observed & ZX_CHANNEL_READABLE);
    // Make buffer large enough to hold largest command packet.
    std::vector<uint8_t> bytes(
        sizeof(HciCommandHeader) +
        std::numeric_limits<decltype(HciCommandHeader::parameter_total_size)>::max());
    uint32_t actual_bytes = 0;
    zx_status_t read_status = command_channel_.read(
        /*flags=*/0, bytes.data(), /*handles=*/nullptr, static_cast<uint32_t>(bytes.size()),
        /*num_handles=*/0, &actual_bytes, /*actual_handles=*/nullptr);
    ASSERT_EQ(read_status, ZX_OK);
    bytes.resize(actual_bytes);

    cmd_chan_received_packets_.push_back(bytes);

    if (command_callback_) {
      command_callback_(std::move(bytes));
    } else {
      zx_status_t write_status = command_channel_.write(/*flags=*/0, kCommandCompleteEvent.data(),
                                                        kCommandCompleteEvent.size(),
                                                        /*handles=*/nullptr, /*num_handles=*/0);
      EXPECT_EQ(write_status, ZX_OK);
    }

    // The wait needs to be restarted.
    zx_status_t wait_begin_status = wait->Begin(fdf::Dispatcher::GetCurrent()->async_dispatcher());
    ASSERT_EQ(wait_begin_status, ZX_OK) << zx_status_get_string(wait_begin_status);
  }

  fit::function<void(std::vector<uint8_t>)> command_callback_;
  zx::channel command_channel_;
  std::vector<std::vector<uint8_t>> cmd_chan_received_packets_;
  async::WaitMethod<FakeTransportDevice, &FakeTransportDevice::OnCommandChannelSignal>
      cmd_chan_wait_{this};

  fdf::ServerBindingGroup<fuchsia_hardware_serialimpl::Device> serial_binding_group_;
  fidl::ServerBindingGroup<fuchsia_hardware_bluetooth::Hci> hci_binding_group_;
};

class TestEnvironment : fdf_testing::Environment {
 public:
  zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) override {
    auto dir_endpoints = fidl::Endpoints<fuchsia_io::Directory>::Create();
    firmware_server_.SetDispatcher(fdf::Dispatcher::GetCurrent()->async_dispatcher());
    // Serve our firmware directory (will start serving FIDL requests on dir_endpoints with
    // dispatcher on previous line)
    ZX_ASSERT(firmware_server_.ServeDirectory(firmware_dir_, std::move(dir_endpoints.server)) ==
              ZX_OK);
    // Attach the firmware directory endpoint to "pkg/lib"
    ZX_ASSERT(to_driver_vfs.component()
                  .AddDirectoryAt(std::move(dir_endpoints.client), "pkg/lib", "firmware")
                  .is_ok());

    // Add the services that the fake parent driver exposes to the incoming directory of the driver
    // under test.
    zx::result result = to_driver_vfs.AddService<fuchsia_hardware_serialimpl::Service>(
        transport_device_.GetSerialInstanceHandler());
    EXPECT_TRUE(result.is_ok());

    result = to_driver_vfs.AddService<fuchsia_hardware_bluetooth::HciService>(
        transport_device_.GetHciInstanceHandler());
    EXPECT_TRUE(result.is_ok());

    device_server_.Init(component::kDefaultInstance, "root");
    EXPECT_EQ(ZX_OK, device_server_.Serve(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                                          &to_driver_vfs));
    return zx::ok();
  }

  void AddFirmwareFile(const std::vector<uint8_t> firmware) {
    // Create vmo for firmware file.
    zx::vmo vmo;
    zx::vmo::create(4096, 0, &vmo);
    vmo.write(firmware.data(), 0, firmware.size());
    vmo.set_prop_content_size(firmware.size());

    //  Create firmware file, and add it to the "firmware" directory we added under pkg/lib.
    fbl::RefPtr<fs::VmoFile> firmware_file =
        fbl::MakeRefCounted<fs::VmoFile>(std::move(vmo), firmware.size());
    ZX_ASSERT(firmware_dir_->AddEntry(kFirmwarePath, firmware_file) == ZX_OK);
  }

  zx_status_t SetMetadata(uint32_t name, const std::vector<uint8_t> data, const size_t size) {
    // Serve metadata.
    return device_server_.AddMetadata(name, data.data(), size);
  }

  FakeTransportDevice transport_device_;

 private:
  compat::DeviceServer device_server_;
  fbl::RefPtr<fs::PseudoDir> firmware_dir_ = fbl::MakeRefCounted<fs::PseudoDir>();
  fs::SynchronousVfs firmware_server_;
};

class FixtureConfig final {
 public:
  static constexpr bool kDriverOnForeground = false;
  static constexpr bool kAutoStartDriver = false;
  static constexpr bool kAutoStopDriver = true;

  using DriverType = BtHciBroadcom;
  using EnvironmentType = TestEnvironment;
};

class BtHciBroadcomTest : public fdf_testing::DriverTestFixture<FixtureConfig> {
 public:
  BtHciBroadcomTest() = default;

 protected:
  void SetFirmware(const std::vector<uint8_t> firmware = kFirmware) {
    RunInEnvironmentTypeContext([&](TestEnvironment& env) { env.AddFirmwareFile(firmware); });
  }

  void SetMetadata(uint32_t name = DEVICE_METADATA_MAC_ADDRESS,
                   const std::vector<uint8_t> data = kMacAddress, const size_t size = kMacAddrLen) {
    ASSERT_EQ(ZX_OK, RunInEnvironmentTypeContext<zx_status_t>(
                         [&](TestEnvironment& env) { return env.SetMetadata(name, data, size); }));
  }

  void OpenVendor() {
    class EventHandler : public fidl::WireSyncEventHandler<fuchsia_hardware_bluetooth::Vendor> {
     public:
      void OnFeatures(
          fidl::WireEvent<fuchsia_hardware_bluetooth::Vendor::OnFeatures>* event) override {
        EXPECT_TRUE(event->acl_priority_command());
        on_vendor_connect_handled_ = true;
      }

      void handle_unknown_event(
          fidl::UnknownEventMetadata<fuchsia_hardware_bluetooth::Vendor> metadata) override {}

      bool on_vendor_connect_handled_ = false;
    };

    EventHandler event_handler;
    // Connect to Vendor protocol through devfs, get the channel handle from node server.
    zx::result connect_result =
        ConnectThroughDevfs<fuchsia_hardware_bluetooth::Vendor>("bt-hci-broadcom");
    ASSERT_EQ(ZX_OK, connect_result.status_value());

    // Bind the channel to a Vendor client end.
    vendor_client_.Bind(std::move(connect_result.value()));
    EXPECT_TRUE(vendor_client_.HandleOneEvent(event_handler).ok());
    EXPECT_TRUE(event_handler.on_vendor_connect_handled_);
  }

  void OpenVendorWithHciClient() {
    // Connect to Vendor protocol through devfs, get the channel handle from node server.
    zx::result connect_result =
        ConnectThroughDevfs<fuchsia_hardware_bluetooth::Vendor>("bt-hci-broadcom");
    ASSERT_EQ(ZX_OK, connect_result.status_value());

    fidl::ClientEnd<fuchsia_hardware_bluetooth::Hci> hci_end(connect_result.value().TakeChannel());
    hci_client_.Bind(std::move(hci_end));
  }

  void OpenHci() {
    // Connect to Hci through vendor protocol
    auto open_hci_result = vendor_client_->OpenHci();
    EXPECT_TRUE(open_hci_result.ok());
    EXPECT_FALSE(open_hci_result->is_error());

    hci_client_.Bind(std::move(open_hci_result->value()->channel));
  }

  fidl::WireSyncClient<fuchsia_hardware_bluetooth::Vendor> vendor_client_;
  fidl::WireSyncClient<fuchsia_hardware_bluetooth::Hci> hci_client_;
};

class BtHciBroadcomInitializedTest : public BtHciBroadcomTest {
 public:
  void SetUp() override {
    BtHciBroadcomTest::SetUp();
    SetFirmware();
    SetMetadata();
    ASSERT_TRUE(StartDriver().is_ok());
    OpenVendor();
  }
};

TEST_F(BtHciBroadcomInitializedTest, Lifecycle) {}

TEST_F(BtHciBroadcomTest, ReportLoadFirmwareError) {
  // Ensure reading metadata succeeds.
  SetMetadata();

  // No firmware has been set, so load_firmware() should fail during initialization.
  ASSERT_EQ(StartDriver().status_value(), ZX_ERR_NOT_FOUND);
}

TEST_F(BtHciBroadcomTest, TooSmallFirmwareBuffer) {
  // Ensure reading metadata succeeds.
  SetMetadata();

  SetFirmware(std::vector<uint8_t>{0x00});
  ASSERT_EQ(StartDriver().status_value(), ZX_ERR_INTERNAL);
}

TEST_F(BtHciBroadcomTest, ControllerReturnsEventSmallerThanEventHeader) {
  RunInEnvironmentTypeContext([](TestEnvironment& env) {
    env.transport_device_.SetCommandHandler([&](const std::vector<uint8_t>& command) {
      zx_status_t write_status =
          env.transport_device_.command_chan().write(/*flags=*/0, kCommandCompleteEvent.data(),
                                                     /*num_bytes=*/1,
                                                     /*handles=*/nullptr, /*num_handles=*/0);
      EXPECT_EQ(write_status, ZX_OK);
    });
  });

  SetFirmware();
  SetMetadata();
  ASSERT_NE(StartDriver().status_value(), ZX_OK);
}

TEST_F(BtHciBroadcomTest, ControllerReturnsEventSmallerThanCommandComplete) {
  RunInEnvironmentTypeContext([](TestEnvironment& env) {
    env.transport_device_.SetCommandHandler([&](const std::vector<uint8_t>& command) {
      zx_status_t write_status =
          env.transport_device_.command_chan().write(/*flags=*/0, kCommandCompleteEvent.data(),
                                                     /*num_bytes=*/sizeof(HciEventHeader),
                                                     /*handles=*/nullptr, /*num_handles=*/0);
      EXPECT_EQ(write_status, ZX_OK);
    });
  });

  SetFirmware();
  SetMetadata();
  ASSERT_FALSE(StartDriver().is_ok());
}

TEST_F(BtHciBroadcomTest, ControllerReturnsBdaddrEventWithoutBdaddrParam) {
  // Set an invalid mac address in the metadata so that a ReadBdaddr command is sent to get
  // fallback address.
  SetMetadata(DEVICE_METADATA_MAC_ADDRESS, kMacAddress, kMacAddress.size() - 1);
  //  Respond to ReadBdaddr command with a command complete (which doesn't include the bdaddr).
  RunInEnvironmentTypeContext([](TestEnvironment& env) {
    env.transport_device_.SetCommandHandler([&](const std::vector<uint8_t>& command) {
      zx_status_t write_status =
          env.transport_device_.command_chan().write(/*flags=*/0, kCommandCompleteEvent.data(),
                                                     /*num_bytes=*/kCommandCompleteEvent.size(),
                                                     /*handles=*/nullptr, /*num_handles=*/0);
      EXPECT_EQ(write_status, ZX_OK);
    });
  });

  // Ensure loading the firmware succeeds.
  SetFirmware();

  // Initialization should still succeed (an error will be logged, but it's not fatal).
  ASSERT_TRUE(StartDriver().is_ok());
}

TEST_F(BtHciBroadcomTest, VendorProtocolUnknownMethod) {
  SetFirmware();
  SetMetadata();
  ASSERT_TRUE(StartDriver().is_ok());

  OpenVendorWithHciClient();

  auto result = hci_client_->ResetSco();

  ASSERT_EQ(result.status(), ZX_ERR_NOT_SUPPORTED);
}

TEST_F(BtHciBroadcomTest, HciProtocolUnknownMethod) {
  SetFirmware();
  SetMetadata();
  ASSERT_TRUE(StartDriver().is_ok());
  OpenVendor();

  // Connect to Hci through Vendor protocol
  auto open_hci_result = vendor_client_->OpenHci();
  EXPECT_TRUE(open_hci_result.ok());
  EXPECT_FALSE(open_hci_result->is_error());

  // Bind the channel to Vendor client end.
  fidl::ClientEnd<fuchsia_hardware_bluetooth::Vendor> vendor_client_end(
      open_hci_result->value()->channel.TakeChannel());
  fidl::WireSyncClient vendor_client(std::move(vendor_client_end));

  fidl::Arena arena;
  auto builder = fuchsia_hardware_bluetooth::wire::VendorSetAclPriorityParams::Builder(arena);
  builder.connection_handle(0);
  builder.priority(fuchsia_hardware_bluetooth::wire::VendorAclPriority::kNormal);
  builder.direction(fuchsia_hardware_bluetooth::wire::VendorAclDirection::kSource);

  auto command =
      fuchsia_hardware_bluetooth::wire::VendorCommand::WithSetAclPriority(arena, builder.Build());
  auto result = vendor_client->EncodeCommand(command);

  ASSERT_EQ(result.status(), ZX_ERR_NOT_SUPPORTED);
}

TEST_F(BtHciBroadcomInitializedTest, EncodeSetAclPrioritySuccessWithParametersHighSink) {
  std::array<uint8_t, kBcmSetAclPriorityCmdSize> result_buffer;
  fidl::Arena arena;
  auto builder = fuchsia_hardware_bluetooth::wire::VendorSetAclPriorityParams::Builder(arena);
  builder.connection_handle(0xFF00);
  builder.priority(fuchsia_hardware_bluetooth::wire::VendorAclPriority::kHigh);
  builder.direction(fuchsia_hardware_bluetooth::wire::VendorAclDirection::kSink);

  auto command =
      fuchsia_hardware_bluetooth::wire::VendorCommand::WithSetAclPriority(arena, builder.Build());
  auto result = vendor_client_->EncodeCommand(command);
  ASSERT_TRUE(result.ok());
  ASSERT_FALSE(result->is_error());

  std::copy(result->value()->encoded.begin(), result->value()->encoded.end(),
            result_buffer.begin());
  const std::array<uint8_t, kBcmSetAclPriorityCmdSize> kExpectedBuffer = {
      0x1A,
      0xFD,  // OpCode
      0x04,  // size
      0x00,
      0xFF,                  // handle
      kBcmAclPriorityHigh,   // priority
      kBcmAclDirectionSink,  // direction
  };
  EXPECT_EQ(result_buffer, kExpectedBuffer);
}

TEST_F(BtHciBroadcomInitializedTest, EncodeSetAclPrioritySuccessWithParametersNormalSource) {
  std::array<uint8_t, kBcmSetAclPriorityCmdSize> result_buffer;
  fidl::Arena arena;
  auto builder = fuchsia_hardware_bluetooth::wire::VendorSetAclPriorityParams::Builder(arena);
  builder.connection_handle(0xFF00);
  builder.priority(fuchsia_hardware_bluetooth::wire::VendorAclPriority::kNormal);
  builder.direction(fuchsia_hardware_bluetooth::wire::VendorAclDirection::kSource);

  auto command =
      fuchsia_hardware_bluetooth::wire::VendorCommand::WithSetAclPriority(arena, builder.Build());
  auto result = vendor_client_->EncodeCommand(command);
  ASSERT_TRUE(result.ok());
  ASSERT_FALSE(result->is_error());

  std::copy(result->value()->encoded.begin(), result->value()->encoded.end(),
            result_buffer.begin());
  const std::array<uint8_t, kBcmSetAclPriorityCmdSize> kExpectedBuffer = {
      0x1A,
      0xFD,  // OpCode
      0x04,  // size
      0x00,
      0xFF,                    // handle
      kBcmAclPriorityNormal,   // priority
      kBcmAclDirectionSource,  // direction
  };
  EXPECT_EQ(result_buffer, kExpectedBuffer);
}

}  // namespace

}  // namespace bt_hci_broadcom
