// Copyright 2020 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 "src/devices/bin/driver_manager/inspect.h"

#include <lib/ddk/driver.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/inspect/component/cpp/service.h>

#include <utility>

#include "src/storage/lib/vfs/cpp/service.h"
#include "src/storage/lib/vfs/cpp/vfs_types.h"
#include "src/storage/lib/vfs/cpp/vnode.h"

namespace driver_manager {
namespace {
const char* BindParamName(uint32_t param_num) {
  switch (param_num) {
    case BIND_FLAGS:
      return "Flags";
    case BIND_PROTOCOL:
      return "Protocol";
    case BIND_AUTOBIND:
      return "Autobind";
    case BIND_PCI_VID:
      return "PCI.VID";
    case BIND_PCI_DID:
      return "PCI.DID";
    case BIND_PCI_CLASS:
      return "PCI.Class";
    case BIND_PCI_SUBCLASS:
      return "PCI.Subclass";
    case BIND_PCI_INTERFACE:
      return "PCI.Interface";
    case BIND_PCI_REVISION:
      return "PCI.Revision";
    case BIND_PCI_TOPO:
      return "PCI.Topology";
    case BIND_USB_VID:
      return "USB.VID";
    case BIND_USB_PID:
      return "USB.PID";
    case BIND_USB_CLASS:
      return "USB.Class";
    case BIND_USB_SUBCLASS:
      return "USB.Subclass";
    case BIND_USB_PROTOCOL:
      return "USB.Protocol";
    case BIND_PLATFORM_DEV_VID:
      return "PlatDev.VID";
    case BIND_PLATFORM_DEV_PID:
      return "PlatDev.PID";
    case BIND_PLATFORM_DEV_DID:
      return "PlatDev.DID";
    case BIND_ACPI_BUS_TYPE:
      return "ACPI.BusType";
    case BIND_IHDA_CODEC_VID:
      return "IHDA.Codec.VID";
    case BIND_IHDA_CODEC_DID:
      return "IHDA.Codec.DID";
    case BIND_IHDA_CODEC_MAJOR_REV:
      return "IHDACodec.MajorRev";
    case BIND_IHDA_CODEC_MINOR_REV:
      return "IHDACodec.MinorRev";
    case BIND_IHDA_CODEC_VENDOR_REV:
      return "IHDACodec.VendorRev";
    case BIND_IHDA_CODEC_VENDOR_STEP:
      return "IHDACodec.VendorStep";
    default:
      return NULL;
  }
}
}  // namespace

zx::result<InspectDevfs> InspectDevfs::Create(async_dispatcher_t* dispatcher) {
  InspectDevfs devfs(dispatcher);

  return zx::ok(std::move(devfs));
}

zx::result<std::string> InspectDevfs::Publish(const char* name, zx::vmo vmo) {
  if (dispatcher_ == nullptr) {
    return zx::error(ZX_ERR_INVALID_ARGS);
  }

  std::string inspect_name = "driver-" + std::to_string(InspectDevfs::inspect_dev_counter_++) +
                             (name != nullptr ? "-" + std::string{name} : "");

  // TODO(b/324637276): this is the export point for duplicated data from driver components.
  inspect::PublishVmo(dispatcher_, std::move(vmo), {.tree_name = inspect_name});

  return zx::ok(std::move(inspect_name));
}

InspectManager::InspectManager(async_dispatcher_t* dispatcher) : inspector_(dispatcher, {}) {
  zx::result devfs = InspectDevfs::Create(dispatcher);
  ZX_ASSERT(devfs.is_ok());
  info_ = fbl::MakeRefCounted<Info>(root_node(), std::move(devfs.value()));
}

DeviceInspect InspectManager::CreateDevice(std::string name, zx::vmo vmo, uint32_t protocol_id) {
  return DeviceInspect(info_, std::move(name), std::move(vmo), protocol_id);
}

DeviceInspect::DeviceInspect(fbl::RefPtr<InspectManager::Info> info, std::string name, zx::vmo vmo,
                             uint32_t protocol_id)
    : info_(std::move(info)), protocol_id_(protocol_id), name_(std::move(name)) {
  // Devices are sometimes passed bogus handles. Fun!
  if (vmo.is_valid()) {
    dev_vmo_.emplace(std::move(vmo));
  }
  device_node_ = info_->devices.CreateChild(name_);
  // Increment device count.
  info_->device_count.Add(1);
}

DeviceInspect::~DeviceInspect() {
  if (info_) {
    // Decrement device count.
    info_->device_count.Subtract(1);
  }
}

DeviceInspect DeviceInspect::CreateChild(std::string name, zx::vmo vmo, uint32_t protocol_id) {
  return DeviceInspect(info_, std::move(name), std::move(vmo), protocol_id);
}

zx::result<> DeviceInspect::Publish() {
  if (!dev_vmo_.has_value()) {
    return zx::ok();
  }

  zx::result link_name = info_->devfs.Publish(name_.c_str(), std::move(*dev_vmo_));
  dev_vmo_.reset();
  if (link_name.is_error()) {
    return link_name.take_error();
  }

  link_name_ = link_name.value();
  return zx::ok();
}

void DeviceInspect::SetStaticValues(const std::string& topological_path, uint32_t protocol_id,
                                    const std::string& type,
                                    const cpp20::span<const zx_device_prop_t>& properties,
                                    const std::string& driver_url) {
  protocol_id_ = protocol_id;
  device_node_.CreateString("topological_path", topological_path, &static_values_);
  device_node_.CreateUint("protocol_id", protocol_id, &static_values_);
  device_node_.CreateString("type", type, &static_values_);
  device_node_.CreateString("driver", driver_url, &static_values_);

  inspect::Node properties_array;

  // Add a node only if there are any `props`
  if (!properties.empty()) {
    properties_array = device_node_.CreateChild("properties");
  }

  for (uint32_t i = 0; i < properties.size(); ++i) {
    const zx_device_prop_t* p = &properties[i];
    const char* param_name = BindParamName(p->id);
    auto property = properties_array.CreateChild(std::to_string(i));
    property.CreateUint("value", p->value, &static_values_);
    if (param_name) {
      property.CreateString("id", param_name, &static_values_);
    } else {
      property.CreateString("id", std::to_string(p->id), &static_values_);
    }
    static_values_.emplace(std::move(property));
  }

  // Place the node into value list as props will not change in the lifetime of the device.
  if (!properties.empty()) {
    static_values_.emplace(std::move(properties_array));
  }
}

}  // namespace driver_manager
