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

#include <lib/inspect/cpp/inspect.h>
#include <zircon/status.h>

#include "host.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/device_wrapper.h"

namespace bthost {
namespace {

// bt-gatt-svc devices are published for HID-over-GATT only.
constexpr bt::UUID kHogUuid(uint16_t{0x1812});

const char* kDeviceName = "bt_host";

}  // namespace

HostDevice::HostDevice(zx_device_t* parent)
    : HostDeviceType(parent), loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
  ZX_DEBUG_ASSERT(parent);

  inspect_.GetRoot().CreateString("name", kDeviceName, &inspect_);
}

zx_status_t HostDevice::Bind() {
  bt_log(DEBUG, "bt-host", "bind");

  std::lock_guard<std::mutex> lock(mtx_);

  zx_status_t status = device_get_protocol(parent_, ZX_PROTOCOL_BT_HCI, &hci_proto_);
  if (status != ZX_OK) {
    bt_log(ERROR, "bt-host", "failed to obtain bt-hci protocol ops: %s",
           zx_status_get_string(status));
    return status;
  }

  if (!hci_proto_.ops) {
    bt_log(ERROR, "bt-host", "bt-hci device ops required!");
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (!hci_proto_.ops->open_command_channel) {
    bt_log(ERROR, "bt-host", "bt-hci op required: open_command_channel");
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (!hci_proto_.ops->open_acl_data_channel) {
    bt_log(ERROR, "bt-host", "bt-hci op required: open_acl_data_channel");
    return ZX_ERR_NOT_SUPPORTED;
  }

  if (!hci_proto_.ops->open_snoop_channel) {
    bt_log(ERROR, "bt-host", "bt-hci op required: open_snoop_channel");
    return ZX_ERR_NOT_SUPPORTED;
  }

  device_add_args_t args = {
      .version = DEVICE_ADD_ARGS_VERSION,
      .proto_id = ZX_PROTOCOL_BT_HOST,
      .flags = DEVICE_ADD_NON_BINDABLE,
      .inspect_vmo = inspect_.DuplicateVmo().release(),
  };
  status = DdkAdd("bt_host", args);

  if (status != ZX_OK) {
    bt_log(ERROR, "bt-host", "Failed to publish device: %s", zx_status_get_string(status));
    return status;
  }

  return status;
  // Since we define an init hook, Init will be called by the DDK after this method finishes.
}

void HostDevice::DdkInit(ddk::InitTxn txn) {
  bt_log(DEBUG, "bt-host", "init");

  std::lock_guard<std::mutex> lock(mtx_);

  auto vendor_result = GetVendorProtocol();
  if (vendor_result.is_ok()) {
    vendor_proto_ = vendor_result.value();
  } else {
    bt_log(WARN, "bt-host", "failed to obtain bt-vendor protocol ops: %s",
           zx_status_get_string(vendor_result.error()));
  }

  loop_.StartThread("bt-host (gap)");

  // Send the bootstrap message to Host. The Host object can only be accessed on
  // the Host thread.
  async::PostTask(loop_.dispatcher(), [this, txn{std::move(txn)}]() mutable {
    bt_log(TRACE, "bt-host", "host thread start");

    std::lock_guard<std::mutex> lock(mtx_);
    host_ = fxl::MakeRefCounted<Host>(hci_proto_, vendor_proto_);
    bt_host_node_ = inspect_.GetRoot().CreateChild("bt-host");
    host_->Initialize(bt_host_node_, [this, txn{std::move(txn)}](bool success) mutable {
      std::lock_guard<std::mutex> lock(mtx_);

      // host_ must be defined here as Bind() must have been called and the runloop has not
      // yet been been drained in Unbind().
      ZX_DEBUG_ASSERT(host_);

      if (!success) {
        bt_log(ERROR, "bt-host", "failed to initialize adapter; cleaning up");
        txn.Reply(ZX_ERR_INTERNAL);
        // DDK will call Unbind here to clean up.
      } else {
        bt_log(DEBUG, "bt-host", "adapter initialized; make device visible");
        host_->gatt()->RegisterRemoteServiceWatcher(
            fit::bind_member(this, &HostDevice::OnRemoteGattServiceAdded));
        txn.Reply(ZX_OK);
        return;
      }
    });
  });
}

void HostDevice::DdkUnbind(ddk::UnbindTxn txn) {
  bt_log(DEBUG, "bt-host", "unbind");

  {
    std::lock_guard<std::mutex> lock(mtx_);

    // Do this immediately to stop receiving new service callbacks.
    bt_log(TRACE, "bt-host", "removing GATT service watcher");
    ignore_gatt_services_ = true;

    async::PostTask(loop_.dispatcher(), [this] {
      std::lock_guard<std::mutex> lock(mtx_);
      host_->ShutDown();
      host_ = nullptr;
      loop_.Quit();
    });

    // Don't hold lock waiting on the loop to terminate.
  }

  // Make sure that the ShutDown task runs before this returns.
  bt_log(TRACE, "bt-host", "waiting for shut down tasks to complete");
  loop_.JoinThreads();

  txn.Reply();

  bt_log(DEBUG, "bt-host", "GAP has been shut down");
}

void HostDevice::DdkRelease() {
  bt_log(DEBUG, "bt-host", "release");
  delete this;
}

// Route ddk fidl messages to the dispatcher function
zx_status_t HostDevice::DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn) {
  // Struct containing function pointers for all fidl ops to be dispatched on
  static constexpr fuchsia_hardware_bluetooth_Host_ops_t fidl_ops = {
      .Open = [](void* ctx, zx_handle_t channel) {
        return static_cast<HostDevice*>(ctx)->OpenHostChannel(zx::channel(channel));
      }};

  bt_log(DEBUG, "bt-host", "fidl message");
  return fuchsia_hardware_bluetooth_Host_dispatch(this, txn, msg, &fidl_ops);
}

zx_status_t HostDevice::OpenHostChannel(zx::channel channel) {
  ZX_DEBUG_ASSERT(channel);
  std::lock_guard<std::mutex> lock(mtx_);

  // This is called from the fidl operation OpenChannelOp.  No fidl calls will be delivered to the
  // driver before host_ is initialized by Init(), and no fidl calls
  // will be delivered after the DDK calls Unbind() and host_ is removed.
  ZX_DEBUG_ASSERT(host_);

  // Tell Host to start processing messages on this handle.
  async::PostTask(loop_.dispatcher(), [host = host_, chan = std::move(channel)]() mutable {
    host->BindHostInterface(std::move(chan));
  });

  return ZX_OK;
}

void HostDevice::OnRemoteGattServiceAdded(bt::gatt::PeerId peer_id,
                                          fbl::RefPtr<bt::gatt::RemoteService> service) {
  TRACE_DURATION("bluetooth", "HostDevice::OnRemoteGattServiceAdded");

  // Only publish children for HID-over-GATT.
  if (service->uuid() != kHogUuid) {
    return;
  }

  std::lock_guard<std::mutex> lock(mtx_);

  if (ignore_gatt_services_) {
    return;
  }

  // This is run on the host event loop. Bind(), Init() and Unbind() should maintain the invariant
  // that  host_ are initialized when the event loop is running.
  ZX_DEBUG_ASSERT(host_);

  __UNUSED zx_status_t status = GattRemoteServiceDevice::Publish(zxdev(), peer_id, service);
}

fit::result<bt_vendor_protocol_t, zx_status_t> HostDevice::GetVendorProtocol() {
  bt_vendor_protocol_t vendor_proto = {};
  zx_status_t status = device_get_protocol(parent_, ZX_PROTOCOL_BT_VENDOR, &vendor_proto);
  if (status != ZX_OK) {
    return fit::error(status);
  }

  if (!vendor_proto.ops) {
    bt_log(WARN, "bt-host", "bt-vendor device ops required");
    return fit::error(ZX_ERR_NOT_SUPPORTED);
  }

  if (!vendor_proto.ops->get_features) {
    bt_log(WARN, "bt-host", "bt-vendor op required: get_features");
    return fit::error(ZX_ERR_NOT_SUPPORTED);
  }

  if (!vendor_proto.ops->encode_command) {
    bt_log(WARN, "bt-host", "bt-vendor op required: encode_command");
    return fit::error(ZX_ERR_NOT_SUPPORTED);
  }

  return fit::ok(vendor_proto);
}

}  // namespace bthost
