// Copyright 2020 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 "src/devices/usb/drivers/usb-peripheral/usb-peripheral.h"

#include <fuchsia/hardware/usb/dci/c/banjo.h>
#include <fuchsia/hardware/usb/dci/cpp/banjo.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <lib/ddk/metadata.h>
#include <lib/zx/clock.h>
#include <lib/zx/interrupt.h>
#include <zircon/errors.h>
#include <zircon/syscalls.h>

#include <cstring>
#include <memory>

#include <usb/usb.h>
#include <zxtest/zxtest.h>

#include "src/devices/testing/mock-ddk/mock-device.h"
#include "src/devices/usb/drivers/usb-peripheral/usb-function.h"

class FakeDevice : public ddk::UsbDciProtocol<FakeDevice, ddk::base_protocol> {
 public:
  FakeDevice() : proto_({&usb_dci_protocol_ops_, this}) {}

  // USB DCI protocol implementation.
  void UsbDciRequestQueue(usb_request_t* req, const usb_request_complete_callback_t* cb) {}

  zx_status_t UsbDciSetInterface(const usb_dci_interface_protocol_t* interface) {
    interface_ = *interface;
    sync_completion_signal(&set_interface_called_);
    return ZX_OK;
  }

  zx_status_t UsbDciConfigEp(const usb_endpoint_descriptor_t* ep_desc,
                             const usb_ss_ep_comp_descriptor_t* ss_comp_desc) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  zx_status_t UsbDciDisableEp(uint8_t ep_address) { return ZX_ERR_NOT_SUPPORTED; }
  zx_status_t UsbDciEpSetStall(uint8_t ep_address) { return ZX_ERR_NOT_SUPPORTED; }
  zx_status_t UsbDciEpClearStall(uint8_t ep_address) { return ZX_ERR_NOT_SUPPORTED; }
  size_t UsbDciGetRequestSize() { return sizeof(usb_request_t); }

  zx_status_t UsbDciCancelAll(uint8_t ep_address) { return ZX_OK; }

  usb_dci_protocol_t* proto() { return &proto_; }

  usb_dci_interface_protocol_t* interface() {
    sync_completion_wait(&set_interface_called_, ZX_TIME_INFINITE);
    return &interface_;
  }

 private:
  sync_completion_t set_interface_called_;

  usb_dci_interface_protocol_t interface_;
  usb_dci_protocol_t proto_;
};

class UsbPeripheralHarness : public zxtest::Test {
 public:
  void SetUp() override {
    root_device_ = MockDevice::FakeRootParent();
    dci_ = std::make_unique<FakeDevice>();
    root_device_->SetMetadata(DEVICE_METADATA_SERIAL_NUMBER, &kSerialNumber, sizeof(kSerialNumber));
    root_device_->AddProtocol(ZX_PROTOCOL_USB_DCI, dci_->proto()->ops, dci_->proto()->ctx);
    auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
    ASSERT_OK(endpoints);
    root_device_->AddFidlService(fuchsia_hardware_usb_dci::UsbDciService::Name,
                                 std::move(endpoints->client));

    usb_peripheral_config::Config fake_config;
    fake_config.functions() = {};
    root_device_->SetConfigVmo(fake_config.ToVmo());

    ASSERT_OK(usb_peripheral::UsbPeripheral::Create(nullptr, root_device_.get()));
    ASSERT_EQ(1, root_device_->child_count());
    mock_dev_ = root_device_->GetLatestChild();
    client_ = ddk::UsbDciInterfaceProtocolClient(dci_->interface());
  }

  void TearDown() override {
    mock_dev_->UnbindOp();
    mock_dev_->WaitUntilUnbindReplyCalled();
  }

 protected:
  std::unique_ptr<FakeDevice> dci_;
  std::shared_ptr<MockDevice> root_device_;
  MockDevice* mock_dev_;
  ddk::UsbDciInterfaceProtocolClient client_;

  static constexpr char kSerialNumber[] = "Test serial number";
};

TEST_F(UsbPeripheralHarness, AddsCorrectSerialNumberMetadata) {
  char serial[256];
  usb_setup_t setup;
  setup.w_length = sizeof(serial);
  setup.w_value = 0x3 | (USB_DT_STRING << 8);
  setup.bm_request_type = USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_STANDARD;
  setup.b_request = USB_REQ_GET_DESCRIPTOR;
  size_t actual;
  ASSERT_OK(client_.Control(&setup, nullptr, 0, reinterpret_cast<uint8_t*>(&serial), sizeof(serial),
                            &actual));
  ASSERT_EQ(serial[0], sizeof(kSerialNumber) * 2);
  ASSERT_EQ(serial[1], USB_DT_STRING);
  for (size_t i = 0; i < sizeof(kSerialNumber) - 1; i++) {
    ASSERT_EQ(serial[2 + (i * 2)], kSerialNumber[i]);
  }
}

TEST_F(UsbPeripheralHarness, WorksWithVendorSpecificCommandWhenConfigurationIsZero) {
  char serial[256];
  usb_setup_t setup;
  setup.w_length = sizeof(serial);
  setup.w_value = 0x3 | (USB_DT_STRING << 8);
  setup.bm_request_type = USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR;
  setup.b_request = USB_REQ_GET_DESCRIPTOR;
  size_t actual;
  ASSERT_EQ(client_.Control(&setup, nullptr, 0, reinterpret_cast<uint8_t*>(&serial), sizeof(serial),
                            &actual),
            ZX_ERR_BAD_STATE);
}
