// Copyright 2019 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 "hid.h"

#include <lib/fake_ddk/fake_ddk.h>
#include <unistd.h>

#include <thread>
#include <vector>

#include <ddktl/protocol/hidbus.h>
#include <hid/ambient-light.h>
#include <hid/boot.h>
#include <hid/paradise.h>
#include <zxtest/zxtest.h>

namespace hid_driver {

struct ProtocolDeviceOps {
  const zx_protocol_device_t* ops;
  void* ctx;
};

// Create our own Fake Ddk Bind class. We want to save the last device arguments that
// have been seen, so the test can get ahold of the instance device and test
// Reads and Writes on it.
class Binder : public fake_ddk::Bind {
 public:
  zx_status_t DeviceAdd(zx_driver_t* drv, zx_device_t* parent, device_add_args_t* args,
                        zx_device_t** out) override {
    zx_status_t status;

    if (args && args->ops) {
      if (args->ops->message) {
        if ((status = fidl_.SetMessageOp(args->ctx, args->ops->message)) < 0) {
          return status;
        }
      }
    }

    *out = fake_ddk::kFakeDevice;
    add_called_ = true;

    last_ops_.ctx = args->ctx;
    last_ops_.ops = args->ops;

    return ZX_OK;
  }

  ProtocolDeviceOps GetLastDeviceOps() { return last_ops_; }

 private:
  ProtocolDeviceOps last_ops_;
};

class FakeHidbus : public ddk::HidbusProtocol<FakeHidbus> {
 public:
  FakeHidbus() : proto_({&hidbus_protocol_ops_, this}) {}

  zx_status_t HidbusQuery(uint32_t options, hid_info_t* out_info) {
    *out_info = info_;
    return ZX_OK;
  }

  void SetHidInfo(hid_info_t info) { info_ = info; }

  void SetStartStatus(zx_status_t status) { start_status_ = status; }

  zx_status_t HidbusStart(const hidbus_ifc_protocol_t* ifc) {
    if (start_status_ != ZX_OK) {
      return start_status_;
    }
    ifc_ = *ifc;
    return ZX_OK;
  }

  void SendReport(const uint8_t* report_data, size_t report_size) {
    ASSERT_NE(ifc_.ops, nullptr);
    ifc_.ops->io_queue(ifc_.ctx, report_data, report_size, zx_clock_get_monotonic());
  }

  void SendReportWithTime(const uint8_t* report_data, size_t report_size, zx_time_t time) {
    ASSERT_NE(ifc_.ops, nullptr);
    ifc_.ops->io_queue(ifc_.ctx, report_data, report_size, time);
  }

  void HidbusStop() { ifc_.ops = nullptr; }

  zx_status_t HidbusGetDescriptor(hid_description_type_t desc_type, void* out_data_buffer,
                                  size_t data_size, size_t* out_data_actual) {
    if (data_size < report_desc_.size()) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    memcpy(out_data_buffer, report_desc_.data(), report_desc_.size());
    *out_data_actual = report_desc_.size();

    return ZX_OK;
  }

  void SetDescriptor(const uint8_t* desc, size_t desc_len) {
    report_desc_ = std::vector<uint8_t>(desc, desc + desc_len);
  }

  zx_status_t HidbusGetReport(hid_report_type_t rpt_type, uint8_t rpt_id, void* out_data_buffer,
                              size_t data_size, size_t* out_data_actual) {
    if (rpt_id != last_set_report_id_) {
      return ZX_ERR_INTERNAL;
    }
    if (data_size < last_set_report_.size()) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    memcpy(out_data_buffer, last_set_report_.data(), last_set_report_.size());
    *out_data_actual = last_set_report_.size();

    return ZX_OK;
  }

  zx_status_t HidbusSetReport(hid_report_type_t rpt_type, uint8_t rpt_id, const void* data_buffer,
                              size_t data_size) {
    last_set_report_id_ = rpt_id;
    auto data_bytes = reinterpret_cast<const uint8_t*>(data_buffer);
    last_set_report_ = std::vector<uint8_t>(data_bytes, data_bytes + data_size);

    return ZX_OK;
  }

  zx_status_t HidbusGetIdle(uint8_t rpt_id, uint8_t* out_duration) {
    *out_duration = 0;
    return ZX_OK;
  }

  zx_status_t HidbusSetIdle(uint8_t rpt_id, uint8_t duration) { return ZX_OK; }

  zx_status_t HidbusGetProtocol(hid_protocol_t* out_protocol) {
    *out_protocol = hid_protocol_;
    return ZX_OK;
  }

  zx_status_t HidbusSetProtocol(hid_protocol_t protocol) {
    hid_protocol_ = protocol;
    return ZX_OK;
  }

  hidbus_protocol_t* GetProto() { return &proto_; }

 protected:
  std::vector<uint8_t> report_desc_;

  std::vector<uint8_t> last_set_report_;
  uint8_t last_set_report_id_;

  hid_protocol_t hid_protocol_ = HID_PROTOCOL_REPORT;
  hidbus_protocol_t proto_ = {};
  hid_info_t info_ = {};
  hidbus_ifc_protocol_t ifc_;
  zx_status_t start_status_ = ZX_OK;
};

class HidDeviceTest : public zxtest::Test {
 public:
  void SetUp() override {
    client_ = ddk::HidbusProtocolClient(fake_hidbus_.GetProto());
    device_ = new HidDevice(fake_ddk::kFakeParent);

    // Each test is responsible for calling Bind().
  }

  void TearDown() override {
    TeardownInstanceDriver();
    device_->DdkAsyncRemove();
    EXPECT_TRUE(ddk_.Ok());

    // This should delete the object, which means this test should not leak.
    device_->DdkRelease();
  }

  void SetupBootMouseDevice() {
    size_t desc_size;
    const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&desc_size);
    fake_hidbus_.SetDescriptor(boot_mouse_desc, desc_size);

    hid_info_t info = {};
    info.device_class = HID_DEVICE_CLASS_POINTER;
    info.boot_device = true;
    fake_hidbus_.SetHidInfo(info);
  }

  void SetupInstanceDriver() {
    ASSERT_OK(device_->DdkOpen(&instance_driver_, 0));
    instance_ops_ = ddk_.GetLastDeviceOps();

    sync_client_ =
        llcpp::fuchsia::hardware::input::Device::SyncClient(std::move(ddk_.FidlClient()));

    auto result = sync_client_->GetReportsEvent();
    ASSERT_OK(result.status());
    ASSERT_OK(result->status);
    report_event_ = std::move(result->event);
  }

  void TeardownInstanceDriver() {
    if (instance_driver_ == nullptr) {
      return;
    }

    instance_ops_.ops->close(instance_ops_.ctx, 0);
    instance_ops_.ops->release(instance_ops_.ctx);
    instance_driver_ = nullptr;
  }

  zx_status_t ReadOneReport(uint8_t* report_data, size_t report_size, size_t* returned_size) {
    zx_status_t status = report_event_.wait_one(DEV_STATE_READABLE, zx::time::infinite(), nullptr);
    if (status != ZX_OK) {
      return status;
    }

    auto result = sync_client_->ReadReport();
    status = result.status();
    if (status != ZX_OK) {
      return status;
    }
    status = result->status;
    if (status != ZX_OK) {
      return status;
    }
    if (result->data.count() > report_size) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    for (size_t i = 0; i < result->data.count(); i++) {
      report_data[i] = result->data[i];
    }
    *returned_size = result->data.count();
    return ZX_OK;
  }

 protected:
  zx_device_t* instance_driver_ = nullptr;
  ProtocolDeviceOps instance_ops_;
  std::optional<llcpp::fuchsia::hardware::input::Device::SyncClient> sync_client_;
  zx::event report_event_;

  HidDevice* device_;
  Binder ddk_;
  FakeHidbus fake_hidbus_;
  ddk::HidbusProtocolClient client_;
};

TEST_F(HidDeviceTest, LifeTimeTest) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));
}

TEST_F(HidDeviceTest, TestQuery) {
  // Ids were chosen arbitrarily.
  constexpr uint16_t kVendorId = 0xacbd;
  constexpr uint16_t kProductId = 0xdcba;
  constexpr uint16_t kVersion = 0x1234;

  SetupBootMouseDevice();
  hid_info_t info = {};
  info.device_class = HID_DEVICE_CLASS_POINTER;
  info.boot_device = true;
  info.vendor_id = kVendorId;
  info.product_id = kProductId;
  info.version = kVersion;
  fake_hidbus_.SetHidInfo(info);

  ASSERT_OK(device_->Bind(client_));

  zx_device_t* open_dev;
  ASSERT_OK(device_->DdkOpen(&open_dev, 0));
  // Opening the device created an instance device to be created, and we can
  // get its arguments here.
  ProtocolDeviceOps dev_ops = ddk_.GetLastDeviceOps();

  auto sync_client =
      llcpp::fuchsia::hardware::input::Device::SyncClient(std::move(ddk_.FidlClient()));
  auto result = sync_client.GetDeviceIds();
  ASSERT_OK(result.status());
  llcpp::fuchsia::hardware::input::DeviceIds ids = result->ids;

  ASSERT_EQ(kVendorId, ids.vendor_id);
  ASSERT_EQ(kProductId, ids.product_id);
  ASSERT_EQ(kVersion, ids.version);

  // Close the instance device.
  dev_ops.ops->close(dev_ops.ctx, 0);
  dev_ops.ops->release(dev_ops.ctx);
}

TEST_F(HidDeviceTest, BootMouseSendReport) {
  SetupBootMouseDevice();
  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};
  ASSERT_OK(device_->Bind(client_));

  SetupInstanceDriver();

  fake_hidbus_.SendReport(mouse_report, sizeof(mouse_report));

  uint8_t returned_report[3] = {};
  size_t actual;
  ASSERT_OK(ReadOneReport(returned_report, sizeof(returned_report), &actual));

  ASSERT_EQ(actual, sizeof(returned_report));
  for (size_t i = 0; i < actual; i++) {
    ASSERT_EQ(returned_report[i], mouse_report[i]);
  }
}

TEST_F(HidDeviceTest, BootMouseSendReportWithTime) {
  SetupBootMouseDevice();
  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};
  ASSERT_OK(device_->Bind(client_));

  // Regsiter a device listener
  std::pair<sync_completion_t, zx_time_t> callback_data;
  callback_data.second = 0xabcd;

  hid_report_listener_protocol_ops_t listener_ops;
  listener_ops.receive_report = [](void* ctx, const uint8_t* report_list, size_t report_count,
                                   zx_time_t report_time) {
    auto callback_data = static_cast<std::pair<sync_completion_t, zx_time_t>*>(ctx);
    ASSERT_EQ(callback_data->second, report_time);
    sync_completion_signal(&callback_data->first);
  };
  hid_report_listener_protocol_t listener = {&listener_ops, &callback_data};
  device_->HidDeviceRegisterListener(&listener);

  fake_hidbus_.SendReportWithTime(mouse_report, sizeof(mouse_report), callback_data.second);
  sync_completion_wait_deadline(&callback_data.first, zx::time::infinite().get());
  ASSERT_NO_FATAL_FAILURES();
}

TEST_F(HidDeviceTest, BootMouseSendReportInPieces) {
  SetupBootMouseDevice();
  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};
  ASSERT_OK(device_->Bind(client_));

  SetupInstanceDriver();

  fake_hidbus_.SendReport(&mouse_report[0], sizeof(uint8_t));
  fake_hidbus_.SendReport(&mouse_report[1], sizeof(uint8_t));
  fake_hidbus_.SendReport(&mouse_report[2], sizeof(uint8_t));

  uint8_t returned_report[3] = {};
  size_t actual;
  ASSERT_OK(ReadOneReport(returned_report, sizeof(returned_report), &actual));

  ASSERT_EQ(actual, sizeof(returned_report));
  for (size_t i = 0; i < actual; i++) {
    ASSERT_EQ(returned_report[i], mouse_report[i]);
  }
}

TEST_F(HidDeviceTest, BootMouseSendMultipleReports) {
  SetupBootMouseDevice();
  uint8_t double_mouse_report[] = {0xDE, 0xAD, 0xBE, 0x12, 0x34, 0x56};
  ASSERT_OK(device_->Bind(client_));

  SetupInstanceDriver();

  fake_hidbus_.SendReport(double_mouse_report, sizeof(double_mouse_report));

  uint8_t returned_report[3] = {};
  size_t actual;

  // Read the first report.
  ASSERT_OK(ReadOneReport(returned_report, sizeof(returned_report), &actual));
  ASSERT_EQ(actual, sizeof(returned_report));
  for (size_t i = 0; i < actual; i++) {
    ASSERT_EQ(returned_report[i], double_mouse_report[i]);
  }

  // Read the second report.
  ASSERT_OK(ReadOneReport(returned_report, sizeof(returned_report), &actual));
  ASSERT_EQ(actual, sizeof(returned_report));
  for (size_t i = 0; i < actual; i++) {
    ASSERT_EQ(returned_report[i], double_mouse_report[i + 3]);
  }
}

TEST(HidDeviceTest, FailToRegister) {
  FakeHidbus fake_hidbus;
  HidDevice device(fake_ddk::kFakeParent);

  fake_hidbus.SetStartStatus(ZX_ERR_INTERNAL);
  auto client = ddk::HidbusProtocolClient(fake_hidbus.GetProto());
  ASSERT_EQ(device.Bind(client), ZX_ERR_INTERNAL);
}

TEST_F(HidDeviceTest, ReadReportSingleReport) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};

  SetupInstanceDriver();

  // Send the reports.
  zx_time_t time = 0xabcd;
  fake_hidbus_.SendReportWithTime(mouse_report, sizeof(mouse_report), time);

  auto result = sync_client_->ReadReport();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(time, result->time);
  ASSERT_EQ(sizeof(mouse_report), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(mouse_report[i], result->data[i]);
  }

  result = sync_client_->ReadReport();
  ASSERT_OK(result.status());
  ASSERT_EQ(result->status, ZX_ERR_SHOULD_WAIT);
}

TEST_F(HidDeviceTest, ReadReportDoubleReport) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  uint8_t double_mouse_report[] = {0xDE, 0xAD, 0xBE, 0x12, 0x34, 0x56};

  SetupInstanceDriver();

  // Send the reports.
  zx_time_t time = 0xabcd;
  fake_hidbus_.SendReportWithTime(double_mouse_report, sizeof(double_mouse_report), time);

  auto result = sync_client_->ReadReport();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(time, result->time);
  ASSERT_EQ(sizeof(hid_boot_mouse_report_t), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(double_mouse_report[i], result->data[i]);
  }

  result = sync_client_->ReadReport();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(time, result->time);
  ASSERT_EQ(sizeof(hid_boot_mouse_report_t), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(double_mouse_report[i + sizeof(hid_boot_mouse_report_t)], result->data[i]);
  }

  result = sync_client_->ReadReport();
  ASSERT_OK(result.status());
  ASSERT_EQ(result->status, ZX_ERR_SHOULD_WAIT);
}

TEST_F(HidDeviceTest, ReadReportsSingleReport) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};

  SetupInstanceDriver();

  // Send the reports.
  fake_hidbus_.SendReport(mouse_report, sizeof(mouse_report));

  auto sync_client =
      llcpp::fuchsia::hardware::input::Device::SyncClient(std::move(ddk_.FidlClient()));
  auto result = sync_client_->ReadReports();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(sizeof(mouse_report), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(mouse_report[i], result->data[i]);
  }
}

TEST_F(HidDeviceTest, ReadReportsDoubleReport) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  uint8_t double_mouse_report[] = {0xDE, 0xAD, 0xBE, 0x12, 0x34, 0x56};

  SetupInstanceDriver();

  // Send the reports.
  fake_hidbus_.SendReport(double_mouse_report, sizeof(double_mouse_report));

  auto result = sync_client_->ReadReports();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(sizeof(double_mouse_report), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(double_mouse_report[i], result->data[i]);
  }
}

TEST_F(HidDeviceTest, ReadReportsBlockingWait) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  SetupInstanceDriver();

  // Send the reports, but delayed.
  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};
  std::thread report_thread([&]() {
    sleep(1);
    fake_hidbus_.SendReport(mouse_report, sizeof(mouse_report));
  });

  ASSERT_OK(report_event_.wait_one(DEV_STATE_READABLE, zx::time::infinite(), nullptr));

  // Get the report.
  auto result = sync_client_->ReadReports();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(sizeof(mouse_report), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(mouse_report[i], result->data[i]);
  }

  report_thread.join();
}

// Test that only whole reports get sent through.
TEST_F(HidDeviceTest, ReadReportsOneAndAHalfReports) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(client_));

  SetupInstanceDriver();

  // Send the report.
  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};
  fake_hidbus_.SendReport(mouse_report, sizeof(mouse_report));

  // Send a half of a report.
  uint8_t half_report[] = {0xDE, 0xAD};
  fake_hidbus_.SendReport(half_report, sizeof(half_report));

  auto result = sync_client_->ReadReports();
  ASSERT_OK(result.status());
  ASSERT_OK(result->status);
  ASSERT_EQ(sizeof(mouse_report), result->data.count());
  for (size_t i = 0; i < result->data.count(); i++) {
    EXPECT_EQ(mouse_report[i], result->data[i]);
  }
}

// This tests that we can set the boot mode for a non-boot device, and that the device will
// have it's report descriptor set to the boot mode descriptor. For this, we will take an
// arbitrary descriptor and claim that it can be set to a boot-mode keyboard. We then
// test that the report descriptor we get back is for the boot keyboard.
// (The descriptor doesn't matter, as long as a device claims its a boot device it should
//  support this transformation in hardware).
TEST_F(HidDeviceTest, SettingBootModeMouse) {
  size_t desc_size;
  const uint8_t* desc = get_paradise_touchpad_v1_report_desc(&desc_size);
  fake_hidbus_.SetDescriptor(desc, desc_size);

  hid_info_t info = {};
  info.device_class = HID_DEVICE_CLASS_POINTER;
  info.boot_device = true;
  fake_hidbus_.SetHidInfo(info);

  // Set the device to boot protocol.
  fake_hidbus_.HidbusSetProtocol(HID_PROTOCOL_BOOT);

  ASSERT_OK(device_->Bind(client_));

  size_t boot_mouse_desc_size;
  const uint8_t* boot_mouse_desc = get_boot_mouse_report_desc(&boot_mouse_desc_size);
  ASSERT_EQ(boot_mouse_desc_size, device_->GetReportDescLen());
  const uint8_t* received_desc = device_->GetReportDesc();
  for (size_t i = 0; i < boot_mouse_desc_size; i++) {
    ASSERT_EQ(boot_mouse_desc[i], received_desc[i]);
  }
}

// This tests that we can set the boot mode for a non-boot device, and that the device will
// have it's report descriptor set to the boot mode descriptor. For this, we will take an
// arbitrary descriptor and claim that it can be set to a boot-mode keyboard. We then
// test that the report descriptor we get back is for the boot keyboard.
// (The descriptor doesn't matter, as long as a device claims its a boot device it should
//  support this transformation in hardware).
TEST_F(HidDeviceTest, SettingBootModeKbd) {
  size_t desc_size;
  const uint8_t* desc = get_paradise_touchpad_v1_report_desc(&desc_size);
  fake_hidbus_.SetDescriptor(desc, desc_size);

  hid_info_t info = {};
  info.device_class = HID_DEVICE_CLASS_KBD;
  info.boot_device = true;
  fake_hidbus_.SetHidInfo(info);

  // Set the device to boot protocol.
  fake_hidbus_.HidbusSetProtocol(HID_PROTOCOL_BOOT);

  ASSERT_OK(device_->Bind(client_));

  size_t boot_kbd_desc_size;
  const uint8_t* boot_kbd_desc = get_boot_kbd_report_desc(&boot_kbd_desc_size);
  ASSERT_EQ(boot_kbd_desc_size, device_->GetReportDescLen());
  const uint8_t* received_desc = device_->GetReportDesc();
  for (size_t i = 0; i < boot_kbd_desc_size; i++) {
    ASSERT_EQ(boot_kbd_desc[i], received_desc[i]);
  }
}

TEST_F(HidDeviceTest, BanjoGetDescriptor) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(fake_hidbus_.GetProto()));

  size_t known_size;
  const uint8_t* known_descriptor = get_boot_mouse_report_desc(&known_size);

  uint8_t report_descriptor[HID_MAX_DESC_LEN];
  size_t actual;
  ASSERT_OK(device_->HidDeviceGetDescriptor(report_descriptor, sizeof(report_descriptor), &actual));

  ASSERT_EQ(known_size, actual);
  ASSERT_BYTES_EQ(known_descriptor, report_descriptor, known_size);
}

TEST_F(HidDeviceTest, BanjoRegisterListenerSendReport) {
  SetupBootMouseDevice();
  ASSERT_OK(device_->Bind(fake_hidbus_.GetProto()));

  uint8_t mouse_report[] = {0xDE, 0xAD, 0xBE};

  struct ReportCtx {
    sync_completion_t* completion;
    uint8_t* known_report;
  };

  sync_completion_t seen_report;
  ReportCtx ctx;
  ctx.completion = &seen_report;
  ctx.known_report = mouse_report;

  hid_report_listener_protocol_ops_t ops;
  ops.receive_report = [](void* ctx, const uint8_t* report_list, size_t report_count,
                          zx_time_t time) {
    ASSERT_EQ(sizeof(mouse_report), report_count);
    auto report_ctx = reinterpret_cast<ReportCtx*>(ctx);
    ASSERT_BYTES_EQ(report_ctx->known_report, report_list, report_count);
    sync_completion_signal(report_ctx->completion);
  };

  hid_report_listener_protocol_t listener;
  listener.ctx = &ctx;
  listener.ops = &ops;

  ASSERT_OK(device_->HidDeviceRegisterListener(&listener));

  fake_hidbus_.SendReport(mouse_report, sizeof(mouse_report));

  ASSERT_OK(sync_completion_wait(&seen_report, zx::time::infinite().get()));
  device_->HidDeviceUnregisterListener();
}

TEST_F(HidDeviceTest, BanjoGetSetReport) {
  const uint8_t* desc;
  size_t desc_size = get_ambient_light_report_desc(&desc);
  fake_hidbus_.SetDescriptor(desc, desc_size);

  hid_info_t info = {};
  info.device_class = HID_DEVICE_CLASS_OTHER;
  info.boot_device = false;
  fake_hidbus_.SetHidInfo(info);

  ASSERT_OK(device_->Bind(fake_hidbus_.GetProto()));

  ambient_light_feature_rpt_t feature_report = {};
  feature_report.rpt_id = AMBIENT_LIGHT_RPT_ID_FEATURE;
  // Below value are chosen arbitrarily.
  feature_report.state = 100;
  feature_report.interval_ms = 50;
  feature_report.threshold_high = 40;
  feature_report.threshold_low = 10;

  ASSERT_OK(device_->HidDeviceSetReport(HID_REPORT_TYPE_FEATURE, AMBIENT_LIGHT_RPT_ID_FEATURE,
                                        reinterpret_cast<uint8_t*>(&feature_report),
                                        sizeof(feature_report)));

  ambient_light_feature_rpt_t received_report = {};
  size_t actual;
  ASSERT_OK(device_->HidDeviceGetReport(HID_REPORT_TYPE_FEATURE, AMBIENT_LIGHT_RPT_ID_FEATURE,
                                        reinterpret_cast<uint8_t*>(&received_report),
                                        sizeof(received_report), &actual));

  ASSERT_EQ(sizeof(received_report), actual);
  ASSERT_BYTES_EQ(&feature_report, &received_report, actual);
}

// Tests that a device with too large reports don't cause buffer overruns.
TEST_F(HidDeviceTest, GetReportBufferOverrun) {
  const uint8_t desc[] = {
      0x05, 0x01,                    // Usage Page (Generic Desktop Ctrls)
      0x09, 0x02,                    // Usage (Mouse)
      0xA1, 0x01,                    // Collection (Application)
      0x05, 0x09,                    //   Usage Page (Button)
      0x09, 0x30,                    //   Usage (0x30)
      0x97, 0x00, 0xF0, 0x00, 0x00,  //   Report Count (65279)
      0x75, 0x08,                    //   Report Size (8)
      0x25, 0x01,                    //   Logical Maximum (1)
      0x81, 0x02,  //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
      0xC0,        // End Collection

      // 22 bytes
  };
  size_t desc_size = sizeof(desc);
  fake_hidbus_.SetDescriptor(desc, desc_size);

  hid_info_t info = {};
  info.device_class = HID_DEVICE_CLASS_OTHER;
  info.boot_device = false;
  fake_hidbus_.SetHidInfo(info);

  ASSERT_OK(device_->Bind(fake_hidbus_.GetProto()));

  std::vector<uint8_t> report(0xFF0000);
  size_t actual;
  ASSERT_EQ(
      device_->HidDeviceGetReport(HID_REPORT_TYPE_INPUT, 0, report.data(), report.size(), &actual),
      ZX_ERR_INTERNAL);
}

}  // namespace hid_driver
