// 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/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/hw/usb.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <fbl/string.h>
#include <gtest/gtest.h>
#include <sdk/lib/device-watcher/cpp/device-watcher.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;
  device_watcher::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_ =
      fidl::BindSyncClient<fuchsia_hardware_usb_virtual_bus::Bus>(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_ =
      fidl::BindSyncClient<fuchsia_hardware_usb_peripheral::Device>(std::move(peripheral));

  ASSERT_NO_FATAL_FAILURE(ClearPeripheralDeviceFunctions());
}

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

class EventWatcher : public fidl::WireServer<fuchsia_hardware_usb_peripheral::Events> {
 public:
  explicit EventWatcher(async::Loop* loop, zx::channel svc, size_t functions)
      : loop_(loop), functions_(functions) {
    fidl::BindSingleInFlightOnly(loop->dispatcher(), std::move(svc), this);
  }

  void FunctionRegistered(FunctionRegisteredRequestView request,
                          FunctionRegisteredCompleter::Sync& completer) override;
  void FunctionsCleared(FunctionsClearedRequestView request,
                        FunctionsClearedCompleter::Sync& completer) override;

  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(FunctionRegisteredRequestView request,
                                      FunctionRegisteredCompleter::Sync& completer) {
  functions_registered_++;
  if (all_functions_registered()) {
    loop_->Quit();
    completer.Close(ZX_ERR_CANCELED);
  } else {
    completer.Reply();
  }
}

void EventWatcher::FunctionsCleared(FunctionsClearedRequestView request,
                                    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) {
  using ConfigurationDescriptor =
      ::fidl::VectorView<fuchsia_hardware_usb_peripheral::wire::FunctionDescriptor>;
  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);
  std::vector<ConfigurationDescriptor> config_descs;
  config_descs.emplace_back(fidl::VectorView<FunctionDescriptor>::FromExternal(function_descs));
  auto set_config = peripheral_->SetConfiguration(
      std::move(device_desc),
      fidl::VectorView<ConfigurationDescriptor>::FromExternal(config_descs));
  ASSERT_EQ(set_config.status(), ZX_OK);
  ASSERT_FALSE(set_config->is_error());

  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
