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

#ifndef SRC_DEVICES_BIN_DRIVER_HOST_ZX_DRIVER_H_
#define SRC_DEVICES_BIN_DRIVER_HOST_ZX_DRIVER_H_

#include <fuchsia/device/manager/llcpp/fidl.h>
#include <lib/fidl/llcpp/client.h>
#include <zircon/types.h>

#include <fbl/intrusive_double_list.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>

class DriverInspect;
typedef struct fx_logger fx_logger_t;

namespace internal {

struct BindContext {
  fbl::RefPtr<zx_device_t> parent;
  fbl::RefPtr<zx_device_t> child;
};

struct CreationContext {
  fbl::RefPtr<zx_device_t> parent;
  fbl::RefPtr<zx_device_t> child;
  zx::unowned_channel device_controller_rpc;
  llcpp::fuchsia::device::manager::Coordinator::ClientImpl* coordinator_client;
};

void set_bind_context(internal::BindContext* ctx);
void set_creation_context(internal::CreationContext* ctx);

}  // namespace internal

// Note that this must be a struct to match the public opaque declaration.
struct zx_driver : fbl::DoublyLinkedListable<fbl::RefPtr<zx_driver>>, fbl::RefCounted<zx_driver> {
  // |drivers| should outlive zx_driver struct
  static zx_status_t Create(std::string_view libname, InspectNodeCollection& drivers,
                            fbl::RefPtr<zx_driver>* out_driver);

  ~zx_driver();

  const char* name() const { return name_; }

  zx_driver_rec_t* driver_rec() const { return driver_rec_; }

  zx_status_t status() const { return status_; }

  const fbl::String& libname() const { return libname_; }

  void set_name(const char* name) {
    name_ = name;
    inspect_.set_name(name);
  }

  void set_driver_rec(zx_driver_rec_t* driver_rec) {
    driver_rec_ = driver_rec;
    inspect_.set_driver_rec(driver_rec);
  }

  void set_ops(const zx_driver_ops_t* ops) {
    ops_ = ops;
    inspect_.set_ops(ops);
  }

  void set_status(zx_status_t status) {
    status_ = status;
    inspect_.set_status(status);
  }

  fx_logger_t* logger() const { return logger_; }

  DriverInspect& inspect() { return inspect_; }

  // Interface to |ops|. These names contain Op in order to not
  // collide with e.g. RefPtr names.

  bool has_init_op() const { return ops_->init != nullptr; }

  bool has_bind_op() const { return ops_->bind != nullptr; }

  bool has_create_op() const { return ops_->create != nullptr; }

  bool has_run_unit_tests_op() const { return ops_->run_unit_tests != nullptr; }

  zx_status_t InitOp() { return ops_->init(&ctx_); }

  zx_status_t BindOp(internal::BindContext* bind_context,
                     const fbl::RefPtr<zx_device_t>& device) const {
    fbl::StringBuffer<32> trace_label;
    trace_label.AppendPrintf("%s:bind", name_);
    TRACE_DURATION("driver_host:driver-hooks", trace_label.data());

    internal::set_bind_context(bind_context);
    auto status = ops_->bind(ctx_, device.get());
    internal::set_bind_context(nullptr);
    return status;
  }

  zx_status_t CreateOp(internal::CreationContext* creation_context,
                       const fbl::RefPtr<zx_device_t>& parent, const char* name, const char* args,
                       zx_handle_t rpc_channel) const {
    internal::set_creation_context(creation_context);
    auto status = ops_->create(ctx_, parent.get(), name, args, rpc_channel);
    internal::set_creation_context(nullptr);
    return status;
  }

  void ReleaseOp() const {
    // TODO(kulakowski/teisenbe) Consider poisoning the ops_ table on release.
    ops_->release(ctx_);
  }

  bool RunUnitTestsOp(const fbl::RefPtr<zx_device_t>& parent, zx::channel test_output) const {
    return ops_->run_unit_tests(ctx_, parent.get(), test_output.release());
  }

 private:
  friend std::unique_ptr<zx_driver> std::make_unique<zx_driver>();
  zx_driver(fx_logger_t* logger, std::string_view libname, InspectNodeCollection& drivers);

  const char* name_ = nullptr;
  zx_driver_rec_t* driver_rec_ = nullptr;
  const zx_driver_ops_t* ops_ = nullptr;
  void* ctx_ = nullptr;

  fx_logger_t* logger_;
  fbl::String libname_;
  zx_status_t status_ = ZX_OK;

  DriverInspect inspect_;
};

#endif  // SRC_DEVICES_BIN_DRIVER_HOST_ZX_DRIVER_H_
