// 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/async-loop/default.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::CreateAndServeOutgoingDirectory();
  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));

  ASSERT_NO_FATAL_FAILURE(ClearPeripheralDeviceFunctions());
}

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);
  void FunctionsCleared(FunctionsClearedCompleter::Sync completer);

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

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

  bool all_functions_cleared_ = false;
};

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

void EventWatcher::FunctionsCleared(FunctionsClearedCompleter::Sync completer) {
  all_functions_cleared_ = true;
  loop_->Quit();
  completer.Close(ZX_ERR_CANCELED);
}

void USBVirtualBusBase::SetupPeripheralDevice(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(std::move(device_desc), ::fidl::unowned_vec(function_descs));
  ASSERT_EQ(set_config.status(), ZX_OK);
  ASSERT_FALSE(set_config->result.is_err());

  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  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);
}

void USBVirtualBusBase::ClearPeripheralDeviceFunctions() {
  zx::channel handles[2];
  ASSERT_EQ(zx::channel::create(0, handles, handles + 1), ZX_OK);
  auto set_result = peripheral_->SetStateChangeListener(std::move(handles[1]));
  ASSERT_EQ(set_result.status(), ZX_OK);

  auto clear_functions = peripheral_->ClearFunctions();
  ASSERT_EQ(clear_functions.status(), ZX_OK);

  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  EventWatcher watcher(&loop, std::move(handles[0]), 0);
  loop.Run();
  ASSERT_TRUE(watcher.all_functions_cleared());
}

}  // namespace usb_virtual_bus
