// 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/binding.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);
}
