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

#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/device/manager/llcpp/fidl.h>
#include <fuchsia/driver/test/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/fidl/coding.h>
#include <lib/zx/clock.h>
#include <zircon/status.h>

#include <memory>

#include <ddk/driver.h>
#include <fbl/auto_call.h>

#include "coordinator.h"
#include "devfs.h"
#include "fidl.h"
#include "fidl_txn.h"
#include "init_task.h"
#include "resume_task.h"
#include "src/devices/lib/log/log.h"
#include "suspend_task.h"

// TODO(fxbug.dev/43370): remove this once init tasks can be enabled for all devices.
static constexpr bool kEnableAlwaysInit = false;

Device::Device(Coordinator* coord, fbl::String name, fbl::String libname, fbl::String args,
               fbl::RefPtr<Device> parent, uint32_t protocol_id, zx::vmo inspect_vmo,
               zx::channel client_remote, bool wait_make_visible)
    : coordinator(coord),
      name_(std::move(name)),
      libname_(std::move(libname)),
      args_(std::move(args)),
      parent_(std::move(parent)),
      protocol_id_(protocol_id),
      publish_task_([this] { coordinator->HandleNewDevice(fbl::RefPtr(this)); }),
      client_remote_(std::move(client_remote)),
      wait_make_visible_(wait_make_visible) {
  test_reporter = std::make_unique<DriverTestReporter>(name_);
  inspect_.emplace(coord->inspect_manager().devices(), coord->inspect_manager().device_count(),
                   name_.c_str(), std::move(inspect_vmo));
  set_state(Device::State::kActive);  // set default state
}

Device::~Device() {
  // Ideally we'd assert here that immortal devices are never destroyed, but
  // they're destroyed when the Coordinator object is cleaned up in tests.
  // We can probably get rid of the IMMORTAL flag, since if the Coordinator is
  // holding a reference we shouldn't be able to hit that check, in which case
  // the flag is only used to modify the proxy library loading behavior.

  devfs_unpublish(this);

  // If we destruct early enough, we may have created the core devices and devfs might not exist
  // yet.
  if (coordinator->inspect_manager().devfs()) {
    coordinator->inspect_manager().devfs()->Unpublish(this);
  }

  // Drop our reference to our driver_host if we still have it
  set_host(nullptr);

  std::unique_ptr<Metadata> md;
  while ((md = metadata_.pop_front()) != nullptr) {
    if (md->has_path) {
      // return to published_metadata list
      coordinator->AppendPublishedMetadata(std::move(md));
    } else {
      // metadata was attached directly to this device, so we release it now
    }
  }

  // TODO: cancel any pending rpc responses
  // TODO: Have dtor assert that DEV_CTX_IMMORTAL set on flags
  VLOGF(1, "Destroyed device %p '%s'", this, name_.data());
}

zx_status_t Device::Create(Coordinator* coordinator, const fbl::RefPtr<Device>& parent,
                           fbl::String name, fbl::String driver_path, fbl::String args,
                           uint32_t protocol_id, fbl::Array<zx_device_prop_t> props,
                           zx::channel coordinator_rpc, zx::channel device_controller_rpc,
                           bool wait_make_visible, bool want_init_task, bool skip_autobind,
                           zx::vmo inspect, zx::channel client_remote,
                           fbl::RefPtr<Device>* device) {
  fbl::RefPtr<Device> real_parent;
  // If our parent is a proxy, for the purpose of devfs, we need to work with
  // *its* parent which is the device that it is proxying.
  if (parent->flags & DEV_CTX_PROXY) {
    real_parent = parent->parent();
  } else {
    real_parent = parent;
  }

  auto dev = fbl::MakeRefCounted<Device>(
      coordinator, std::move(name), std::move(driver_path), std::move(args), real_parent,
      protocol_id, std::move(inspect), std::move(client_remote), wait_make_visible);
  if (!dev) {
    return ZX_ERR_NO_MEMORY;
  }

  if (skip_autobind) {
    dev->flags |= DEV_CTX_SKIP_AUTOBIND;
  }

  // Initialise and publish device inspect
  if (auto status = coordinator->inspect_manager().devfs()->InitInspectFileAndPublish(dev);
      status.is_error()) {
    return status.error_value();
  }

  zx_status_t status = dev->SetProps(std::move(props));
  if (status != ZX_OK) {
    return status;
  }

  dev->device_controller_.Bind(std::move(device_controller_rpc), coordinator->dispatcher());
  dev->set_channel(std::move(coordinator_rpc));

  // If we have bus device args we are, by definition, a bus device.
  if (dev->args_.size() > 0) {
    dev->flags |= DEV_CTX_MUST_ISOLATE;
  }

  // We exist within our parent's device host
  dev->set_host(parent->host());

  // We must mark the device as invisible before publishing so
  // that we don't send "device added" notifications.
  // The init task must complete before marking the device visible.
  // If |wait_make_visible| is true, we also wait for a device_make_visible call.
  // TODO(fxbug.dev/43370): this check should be removed once init tasks apply to all devices.
  if (wait_make_visible || want_init_task) {
    dev->flags |= DEV_CTX_INVISIBLE;
  }

  if ((status = devfs_publish(real_parent, dev)) < 0) {
    return status;
  }

  if ((status = Device::BeginWait(dev, coordinator->dispatcher())) != ZX_OK) {
    return status;
  }

  real_parent->children_.push_back(dev.get());
  VLOGF(1, "Created device %p '%s' (child)", real_parent.get(), real_parent->name().data());

  if (want_init_task) {
    dev->CreateInitTask();
  }

  dev->InitializeInspectValues();

  *device = std::move(dev);
  return ZX_OK;
}

zx_status_t Device::CreateComposite(Coordinator* coordinator, fbl::RefPtr<DriverHost> driver_host,
                                    const CompositeDevice& composite, zx::channel coordinator_rpc,
                                    zx::channel device_controller_rpc,
                                    fbl::RefPtr<Device>* device) {
  const auto& composite_props = composite.properties();
  fbl::Array<zx_device_prop_t> props(new zx_device_prop_t[composite_props.size()],
                                     composite_props.size());
  memcpy(props.data(), composite_props.data(), props.size() * sizeof(props[0]));

  auto dev =
      fbl::MakeRefCounted<Device>(coordinator, composite.name(), fbl::String(), fbl::String(),
                                  nullptr, ZX_PROTOCOL_COMPOSITE, zx::vmo(), zx::channel());
  if (!dev) {
    return ZX_ERR_NO_MEMORY;
  }

  if (auto status = coordinator->inspect_manager().devfs()->InitInspectFileAndPublish(dev);
      status.is_error()) {
    return status.error_value();
  }

  zx_status_t status = dev->SetProps(std::move(props));
  if (status != ZX_OK) {
    return status;
  }

  dev->device_controller_.Bind(std::move(device_controller_rpc), coordinator->dispatcher());
  dev->set_channel(std::move(coordinator_rpc));
  // We exist within our parent's device host
  dev->set_host(std::move(driver_host));

  // TODO: Record composite membership

  // TODO(teisenbe): Figure out how to manifest in devfs?  For now just hang it off of
  // the root device?
  if ((status = devfs_publish(coordinator->root_device(), dev)) < 0) {
    return status;
  }

  if ((status = Device::BeginWait(dev, coordinator->dispatcher())) != ZX_OK) {
    return status;
  }

  VLOGF(1, "Created composite device %p '%s'", dev.get(), dev->name().data());

  dev->InitializeInspectValues();
  *device = std::move(dev);
  return ZX_OK;
}

zx_status_t Device::CreateProxy() {
  ZX_ASSERT(proxy_ == nullptr);

  fbl::String driver_path = libname_;
  // non-immortal devices, use foo.proxy.so for
  // their proxy devices instead of foo.so
  if (!(this->flags & DEV_CTX_IMMORTAL)) {
    const char* begin = driver_path.data();
    const char* end = strstr(begin, ".so");
    fbl::StringPiece prefix(begin, end == nullptr ? driver_path.size() : end - begin);
    fbl::AllocChecker ac;
    driver_path = fbl::String::Concat({prefix, ".proxy.so"}, &ac);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
  }

  auto dev =
      fbl::MakeRefCounted<Device>(this->coordinator, name_, std::move(driver_path), fbl::String(),
                                  fbl::RefPtr(this), protocol_id_, zx::vmo(), zx::channel());
  if (dev == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  dev->flags = DEV_CTX_PROXY;

  dev->InitializeInspectValues();

  proxy_ = std::move(dev);
  VLOGF(1, "Created proxy device %p '%s'", this, name_.data());
  return ZX_OK;
}

void Device::InitializeInspectValues() {
  inspect().set_driver(libname().c_str());
  inspect().set_protocol_id(protocol_id_);
  inspect().set_flags(flags);
  inspect().set_properties(props());

  char path[fuchsia_device_manager_DEVICE_PATH_MAX] = {};
  coordinator->GetTopologicalPath(fbl::RefPtr(this), path, fuchsia_device_manager_DEVICE_PATH_MAX);
  inspect().set_topological_path(path);

  std::string type("Device");
  if (flags & DEV_CTX_PROXY) {
    type = std::string("Proxy device");
  } else if (protocol_id_ == ZX_PROTOCOL_COMPOSITE) {
    type = std::string("Composite device");
  }
  inspect().set_type(type);
}

void Device::DetachFromParent() {
  // Do this first as we might be deleting the last reference to ourselves.
  auto parent = std::move(parent_);
  if (this->flags & DEV_CTX_PROXY) {
    parent->proxy_ = nullptr;
  } else {
    parent->children_.erase(*this);
  }
}

zx_status_t Device::SignalReadyForBind(zx::duration delay) {
  return publish_task_.PostDelayed(this->coordinator->dispatcher(), delay);
}

void Device::CreateInitTask() {
  // We only ever create an init task when a device is initially added.
  ZX_ASSERT(!active_init_);
  set_state(Device::State::kInitializing);
  active_init_ = InitTask::Create(fbl::RefPtr(this));
}

fbl::RefPtr<SuspendTask> Device::RequestSuspendTask(uint32_t suspend_flags) {
  if (active_suspend_) {
    // We don't support different types of suspends concurrently, and
    // shouldn't be able to reach this state.
    ZX_ASSERT(suspend_flags == active_suspend_->suspend_flags());
  } else {
    active_suspend_ = SuspendTask::Create(fbl::RefPtr(this), suspend_flags);
  }
  return active_suspend_;
}

zx_status_t Device::SendInit(InitCompletion completion) {
  ZX_ASSERT(!init_completion_);

  VLOGF(1, "Initializing device %p '%s'", this, name_.data());
  zx_status_t status = dh_send_init(this);
  if (status != ZX_OK) {
    return status;
  }
  init_completion_ = std::move(completion);
  return ZX_OK;
}

zx_status_t Device::CompleteInit(zx_status_t status) {
  if (!init_completion_ && status == ZX_OK) {
    LOGF(ERROR, "Unexpected reply when initializing device %p '%s'", this, name_.data());
    return ZX_ERR_IO;
  }
  if (init_completion_) {
    init_completion_(status);
  }
  active_init_ = nullptr;
  return ZX_OK;
}

fbl::RefPtr<ResumeTask> Device::RequestResumeTask(uint32_t target_system_state) {
  if (active_resume_) {
    // We don't support different types of resumes concurrently, and
    // shouldn't be able to reach this state.
    ZX_ASSERT(target_system_state == active_resume_->target_system_state());
  } else {
    active_resume_ = ResumeTask::Create(fbl::RefPtr(this), target_system_state);
  }
  return active_resume_;
}

zx_status_t Device::SendSuspend(uint32_t flags, SuspendCompletion completion) {
  if (suspend_completion_) {
    // We already have a pending suspend
    return ZX_ERR_UNAVAILABLE;
  }
  VLOGF(1, "Suspending device %p '%s'", this, name_.data());
  zx_status_t status = dh_send_suspend(this, flags);
  if (status != ZX_OK) {
    return status;
  }
  set_state(Device::State::kSuspending);
  suspend_completion_ = std::move(completion);
  return ZX_OK;
}

zx_status_t Device::SendResume(uint32_t target_system_state, ResumeCompletion completion) {
  if (resume_completion_) {
    // We already have a pending resume
    return ZX_ERR_UNAVAILABLE;
  }
  VLOGF(1, "Resuming device %p '%s'", this, name_.data());
  zx_status_t status = dh_send_resume(this, target_system_state);
  if (status != ZX_OK) {
    return status;
  }
  set_state(Device::State::kResuming);
  resume_completion_ = std::move(completion);
  return ZX_OK;
}

void Device::CompleteSuspend(zx_status_t status) {
  if (status == ZX_OK) {
    // If a device is being removed, any existing suspend task will be forcibly completed,
    // in which case we should not update the state.
    if (state_ != Device::State::kDead) {
      set_state(Device::State::kSuspended);
    }
  } else {
    set_state(Device::State::kActive);
  }

  active_suspend_ = nullptr;
  if (suspend_completion_) {
    suspend_completion_(status);
  }
}

void Device::CompleteResume(zx_status_t status) {
  if (status != ZX_OK) {
    set_state(Device::State::kSuspended);
  } else {
    set_state(Device::State::kResumed);
  }
  if (resume_completion_) {
    resume_completion_(status);
  }
}

void Device::CreateUnbindRemoveTasks(UnbindTaskOpts opts) {
  if (state_ == Device::State::kDead) {
    return;
  }
  // Create the tasks if they do not exist yet. We always create both.
  if (active_unbind_ == nullptr && active_remove_ == nullptr) {
    // Make sure the remove task exists before the unbind task,
    // as the unbind task adds the remove task as a dependent.
    active_remove_ = RemoveTask::Create(fbl::RefPtr(this));
    active_unbind_ = UnbindTask::Create(fbl::RefPtr(this), opts);
    return;
  }
  if (!active_unbind_) {
    // The unbind task has already completed and the device is now being removed.
    return;
  }
  // User requested removals take priority over coordinator generated unbind tasks.
  bool override_existing = opts.driver_host_requested && !active_unbind_->driver_host_requested();
  if (!override_existing) {
    return;
  }
  // There is a potential race condition where a driver calls device_remove() on themselves
  // but the device's unbind hook is about to be called due to a parent being removed.
  // Since it is illegal to call device_remove() twice under the old API,
  // drivers handle this by checking whether their device has already been removed in
  // their unbind hook and hence will never reply to their unbind hook.
  if (state_ == Device::State::kUnbinding) {
    if (unbind_completion_) {
      zx_status_t status = CompleteUnbind(ZX_OK);
      if (status != ZX_OK) {
        LOGF(ERROR, "Cannot complete unbind: %s", zx_status_get_string(status));
      }
    }
  } else {
    // |do_unbind| may not match the stored field in the existing unbind task due to
    // the current device_remove / unbind model.
    // For closest compatibility with the current model, we should prioritize
    // driver_host calls to |ScheduleRemove| over our own scheduled unbind tasks for the children.
    active_unbind_->set_do_unbind(opts.do_unbind);
  }
}

zx_status_t Device::SendUnbind(UnbindCompletion completion) {
  if (unbind_completion_) {
    // We already have a pending unbind
    return ZX_ERR_UNAVAILABLE;
  }
  VLOGF(1, "Unbinding device %p '%s'", this, name_.data());
  set_state(Device::State::kUnbinding);
  unbind_completion_ = std::move(completion);
  zx_status_t status = dh_send_unbind(this);
  if (status != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

zx_status_t Device::SendCompleteRemoval(RemoveCompletion completion) {
  if (remove_completion_) {
    // We already have a pending remove.
    return ZX_ERR_UNAVAILABLE;
  }
  VLOGF(1, "Completing removal of device %p '%s'", this, name_.data());
  set_state(Device::State::kUnbinding);
  remove_completion_ = std::move(completion);
  zx_status_t status = dh_send_complete_removal(
      this, [dev = fbl::RefPtr(this)]() mutable { dev->CompleteRemove(); });
  if (status != ZX_OK) {
    return status;
  }
  return ZX_OK;
}

zx_status_t Device::CompleteUnbind(zx_status_t status) {
  if (!unbind_completion_ && status == ZX_OK) {
    LOGF(ERROR, "Unexpected reply when unbinding device %p '%s'", this, name_.data());
    return ZX_ERR_IO;
  }
  if (unbind_completion_) {
    unbind_completion_(status);
  }
  active_unbind_ = nullptr;
  return ZX_OK;
}

zx_status_t Device::CompleteRemove(zx_status_t status) {
  if (!remove_completion_ && status == ZX_OK) {
    LOGF(ERROR, "Unexpected reply when removing device %p '%s'", this, name_.data());
    return ZX_ERR_IO;
  }
  // If we received an error, it is because we are currently force removing the device.
  if (status == ZX_OK) {
    coordinator->RemoveDevice(fbl::RefPtr(this), false);
  }
  if (remove_completion_) {
    // If we received an error, it is because we are currently force removing the device.
    // In that case, all other devices in the driver_host will be force removed too,
    // and they will call CompleteRemove() before the remove task is scheduled to run.
    // For ancestor dependents in other driver_hosts, we want them to proceed removal as usual.
    remove_completion_(ZX_OK);
  }
  active_remove_ = nullptr;
  return ZX_OK;
}

// Handle inbound messages from driver_host to devices
void Device::HandleRpc(fbl::RefPtr<Device>&& dev, async_dispatcher_t* dispatcher,
                       async::WaitBase* wait, zx_status_t status,
                       const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to wait on RPC for device %p '%s': %s", dev.get(), dev->name().data(),
         zx_status_get_string(status));
    return;
  }

  if (signal->observed & ZX_CHANNEL_READABLE) {
    zx_status_t r = dev->HandleRead();
    if (r != ZX_OK) {
      if (r != ZX_ERR_STOP) {
        LOGF(ERROR, "Failed to handle RPC for device %p '%s': %s", dev.get(), dev->name().data(),
             zx_status_get_string(r));
      }
      // If this device isn't already dead (removed), remove it. RemoveDevice() may
      // have been called by the RPC handler, in particular for the RemoveDevice RPC.
      if (dev->state() != Device::State::kDead) {
        dev->coordinator->RemoveDevice(dev, true);
      }
      // Do not start waiting again on this device's channel again
      return;
    }
    Device::BeginWait(std::move(dev), dispatcher);
    return;
  }
  if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
    // If the device is already dead, we are detecting an expected disconnect from the driver_host.
    if (dev->state() != Device::State::kDead) {
      // TODO(fxbug.dev/56208): Change this log back to error once isolated devmgr is fixed.
      LOGF(WARNING, "Disconnected device %p '%s', see fxbug.dev/56208 for potential cause",
           dev.get(), dev->name().data());
      dev->coordinator->RemoveDevice(dev, true);
    }
    // Do not start waiting again on this device's channel again
    return;
  }
  LOGF(WARNING, "Unexpected signal state %#08x for device %p '%s'", signal->observed, dev.get(),
       dev->name().data());
  Device::BeginWait(std::move(dev), dispatcher);
}

static zx_status_t fidl_LogMessage(void* ctx, const char* msg, size_t size) {
  auto dev = static_cast<Device*>(ctx);
  dev->test_reporter->LogMessage(msg, size);
  return ZX_OK;
}

static zx_status_t fidl_LogTestCase(void* ctx, const char* name, size_t name_size,
                                    const fuchsia_driver_test_TestCaseResult* result) {
  auto dev = static_cast<Device*>(ctx);
  dev->test_reporter->LogTestCase(name, name_size, result);
  return ZX_OK;
}

static const fuchsia_driver_test_Logger_ops_t kTestOps = {
    .LogMessage = fidl_LogMessage,
    .LogTestCase = fidl_LogTestCase,
};

void Device::HandleTestOutput(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                              zx_status_t status, const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to wait on test output for device %p '%s': %s", this, name_.data(),
         zx_status_get_string(status));
    return;
  }
  if (!(signal->observed & ZX_CHANNEL_PEER_CLOSED)) {
    LOGF(WARNING, "Unexpected signal state %#08x for device %p '%s'", signal->observed, this,
         name_.data());
    return;
  }

  test_reporter->TestStart();

  // Now that the driver has closed the channel, read all of the messages.
  // TODO(fxbug.dev/34151): Handle the case where the channel fills up before we begin reading.
  while (true) {
    uint8_t msg_bytes[ZX_CHANNEL_MAX_MSG_BYTES];
    zx_handle_info_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
    uint32_t msize = sizeof(msg_bytes);
    uint32_t hcount = std::size(handles);

    zx_status_t r = test_output_.read_etc(0, &msg_bytes, handles, msize, hcount, &msize, &hcount);
    if (r == ZX_ERR_PEER_CLOSED) {
      test_reporter->TestFinished();
      break;
    } else if (r != ZX_OK) {
      LOGF(ERROR, "Failed to read test output for device %p '%s': %s", this, name_.data(),
           zx_status_get_string(r));
      break;
    }

    fidl_incoming_msg_t fidl_msg = {
        .bytes = msg_bytes,
        .handles = handles,
        .num_bytes = msize,
        .num_handles = hcount,
    };

    if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
      FidlHandleInfoCloseMany(fidl_msg.handles, fidl_msg.num_handles);
      LOGF(ERROR, "Invalid FIDL message header for device %p '%s'", this, name_.data());
      break;
    }

    auto header = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
    FidlTxn txn(test_output_, header->txid);
    r = fuchsia_driver_test_Logger_dispatch(this, txn.fidl_txn(), &fidl_msg, &kTestOps);
    if (r != ZX_OK) {
      LOGF(ERROR, "Failed to handle RPC for device %p '%s': %s", this, name_.data(),
           zx_status_get_string(r));
      break;
    }
  }
}

zx_status_t Device::HandleRead() {
  uint8_t msg[ZX_CHANNEL_MAX_MSG_BYTES];
  zx_handle_info_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
  uint32_t msize = sizeof(msg);
  uint32_t hcount = std::size(hin);

  if (state_ == Device::State::kDead) {
    LOGF(ERROR, "Attempted to RPC dead device %p '%s'", this, name_.data());
    return ZX_ERR_INTERNAL;
  }

  zx_status_t r;
  if ((r = channel()->read_etc(0, &msg, hin, msize, hcount, &msize, &hcount)) != ZX_OK) {
    return r;
  }

  fidl_incoming_msg_t fidl_msg = {
      .bytes = msg,
      .handles = hin,
      .num_bytes = msize,
      .num_handles = hcount,
  };

  if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
    FidlHandleInfoCloseMany(fidl_msg.handles, fidl_msg.num_handles);
    return ZX_ERR_IO;
  }

  auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
  // Check if we're receiving a Coordinator request
  {
    zx::unowned_channel conn = channel();
    DevmgrFidlTxn txn(std::move(conn), hdr->txid);
    ::fidl::DispatchResult dispatch_result =
        llcpp::fuchsia::device::manager::Coordinator::TryDispatch(this, &fidl_msg, &txn);
    auto status = txn.Status();
    if (dispatch_result == ::fidl::DispatchResult::kFound) {
      if (status == ZX_OK && state_ == Device::State::kDead) {
        // We have removed the device. Signal that we are done with this channel.
        return ZX_ERR_STOP;
      }
      return status;
    }
  }

  LOGF(ERROR, "Unsupported FIDL protocol (ordinal %#16lx) for device %p '%s'", hdr->ordinal, this,
       name_.data());
  FidlHandleInfoCloseMany(fidl_msg.handles, fidl_msg.num_handles);
  return ZX_ERR_IO;
}

zx_status_t Device::SetProps(fbl::Array<const zx_device_prop_t> props) {
  // This function should only be called once
  ZX_DEBUG_ASSERT(props_.data() == nullptr);

  props_ = std::move(props);
  topo_prop_ = nullptr;

  for (const auto prop : props_) {
    if (prop.id >= BIND_TOPO_START && prop.id <= BIND_TOPO_END) {
      if (topo_prop_ != nullptr) {
        return ZX_ERR_INVALID_ARGS;
      }
      topo_prop_ = &prop;
    }
  }
  return ZX_OK;
}

void Device::set_host(fbl::RefPtr<DriverHost> host) {
  if (host_) {
    host_->devices().erase(*this);
  }
  host_ = std::move(host);
  set_local_id(0);
  if (host_) {
    host_->devices().push_back(this);
    set_local_id(host_->new_device_id());
  }
}

const char* Device::GetTestDriverName() {
  for (auto& child : children()) {
    return this->coordinator->LibnameToDriver(child.libname().data())->name.data();
  }
  return nullptr;
}

zx_status_t Device::DriverCompatibiltyTest() {
  thrd_t t;
  if (test_state() != TestStateMachine::kTestNotStarted) {
    return ZX_ERR_ALREADY_EXISTS;
  }
  auto cb = [](void* arg) -> int {
    auto dev = fbl::RefPtr(reinterpret_cast<Device*>(arg));
    return dev->RunCompatibilityTests();
  };
  int ret = thrd_create_with_name(&t, cb, this, "compatibility-tests-thread");
  if (ret != thrd_success) {
    LOGF(ERROR, "Failed to create thread for driver compatibility test '%s': %d",
         GetTestDriverName(), ret);
    if (test_reply_required_) {
      dh_send_complete_compatibility_tests(
          this, fuchsia_device_manager_CompatibilityTestStatus_ERR_INTERNAL);
    }
    return ZX_ERR_NO_RESOURCES;
  }
  thrd_detach(t);
  return ZX_OK;
}

#define TEST_LOGF(severity, message...) FX_LOGF(severity, "compatibility", message)

int Device::RunCompatibilityTests() {
  const char* test_driver_name = GetTestDriverName();
  TEST_LOGF(INFO, "Running test '%s'", test_driver_name);
  auto cleanup = fbl::MakeAutoCall([this]() {
    if (test_reply_required_) {
      dh_send_complete_compatibility_tests(this, test_status_);
    }
    test_event().reset();
    set_test_state(Device::TestStateMachine::kTestDone);
    set_test_reply_required(false);
  });
  // Device should be bound for test to work
  if (!(flags & DEV_CTX_BOUND) || children().is_empty()) {
    TEST_LOGF(ERROR, "[  FAILED  ] %s: Parent device not bound", test_driver_name);
    test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_BIND_NO_DDKADD;
    return ZX_ERR_BAD_STATE;
  }
  zx_status_t status = zx::event::create(0, &test_event());
  if (status != ZX_OK) {
    TEST_LOGF(ERROR, "[  FAILED  ] %s: Event creation failed, %s", test_driver_name,
              zx_status_get_string(status));
    test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_INTERNAL;
    return ZX_ERR_INTERNAL;
  }

  // Issue unbind on all its children.
  for (auto itr = children().begin(); itr != children().end();) {
    auto& child = *itr;
    itr++;
    this->set_test_state(Device::TestStateMachine::kTestUnbindSent);
    coordinator->ScheduleDriverHostRequestedRemove(fbl::RefPtr<Device>(&child),
                                                   true /* unbind_self */);
  }

  zx_signals_t observed = 0;
  // Now wait for the device to be removed.
  status =
      test_event().wait_one(TEST_REMOVE_DONE_SIGNAL, zx::deadline_after(test_time()), &observed);
  if (status != ZX_OK) {
    if (status == ZX_ERR_TIMED_OUT) {
      // The Remove did not complete.
      TEST_LOGF(ERROR,
                "[  FAILED  ] %s: Timed out waiting for device to be removed, check if"
                " device_remove() was called in the unbind routine of the driver",
                test_driver_name, status);
      test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_UNBIND_TIMEOUT;
    } else {
      TEST_LOGF(ERROR, "[  FAILED  ] %s: Error waiting for device to be removed: %s",
                test_driver_name, zx_status_get_string(status));
      test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_INTERNAL;
    }
    return ZX_ERR_INTERNAL;
  }
  this->set_test_state(Device::TestStateMachine::kTestBindSent);
  this->coordinator->HandleNewDevice(fbl::RefPtr(this));
  observed = 0;
  status = test_event().wait_one(TEST_BIND_DONE_SIGNAL, zx::deadline_after(test_time()), &observed);
  if (status != ZX_OK) {
    if (status == ZX_ERR_TIMED_OUT) {
      // The Bind did not complete.
      TEST_LOGF(ERROR,
                "[  FAILED  ] %s: Timed out waiting for driver to be bound, check if there"
                " is blocking IO in the driver's bind()",
                test_driver_name, status);
      test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_BIND_TIMEOUT;
    } else {
      TEST_LOGF(ERROR, "[  FAILED  ] %s: Error waiting for driver to be bound: %s",
                test_driver_name, zx_status_get_string(status));
      test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_INTERNAL;
    }
    return ZX_ERR_INTERNAL;
  }
  this->set_test_state(Device::TestStateMachine::kTestBindDone);
  if (this->children().is_empty()) {
    TEST_LOGF(
        ERROR,
        "[  FAILED  ] %s: Driver did not add a child device in bind(), check if it called DdkAdd()",
        test_driver_name);
    test_status_ = fuchsia_device_manager_CompatibilityTestStatus_ERR_BIND_NO_DDKADD;
    return -1;
  }
  TEST_LOGF(INFO, "[  PASSED  ] %s", test_driver_name);
  // TODO(ravoorir): Test Suspend and Resume hooks
  test_status_ = fuchsia_device_manager_CompatibilityTestStatus_OK;
  return ZX_OK;
}

#undef TEST_LOGF

void Device::AddDevice(::zx::channel coordinator, ::zx::channel device_controller_client,
                       ::fidl::VectorView<llcpp::fuchsia::device::manager::DeviceProperty> props,
                       ::fidl::StringView name_view, uint32_t protocol_id,
                       ::fidl::StringView driver_path_view, ::fidl::StringView args_view,
                       llcpp::fuchsia::device::manager::AddDeviceConfig device_add_config,
                       bool has_init, ::zx::vmo inspect, ::zx::channel client_remote,
                       AddDeviceCompleter::Sync& completer) {
  auto parent = fbl::RefPtr(this);
  fbl::StringPiece name(name_view.data(), name_view.size());
  fbl::StringPiece driver_path(driver_path_view.data(), driver_path_view.size());
  fbl::StringPiece args(args_view.data(), args_view.size());

  bool invisible = static_cast<bool>(device_add_config &
                                     llcpp::fuchsia::device::manager::AddDeviceConfig::INVISIBLE);
  bool skip_autobind = static_cast<bool>(
      device_add_config & llcpp::fuchsia::device::manager::AddDeviceConfig::SKIP_AUTOBIND);

  fbl::RefPtr<Device> device;
  zx_status_t status = parent->coordinator->AddDevice(
      parent, std::move(device_controller_client), std::move(coordinator), props.data(),
      props.count(), name, protocol_id, driver_path, args, invisible, skip_autobind, has_init,
      kEnableAlwaysInit, std::move(inspect), std::move(client_remote), &device);
  if (device != nullptr &&
      (device_add_config &
       llcpp::fuchsia::device::manager::AddDeviceConfig::ALLOW_MULTI_COMPOSITE)) {
    device->flags |= DEV_CTX_ALLOW_MULTI_COMPOSITE;
  }
  uint64_t local_id = device != nullptr ? device->local_id() : 0;
  llcpp::fuchsia::device::manager::Coordinator_AddDevice_Result response;
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    llcpp::fuchsia::device::manager::Coordinator_AddDevice_Response resp{.local_device_id =
                                                                             local_id};
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}

void Device::PublishMetadata(::fidl::StringView device_path, uint32_t key,
                             ::fidl::VectorView<uint8_t> data,
                             PublishMetadataCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  char path[fuchsia_device_manager_DEVICE_PATH_MAX + 1];
  ZX_ASSERT(device_path.size() <= fuchsia_device_manager_DEVICE_PATH_MAX);
  memcpy(path, device_path.data(), device_path.size());
  path[device_path.size()] = 0;
  zx_status_t status = dev->coordinator->PublishMetadata(dev, path, key, data.data(),
                                                         static_cast<uint32_t>(data.count()));
  llcpp::fuchsia::device::manager::Coordinator_PublishMetadata_Result response;
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_PublishMetadata_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}

void Device::ScheduleRemove(bool unbind_self, ScheduleRemoveCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);

  VLOGF(1, "Scheduling remove of device %p '%s'", dev.get(), dev->name().data());

  dev->coordinator->ScheduleDriverHostRequestedRemove(dev, unbind_self);
}

void Device::ScheduleUnbindChildren(ScheduleUnbindChildrenCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);

  VLOGF(1, "Scheduling unbind of children for device %p '%s'", dev.get(), dev->name().data());

  dev->coordinator->ScheduleDriverHostRequestedUnbindChildren(dev);
}

void Device::MakeVisible(MakeVisibleCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  llcpp::fuchsia::device::manager::Coordinator_MakeVisible_Result response;
  if (dev->coordinator->InSuspend()) {
    LOGF(ERROR, "'make-visible' is forbidden in suspend");
    zx_status_t status = ZX_ERR_BAD_STATE;
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }
  VLOGF(1, "'make-visible' device %p '%s'", dev.get(), dev->name().data());
  // TODO(teisenbe): MakeVisibile can return errors.  We should probably
  // act on it, but the existing code being migrated does not.
  dev->coordinator->MakeVisible(dev);
  fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_MakeVisible_Response> resp;
  response.set_response(fidl::unowned_ptr(&resp));
  completer.Reply(std::move(response));
}

void Device::BindDevice(::fidl::StringView driver_path_view, BindDeviceCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  fbl::StringPiece driver_path(driver_path_view.data(), driver_path_view.size());

  llcpp::fuchsia::device::manager::Coordinator_BindDevice_Result response;
  if (dev->coordinator->InSuspend()) {
    LOGF(ERROR, "'bind-device' is forbidden in suspend");
    zx_status_t status = ZX_ERR_BAD_STATE;
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }

  VLOGF(1, "'bind-device' device %p '%s'", dev.get(), dev->name().data());
  zx_status_t status = dev->coordinator->BindDevice(dev, driver_path, false /* new device */);
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_BindDevice_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}

void Device::GetTopologicalPath(GetTopologicalPathCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  char path[fuchsia_device_manager_DEVICE_PATH_MAX + 1];
  zx_status_t status;
  llcpp::fuchsia::device::manager::Coordinator_GetTopologicalPath_Result response;
  if ((status = dev->coordinator->GetTopologicalPath(dev, path, sizeof(path))) != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }
  auto path_view = ::fidl::unowned_str(path, strlen(path));
  llcpp::fuchsia::device::manager::Coordinator_GetTopologicalPath_Response resp{
      .path = std::move(path_view)};
  response.set_response(fidl::unowned_ptr(&resp));
  completer.Reply(std::move(response));
}

void Device::LoadFirmware(::fidl::StringView fw_path_view, LoadFirmwareCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);

  char fw_path[fuchsia_device_manager_DEVICE_PATH_MAX + 1];
  memcpy(fw_path, fw_path_view.data(), fw_path_view.size());
  fw_path[fw_path_view.size()] = 0;
  llcpp::fuchsia::device::manager::Coordinator_LoadFirmware_Result response;

  zx::vmo vmo;
  uint64_t size = 0;
  zx_status_t status;
  if ((status = dev->coordinator->LoadFirmware(dev, fw_path, &vmo, &size)) != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }

  llcpp::fuchsia::device::manager::Coordinator_LoadFirmware_Response resp{
      .vmo = std::move(vmo),
      .size = size,
  };
  response.set_response(fidl::unowned_ptr(&resp));
  completer.Reply(std::move(response));
}

void Device::GetMetadata(uint32_t key, GetMetadataCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  uint8_t data[fuchsia_device_manager_METADATA_BYTES_MAX];
  size_t actual = 0;
  llcpp::fuchsia::device::manager::Coordinator_GetMetadata_Result response;
  zx_status_t status = dev->coordinator->GetMetadata(dev, key, data, sizeof(data), &actual);
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }
  auto data_view = ::fidl::VectorView<uint8_t>(fidl::unowned_ptr(data), actual);
  llcpp::fuchsia::device::manager::Coordinator_GetMetadata_Response resp{.data =
                                                                             std::move(data_view)};
  response.set_response(fidl::unowned_ptr(&resp));
  completer.Reply(std::move(response));
}

void Device::GetMetadataSize(uint32_t key, GetMetadataSizeCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  size_t size;
  llcpp::fuchsia::device::manager::Coordinator_GetMetadataSize_Result response;
  zx_status_t status = dev->coordinator->GetMetadataSize(dev, key, &size);
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }
  llcpp::fuchsia::device::manager::Coordinator_GetMetadataSize_Response resp{.size = size};
  response.set_response(fidl::unowned_ptr(&resp));
  completer.Reply(std::move(response));
}

void Device::AddMetadata(uint32_t key, ::fidl::VectorView<uint8_t> data,
                         AddMetadataCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  zx_status_t status =
      dev->coordinator->AddMetadata(dev, key, data.data(), static_cast<uint32_t>(data.count()));
  llcpp::fuchsia::device::manager::Coordinator_AddMetadata_Result response;
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_AddMetadata_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}
void Device::RunCompatibilityTests(int64_t hook_wait_time,
                                   RunCompatibilityTestsCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  fbl::RefPtr<Device>& real_parent = dev;
  zx_status_t status = ZX_OK;
  if (dev->flags & DEV_CTX_PROXY) {
    real_parent = dev->parent();
  }
  zx::duration test_time = zx::nsec(hook_wait_time);
  real_parent->set_test_time(test_time);
  real_parent->set_test_reply_required(true);
  status = real_parent->DriverCompatibiltyTest();
  llcpp::fuchsia::device::manager::Coordinator_RunCompatibilityTests_Result response;
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_RunCompatibilityTests_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}

void Device::DirectoryWatch(uint32_t mask, uint32_t options, ::zx::channel watcher,
                            DirectoryWatchCompleter::Sync& completer) {
  llcpp::fuchsia::device::manager::Coordinator_DirectoryWatch_Result response;
  if (mask & (~fuchsia_io_WATCH_MASK_ALL) || options != 0) {
    zx_status_t status = ZX_ERR_INVALID_ARGS;
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
    return;
  }

  zx_status_t status = devfs_watch(this->self, std::move(watcher), mask);
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_DirectoryWatch_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}

void Device::AddCompositeDevice(
    ::fidl::StringView name_view,
    llcpp::fuchsia::device::manager::CompositeDeviceDescriptor comp_desc,
    AddCompositeDeviceCompleter::Sync& completer) {
  auto dev = fbl::RefPtr(this);
  fbl::StringPiece name(name_view.data(), name_view.size());
  zx_status_t status = this->coordinator->AddCompositeDevice(dev, name, std::move(comp_desc));
  llcpp::fuchsia::device::manager::Coordinator_AddCompositeDevice_Result response;
  if (status != ZX_OK) {
    response.set_err(fidl::unowned_ptr(&status));
    completer.Reply(std::move(response));
  } else {
    fidl::aligned<llcpp::fuchsia::device::manager::Coordinator_AddCompositeDevice_Response> resp;
    response.set_response(fidl::unowned_ptr(&resp));
    completer.Reply(std::move(response));
  }
}
