// 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 "usb-virtual-bus.h"

#include <fcntl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/devmgr-integration-test/fixture.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/watcher.h>
#include <lib/fidl-async/cpp/bind.h>
#include <sys/stat.h>
#include <unistd.h>
#include <zircon/device/vfs.h>
#include <zircon/hw/usb.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <gtest/gtest.h>

namespace usb_virtual_bus {

USBVirtualBusBase::USBVirtualBusBase(std::string pkg_url, std::string svc_name) {
  // create a IsolatedDevmgr through test component
  auto ctx = sys::ComponentContext::Create();
  fidl::InterfacePtr<fuchsia::sys::Launcher> launcher;
  ctx->svc()->Connect(launcher.NewRequest());

  zx::channel req;
  services_ = sys::ServiceDirectory::CreateWithRequest(&req);

  fuchsia::sys::LaunchInfo info;
  info.directory_request = std::move(req);
  info.url = pkg_url;
  launcher->CreateComponent(std::move(info), ctlr_.NewRequest());
  ctlr_.set_error_handler([](zx_status_t err) { FAIL() << "Controller shouldn't exit"; });

  zx::channel devfs_server_end, devfs_client_end;
  zx::channel::create(0, &devfs_server_end, &devfs_client_end);
  services_->Connect(svc_name, std::move(devfs_server_end));
  int fd_devfs;
  fdio_fd_create(devfs_client_end.release(), &fd_devfs);
  devfs_.reset(fd_devfs);
}

void USBVirtualBusBase::InitPeripheral() {
  fbl::unique_fd fd;
  devmgr_integration_test::RecursiveWaitForFile(devfs_root(),
                                                "sys/platform/11:03:0/usb-virtual-bus", &fd);
  ASSERT_EQ(fd.is_valid(), true);
  zx::channel virtual_bus;
  ASSERT_EQ(fdio_get_service_handle(fd.release(), virtual_bus.reset_and_get_address()), ZX_OK);
  virtual_bus_.emplace(std::move(virtual_bus));

  auto enable_result = virtual_bus_->Enable();
  ASSERT_EQ(enable_result.status(), ZX_OK);
  ASSERT_EQ(enable_result.value().status, ZX_OK);

  char peripheral_str[] = "usb-peripheral";
  fd.reset(openat(devfs_root().get(), "class", O_RDONLY));
  while (fdio_watch_directory(fd.get(), usb_virtual_bus_helper::WaitForFile, ZX_TIME_INFINITE,
                              &peripheral_str) != ZX_ERR_STOP)
    continue;

  fd.reset(openat(devfs_root().get(), "class/usb-peripheral", O_RDONLY));
  fbl::String devpath;
  while (fdio_watch_directory(fd.get(), usb_virtual_bus_helper::WaitForAnyFile, ZX_TIME_INFINITE,
                              &devpath) != ZX_ERR_STOP)
    continue;

  devpath = fbl::String::Concat({fbl::String("class/usb-peripheral/"), fbl::String(devpath)});
  fd.reset(openat(devfs_root().get(), devpath.c_str(), O_RDWR));

  zx::channel peripheral;
  ASSERT_EQ(fdio_get_service_handle(fd.release(), peripheral.reset_and_get_address()), ZX_OK);
  peripheral_.emplace(std::move(peripheral));

  auto clear_result = peripheral_->ClearFunctions();
  ASSERT_EQ(clear_result.status(), ZX_OK);
  ASSERT_EQ(clear_result.value().result.is_err(), false);
}

int USBVirtualBusBase::GetRootFd() { return devfs_root().get(); }

class EventWatcher : public ::llcpp::fuchsia::hardware::usb::peripheral::Events::Interface {
 public:
  explicit EventWatcher(async::Loop* loop, zx::channel svc, size_t functions)
      : loop_(loop), functions_(functions) {
    fidl::Bind(loop->dispatcher(), std::move(svc), this);
  }

  void FunctionRegistered(FunctionRegisteredCompleter::Sync completer);

  bool all_functions_registered() { return functions_registered_ == functions_; }

 private:
  async::Loop* loop_;
  const size_t functions_;
  size_t functions_registered_ = 0;

  bool state_changed_ = false;
};

void EventWatcher::FunctionRegistered(FunctionRegisteredCompleter::Sync completer) {
  functions_registered_++;
  if (all_functions_registered()) {
    state_changed_ = true;
    loop_->Quit();
    completer.Close(ZX_ERR_CANCELED);
  } else {
    completer.Reply();
  }
}

void USBVirtualBusBase::SetupPeripheralDevice(const DeviceDescriptor& device_desc,
                                              std::vector<FunctionDescriptor> function_descs) {
  zx::channel state_change_sender, state_change_receiver;
  ASSERT_EQ(zx::channel::create(0, &state_change_sender, &state_change_receiver), ZX_OK);
  auto set_result = peripheral_->SetStateChangeListener(std::move(state_change_receiver));
  ASSERT_EQ(set_result.status(), ZX_OK);

  auto set_config = peripheral_->SetConfiguration(
      device_desc, ::fidl::VectorView(function_descs.size(), function_descs.data()));
  ASSERT_EQ(set_config.status(), ZX_OK);
  ASSERT_FALSE(set_config->result.is_err());

  async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
  EventWatcher watcher(&loop, std::move(state_change_sender), function_descs.size());
  loop.Run();
  ASSERT_TRUE(watcher.all_functions_registered());

  auto connect_result = virtual_bus_->Connect();
  ASSERT_EQ(connect_result.status(), ZX_OK);
  ASSERT_EQ(connect_result.value().status, ZX_OK);
}

}  // namespace usb_virtual_bus
