// 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 "device_controller_connection.h"

#include <fidl/fuchsia.device/cpp/wire.h>
#include <lib/zx/channel.h>
#include <lib/zx/vmo.h>
#include <zircon/status.h>

#include <fbl/auto_lock.h>
#include <fbl/string_printf.h>

#include "driver_host.h"
#include "env.h"
#include "log.h"
#include "proxy_iostate.h"
#include "zx_device.h"
#include "zx_driver.h"

namespace {

// Handles outstanding calls to fuchsia.device.manager.DeviceController/BindDriver
// and fuchsia.device.Controller/Bind.
void BindReply(const fbl::RefPtr<zx_device_t>& dev,
               DeviceControllerConnection::BindDriverCompleter::Sync& completer, zx_status_t status,
               zx::channel test_output = zx::channel()) {
  completer.Reply(status, std::move(test_output));

  bool complete_bind = true;
  for (auto& child : dev->children()) {
    if ((child.flags() & DEV_FLAG_INVISIBLE) || child.ops()->init) {
      // Driver has initialization to do.
      complete_bind = false;
    }
  }
  if (!complete_bind) {
    dev->set_complete_bind_rebind_after_init(true);
    return;
  }
  if (auto bind_conn = dev->take_bind_conn(); bind_conn) {
    bind_conn(status);
  }

  if (auto rebind_conn = dev->take_rebind_conn(); rebind_conn) {
    rebind_conn(status);
  }
}

}  // namespace

void DeviceControllerConnection::Init(InitRequestView request, InitCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->init_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "init");
  this->dev()->init_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                             zx_status_t status) mutable { completer.Reply(status); };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceInit(this->dev());
}

void DeviceControllerConnection::Suspend(SuspendRequestView request,
                                         SuspendCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->suspend_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "suspend");
  this->dev()->suspend_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                                zx_status_t status, uint8_t out_state) mutable {
    if (status == ZX_ERR_NOT_SUPPORTED) {
      status = ZX_OK;
    }
    completer.Reply(status);
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceSystemSuspend(this->dev(), request->flags);
}

void DeviceControllerConnection::Resume(ResumeRequestView request,
                                        ResumeCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->resume_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "resume");
  this->dev()->resume_cb = [completer = completer.ToAsync(), trace = std::move(trace)](
                               zx_status_t status, uint8_t out_power_state,
                               uint32_t out_perf_state) mutable {
    if (status == ZX_ERR_NOT_SUPPORTED) {
      status = ZX_OK;
    }
    if (status != ZX_OK &&
        (out_power_state ==
         static_cast<uint8_t>(fuchsia_device::wire::DevicePowerState::kDevicePowerStateD0))) {
      // Do not fail system resume, when the device is unable to go into a particular performance
      // state, but resumed to a working state.
      status = ZX_OK;
    }
    completer.Reply(status);
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceSystemResume(this->dev(), request->target_system_state);
}

void DeviceControllerConnection::ConnectProxy(ConnectProxyRequestView request,
                                              ConnectProxyCompleter::Sync& _completer) {
  VLOGD(1, *dev(), "Connected to proxy for device %p", dev().get());
  dev()->ops()->rxrpc(dev()->ctx, ZX_HANDLE_INVALID);
  // Ignore any errors in the creation for now?
  // TODO(teisenbe): Investigate if this is the right thing
  ProxyIostate::Create(dev(), std::move(request->shadow),
                       driver_host_context_->loop().dispatcher());
}

void DeviceControllerConnection::BindDriver(BindDriverRequestView request,
                                            BindDriverCompleter::Sync& completer) {
  const auto& dev = this->dev();
  std::string_view driver_path(request->driver_path.data(), request->driver_path.size());

  // TODO: api lock integration
  if (driver_path != "/boot/driver/fragment.so") {
    LOGD(INFO, *dev, "Binding driver '%.*s'", static_cast<int>(driver_path.size()),
         driver_path.data());
  } else {
    LOGD(TRACE, *dev, "Binding driver '%.*s'", static_cast<int>(driver_path.size()),
         driver_path.data());
  }
  if (dev->flags() & DEV_FLAG_DEAD) {
    LOGD(ERROR, *dev, "Cannot bind to removed device");
    BindReply(dev, completer, ZX_ERR_IO_NOT_PRESENT);
    return;
  }

  fbl::RefPtr<zx_driver_t> drv;
  fbl::RefPtr<Driver> driver;
  zx_status_t r =
      driver_host_context_->FindDriver(driver_path, std::move(request->driver), &drv, &driver);
  if (r != ZX_OK) {
    LOGD(ERROR, *dev, "Failed to load driver '%.*s': %s", static_cast<int>(driver_path.size()),
         driver_path.data(), zx_status_get_string(r));
    BindReply(dev, completer, r);
    return;
  }

  // Check for driver test flags.
  bool tests_default = getenv_bool("driver.tests.enable", false);
  auto option = fbl::StringPrintf("driver.%s.tests.enable", drv->name());
  zx::channel test_output;
  if (getenv_bool(option.data(), tests_default) && drv->has_run_unit_tests_op()) {
    zx::channel test_input;
    zx::channel::create(0, &test_input, &test_output);
    bool tests_passed = drv->RunUnitTestsOp(dev, driver, std::move(test_input));
    if (!tests_passed) {
      FX_LOGF(ERROR, "unit-tests", "[  FAILED  ] %s", drv->name());
      drv->set_status(ZX_ERR_BAD_STATE);
      BindReply(dev, completer, ZX_ERR_BAD_STATE, std::move(test_output));
      return;
    }
    FX_LOGF(INFO, "unit-tests", "[  PASSED  ] %s", drv->name());
  }

  if (drv->has_bind_op()) {
    internal::BindContext bind_ctx = {
        .parent = dev,
        .child = nullptr,
    };
    r = drv->BindOp(&bind_ctx, driver, dev);

    if (r != ZX_OK) {
      LOGD(ERROR, *dev, "Failed to bind driver '%.*s': %s", static_cast<int>(driver_path.size()),
           driver_path.data(), zx_status_get_string(r));
    } else if (bind_ctx.child == nullptr) {
      LOGD(WARNING, *dev, "Driver '%.*s' did not add a child device in bind()",
           static_cast<int>(driver_path.size()), driver_path.data());
    }
    BindReply(dev, completer, r, std::move(test_output));
    return;
  }

  if (!drv->has_create_op()) {
    LOGD(ERROR, *dev, "Neither create() nor bind() are implemented for driver '%.*s'",
         static_cast<int>(driver_path.size()), driver_path.data());
  }
  BindReply(dev, completer, ZX_ERR_NOT_SUPPORTED, std::move(test_output));
}

void DeviceControllerConnection::Unbind(UnbindRequestView request,
                                        UnbindCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->unbind_cb == nullptr);

  auto trace = this->dev()->BeginAsyncTrace("driver_host:lifecycle", "unbind");

  this->dev()->unbind_cb = [dev = this->dev(), completer = completer.ToAsync(),
                            trace = std::move(trace)](zx_status_t status) mutable {
    if (status != ZX_OK && dev->parent()) {
      // If unbind returns an error, and if client is waiting for unbind to complete,
      // inform the client.
      if (auto unbind_children_conn = dev->parent()->take_unbind_children_conn();
          unbind_children_conn) {
        unbind_children_conn(status);
      }
    }
    completer.ReplySuccess();
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceUnbind(this->dev());
}

void DeviceControllerConnection::CompleteRemoval(CompleteRemovalRequestView request,
                                                 CompleteRemovalCompleter::Sync& completer) {
  ZX_ASSERT(this->dev()->removal_cb == nullptr);
  this->dev()->removal_cb = [completer = completer.ToAsync()](zx_status_t status) mutable {
    completer.ReplySuccess();
  };
  fbl::AutoLock lock(&driver_host_context_->api_lock());
  driver_host_context_->DeviceCompleteRemoval(this->dev());
}

DeviceControllerConnection::DeviceControllerConnection(
    DriverHostContext* ctx, fbl::RefPtr<zx_device> dev,
    fidl::WireSharedClient<fuchsia_device_manager::Coordinator> coordinator_client)
    : driver_host_context_(ctx),
      dev_(std::move(dev)),
      coordinator_client_(std::move(coordinator_client)) {
  dev_->coordinator_client = coordinator_client_.Clone();
}

std::unique_ptr<DeviceControllerConnection> DeviceControllerConnection::Create(
    DriverHostContext* ctx, fbl::RefPtr<zx_device> dev,
    fidl::WireSharedClient<fuchsia_device_manager::Coordinator> coordinator_client) {
  return std::make_unique<DeviceControllerConnection>(ctx, std::move(dev),
                                                      std::move(coordinator_client));
}

void DeviceControllerConnection::Bind(
    std::unique_ptr<DeviceControllerConnection> conn,
    fidl::ServerEnd<fuchsia_device_manager::DeviceController> request,
    async_dispatcher_t* dispatcher) {
  auto dev = conn->dev_;
  fbl::AutoLock al(&dev->controller_lock);
  dev->controller_binding = fidl::BindServer(
      dispatcher, std::move(request), std::move(conn),
      [](DeviceControllerConnection* self, fidl::UnbindInfo info,
         fidl::ServerEnd<fuchsia_device_manager::DeviceController> server_end) {
        auto& dev = self->dev_;
        if (info.is_user_initiated()) {
          return;
        }
        if (info.is_peer_closed()) {
          // Check if we were expecting this peer close.  If not, this could be a
          // serious bug.
          {
            fbl::AutoLock al(&dev->controller_lock);
            if (!dev->controller_binding) {
              // We're in the middle of shutting down, so just stop processing
              // signals and wait for the queued shutdown packet.  It has a
              // reference to the connection, which it will use to recover
              // ownership of it.
              return;
            }
          }

          // This is expected in test environments where driver_manager has
          // terminated.
          // TODO(fxbug.dev/52627): Support graceful termination.
          LOGD(WARNING, *dev, "driver_manager disconnected from device %p", dev.get());
          zx_process_exit(1);
          return;
        }
        LOGD(FATAL, *dev, "FIDL error for device %p: %s", dev.get(),
             info.FormatDescription().c_str());
      });
}

// Handler for when a fuchsia.io open() is called on a device
void DeviceControllerConnection::Open(OpenRequestView request, OpenCompleter::Sync& completer) {
  VLOGD(1, *dev(), "Opening device %p", dev().get());
  if (request->path.size() > 1 && request->path.data()[0] != '.') {
    LOGD(ERROR, *dev(), "Attempt to open path '%.*s'", static_cast<int>(request->path.size()),
         request->path.data());
  }
  driver_host_context_->DeviceConnect(this->dev(), request->flags, request->object.TakeChannel());
}
