// Copyright 2016 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 <stdarg.h>
#include <stdio.h>
#include <zircon/compiler.h>
#include <zircon/device/vfs.h>

#include <utility>

#include <ddk/debug.h>
#include <ddk/device.h>

#include "devhost.h"
#include "scheduler_profile.h"

using namespace devmgr;

// These are the API entry-points from drivers
// They must take the devhost_api_lock before calling devhost_* internals
//
// Driver code MUST NOT directly call devhost_* APIs

// LibDriver Device Interface

#define ALLOWED_FLAGS                                                        \
  (DEVICE_ADD_NON_BINDABLE | DEVICE_ADD_INSTANCE | DEVICE_ADD_MUST_ISOLATE | \
   DEVICE_ADD_INVISIBLE | DEVICE_ADD_ALLOW_MULTI_COMPOSITE)

__EXPORT zx_status_t device_add_from_driver(zx_driver_t* drv, zx_device_t* parent,
                                            device_add_args_t* args, zx_device_t** out) {
  zx_status_t r;
  fbl::RefPtr<zx_device_t> dev;

  if (!parent) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::RefPtr<zx_device> parent_ref(parent);

  if (!args || args->version != DEVICE_ADD_ARGS_VERSION) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (!args->ops || args->ops->version != DEVICE_OPS_VERSION) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (args->flags & ~ALLOWED_FLAGS) {
    return ZX_ERR_INVALID_ARGS;
  }
  if ((args->flags & DEVICE_ADD_INSTANCE) &&
      (args->flags & (DEVICE_ADD_MUST_ISOLATE | DEVICE_ADD_INVISIBLE))) {
    return ZX_ERR_INVALID_ARGS;
  }

  // If the device will be added in the same devhost and visible,
  // we can connect the client immediately after adding the device.
  // Otherwise we will pass this channel to the devcoordinator via devhost_device_add.
  zx::channel client_remote(args->client_remote);

  {
    ApiAutoLock lock;
    r = devhost_device_create(drv, args->name, args->ctx, args->ops, &dev);
    if (r != ZX_OK) {
      return r;
    }
    if (args->proto_id) {
      dev->protocol_id = args->proto_id;
      dev->protocol_ops = args->proto_ops;
    }
    if (args->flags & DEVICE_ADD_NON_BINDABLE) {
      dev->flags |= DEV_FLAG_UNBINDABLE;
    }
    if (args->flags & DEVICE_ADD_INVISIBLE) {
      dev->flags |= DEV_FLAG_INVISIBLE;
    }
    if (args->flags & DEVICE_ADD_ALLOW_MULTI_COMPOSITE) {
      dev->flags |= DEV_FLAG_ALLOW_MULTI_COMPOSITE;
    }

    if (!args->power_states) {
      // TODO(fxb/34081): Remove when all drivers declare power states
      // Temporarily allocate working and non-working power states
      device_power_state_info_t power_states[2] = {};
      power_states[0].state_id = fuchsia_device_DevicePowerState_DEVICE_POWER_STATE_D0;
      power_states[1].state_id = fuchsia_device_DevicePowerState_DEVICE_POWER_STATE_D3COLD;
      r = dev->SetPowerStates(power_states, 2);
    } else {
      r = dev->SetPowerStates(args->power_states, args->power_state_count);
    }
    if (r != ZX_OK) {
      return r;
    }

    if (args->performance_states && (args->performance_state_count != 0)) {
      r = dev->SetPerformanceStates(args->performance_states, args->performance_state_count);
    } else {
      device_performance_state_info_t perf_power_states[1];
      perf_power_states[0].state_id = fuchsia_device_DEVICE_PERFORMANCE_STATE_P0;
      r = dev->SetPerformanceStates(perf_power_states, 1);
    }

    if (r != ZX_OK) {
      return r;
    }

    // Set default system to device power state mapping. This can be later
    // updated by the system power manager.
    zx_device::SystemPowerStateMapping states_mapping{};
    for (auto& entry : states_mapping) {
      entry.dev_state = ::llcpp::fuchsia::device::DevicePowerState::DEVICE_POWER_STATE_D3COLD;
      entry.wakeup_enable = false;
    }
    r = dev->SetSystemPowerStateMapping(states_mapping);
    if (r != ZX_OK) {
      return r;
    }

    // out must be set before calling devhost_device_add().
    // devhost_device_add() may result in child devices being created before it returns,
    // and those children may call ops on the device before device_add() returns.
    // This leaked-ref will be accounted below.
    if (out) {
      *out = dev.get();
    }

    if (args->flags & DEVICE_ADD_MUST_ISOLATE) {
      r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, args->proxy_args,
                             std::move(client_remote));
    } else if (args->flags & DEVICE_ADD_INSTANCE) {
      dev->flags |= DEV_FLAG_INSTANCE | DEV_FLAG_UNBINDABLE;
      r = devhost_device_add(dev, parent_ref, nullptr, 0, nullptr,
                             zx::channel() /* client_remote */);
    } else {
      bool pass_client_remote = args->flags & DEVICE_ADD_INVISIBLE;
      r = devhost_device_add(dev, parent_ref, args->props, args->prop_count, nullptr,
                             pass_client_remote ? std::move(client_remote) : zx::channel());
    }
    if (r != ZX_OK) {
      if (out) {
        *out = nullptr;
      }
      dev.reset();
    }
  }

  if (dev && client_remote.is_valid()) {
    // This needs to be called outside the ApiAutoLock, as device_open will be called
    devhost_device_connect(dev, ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE,
                           std::move(client_remote));

    // Leak the reference that was written to |out|, it will be recovered in device_remove().
    // For device instances we mimic the behavior of |open| by not leaking the reference,
    // effectively passing owenership to the new connection.
    if (!(args->flags & DEVICE_ADD_INSTANCE)) {
      __UNUSED auto ptr = fbl::ExportToRawPtr(&dev);
    }
  } else {
    // Leak the reference that was written to |out|, it will be recovered in device_remove().
    __UNUSED auto ptr = fbl::ExportToRawPtr(&dev);
  }

  return r;
}

__EXPORT void device_init_reply(zx_device_t* dev, zx_status_t status,
                                const device_init_reply_args_t* args) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  devhost_device_init_reply(dev_ref, status, args);
}

__EXPORT zx_status_t device_remove_deprecated(zx_device_t* dev) {
  ApiAutoLock lock;
  // The leaked reference in device_add_from_driver() will be recovered when
  // devhost_remove() completes. We can't drop it here as we may just be
  // scheduling a removal, and do not know when that will happen.
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  return devhost_device_remove_deprecated(dev_ref);
}

__EXPORT zx_status_t device_remove(zx_device_t* dev) { return device_remove_deprecated(dev); }

__EXPORT zx_status_t device_rebind(zx_device_t* dev) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  return devhost_device_rebind(dev_ref);
}

__EXPORT void device_make_visible(zx_device_t* dev, const device_make_visible_args_t* args) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  devhost_make_visible(dev_ref, args);
}

__EXPORT void device_async_remove(zx_device_t* dev) {
  ApiAutoLock lock;
  // The leaked reference in device_add_from_driver() will be recovered when
  // devhost_remove() completes. We can't drop it here as we are just
  // scheduling the removal, and do not know when that will happen.
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  devhost_device_remove(dev_ref, true /* unbind_self */);
}

__EXPORT void device_unbind_reply(zx_device_t* dev) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  devhost_device_unbind_reply(dev_ref);
}

__EXPORT void device_suspend_reply(zx_device_t* dev, zx_status_t status, uint8_t out_state) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  devhost_device_suspend_reply(dev_ref, status, out_state);
}

__EXPORT zx_status_t device_get_profile(zx_device_t* dev, uint32_t priority, const char* name,
                                        zx_handle_t* out_profile) {
  return devhost_get_scheduler_profile(priority, name, out_profile);
}

__EXPORT zx_status_t device_get_deadline_profile(zx_device_t* device, uint64_t capacity,
                                                 uint64_t deadline, uint64_t period,
                                                 const char* name, zx_handle_t* out_profile) {
  return devhost_get_scheduler_deadline_profile(capacity, deadline, period, name, out_profile);
}

__EXPORT const char* device_get_name(zx_device_t* dev) { return dev->name; }

__EXPORT zx_device_t* device_get_parent(zx_device_t* dev) {
  // The caller should not hold on to this past the lifetime of |dev|.
  return dev->parent.get();
}

struct GenericProtocol {
  void* ops;
  void* ctx;
};

__EXPORT zx_status_t device_get_protocol(const zx_device_t* dev, uint32_t proto_id, void* out) {
  auto proto = static_cast<GenericProtocol*>(out);
  if (dev->ops->get_protocol) {
    return dev->ops->get_protocol(dev->ctx, proto_id, out);
  }
  if ((proto_id == dev->protocol_id) && (dev->protocol_ops != nullptr)) {
    proto->ops = dev->protocol_ops;
    proto->ctx = dev->ctx;
    return ZX_OK;
  }
  return ZX_ERR_NOT_SUPPORTED;
}

__EXPORT void device_state_clr_set(zx_device_t* dev, zx_signals_t clearflag, zx_signals_t setflag) {
  dev->event.signal(clearflag, setflag);
}

__EXPORT zx_off_t device_get_size(zx_device_t* dev) { return dev->GetSizeOp(); }

// LibDriver Misc Interfaces

namespace devmgr {
extern zx_handle_t root_resource_handle;
}  // namespace devmgr

// Please do not use get_root_resource() in new code. See ZX-1467.
__EXPORT zx_handle_t get_root_resource() { return root_resource_handle; }

__EXPORT zx_status_t load_firmware(zx_device_t* dev, const char* path, zx_handle_t* fw,
                                   size_t* size) {
  ApiAutoLock lock;
  fbl::RefPtr<zx_device_t> dev_ref(dev);
  // TODO(bwb): Can we propogate zx::vmo further up?
  return devhost_load_firmware(dev_ref, path, fw, size);
}

// Interface Used by DevHost RPC Layer

zx_status_t device_bind(const fbl::RefPtr<zx_device_t>& dev, const char* drv_libname) {
  ApiAutoLock lock;
  return devhost_device_bind(dev, drv_libname);
}

zx_status_t device_unbind(const fbl::RefPtr<zx_device_t>& dev) {
  ApiAutoLock lock;
  return devhost_device_unbind(dev);
}

zx_status_t device_schedule_remove(const fbl::RefPtr<zx_device_t>& dev, bool unbind_self) {
  ApiAutoLock lock;
  return devhost_schedule_remove(dev, unbind_self);
}

zx_status_t device_run_compatibility_tests(const fbl::RefPtr<zx_device_t>& dev,
                                           int64_t hook_wait_time) {
  ApiAutoLock lock;
  return devhost_device_run_compatibility_tests(dev, hook_wait_time);
}

zx_status_t device_open(const fbl::RefPtr<zx_device_t>& dev, fbl::RefPtr<zx_device_t>* out,
                        uint32_t flags) {
  ApiAutoLock lock;
  return devhost_device_open(dev, out, flags);
}

// This function is intended to consume the reference produced by device_open()
zx_status_t device_close(fbl::RefPtr<zx_device_t> dev, uint32_t flags) {
  ApiAutoLock lock;
  return devhost_device_close(std::move(dev), flags);
}

__EXPORT zx_status_t device_get_metadata(zx_device_t* dev, uint32_t type, void* buf, size_t buflen,
                                         size_t* actual) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_get_metadata(dev_ref, type, buf, buflen, actual);
}

__EXPORT zx_status_t device_get_metadata_size(zx_device_t* dev, uint32_t type, size_t* out_size) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_get_metadata_size(dev_ref, type, out_size);
}

__EXPORT zx_status_t device_add_metadata(zx_device_t* dev, uint32_t type, const void* data,
                                         size_t length) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_add_metadata(dev_ref, type, data, length);
}

__EXPORT zx_status_t device_publish_metadata(zx_device_t* dev, const char* path, uint32_t type,
                                             const void* data, size_t length) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_publish_metadata(dev_ref, path, type, data, length);
}

__EXPORT zx_status_t device_add_composite(zx_device_t* dev, const char* name,
                                          const composite_device_desc_t* comp_desc) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_device_add_composite(dev_ref, name, comp_desc);
}

__EXPORT zx_status_t device_schedule_work(zx_device_t* dev, void (*callback)(void*), void* cookie) {
  ApiAutoLock lock;
  auto dev_ref = fbl::RefPtr(dev);
  return devhost_schedule_work(dev_ref, callback, cookie);
}
