// Copyright 2022 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 "adb-function.h"

#include <lib/driver/compat/cpp/compat.h>
#include <lib/driver/logging/cpp/structured_logger.h>
#include <lib/zx/vmar.h>
#include <zircon/assert.h>

#include <cstdint>
#include <mutex>
#include <optional>

#include <usb/peripheral.h>
#include <usb/request-cpp.h>

#include "zircon/status.h"

namespace usb_adb_function {

namespace {

// CompleterType follows fidl::internal::WireCompleter<RequestType>::Async
template <typename CompleterType>
void CompleteTxn(CompleterType& completer, zx_status_t status) {
  if (status == ZX_OK) {
    completer.Reply(fit::ok());
  } else {
    completer.Reply(fit::error(status));
  }
}

}  // namespace

void UsbAdbDevice::StartAdb(StartAdbRequestView request, StartAdbCompleter::Sync& completer) {
  std::lock_guard<async::sequence_checker> _(checker_);

  if (adb_binding_.has_value()) {
    zxlogf(WARNING, "ADB already connected");
    completer.ReplyError(ZX_ERR_ALREADY_BOUND);
    return;
  }

  switch (state_) {
    case State::kStoppingUsb:
      zxlogf(WARNING, "ADB connected while stopping");
      completer.ReplyError(ZX_ERR_BAD_STATE);
      return;
    case State::kOnline:
      // We're already online, so send the status change immediately.
      if (auto result =
              fidl::WireSendEvent(request->interface)->OnStatusChanged(fadb::StatusFlags::kOnline);
          !result.ok()) {
        zxlogf(ERROR, "Could not call UsbAdbImpl.OnStatusChanged.");
      }
      break;
    case State::kAwaitingUsbConnection:
      break;
  }
  zxlogf(INFO, "ADB client connected");

  adb_binding_.emplace(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                       std::move(request->interface), this, [this](fidl::UnbindInfo info) {
                         std::lock_guard<async::sequence_checker> _(checker_);
                         zxlogf(INFO, "Device closed with reason '%s'",
                                info.FormatDescription().c_str());
                         ResetOrStopUsb();
                       });
  completer.ReplySuccess();
}

void UsbAdbDevice::StopAdb(StopAdbCompleter::Sync& completer) {
  zxlogf(INFO, "ADB client requested disconnect.");

  std::lock_guard<async::sequence_checker> _(checker_);
  stop_completers_.push_back(completer.ToAsync());
  ResetOrStopUsb();
}

void UsbAdbDevice::ResetOrStopUsb() {
  switch (state_) {
    case State::kStoppingUsb:
      zxlogf(INFO, "Stop requested, but already stopping");
      return;
    case State::kOnline:
      zxlogf(INFO, "Stopping USB");
      break;
    case State::kAwaitingUsbConnection:
      zxlogf(INFO, "Stop requested during USB startup");
      break;
  }

  // Purge any requests from internal queues.
  // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
  zxlogf(INFO, "rx_requests: %ld", rx_requests_.size());
  while (!rx_requests_.empty()) {
    rx_requests_.front().Reply(fit::error(ZX_ERR_BAD_STATE));
    rx_requests_.pop();
  }
  // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
  zxlogf(INFO, "pending_replies: %ld", pending_replies_.size());
  while (!pending_replies_.empty()) {
    bulk_out_ep_.PutRequest(
        usb::FidlRequest(std::move(pending_replies_.front().request().value())));
    pending_replies_.pop();
  }
  // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
  zxlogf(INFO, "tx_pending_reqs: %ld", tx_pending_reqs_.size());
  while (!tx_pending_reqs_.empty()) {
    CompleteTxn(tx_pending_reqs_.front().completer, ZX_ERR_CANCELED);
    tx_pending_reqs_.pop();
  }

  // Disconnect USB.
  // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
  zxlogf(INFO, "Disconnecting from USB with SetInterface(nullptr, nullptr)");
  zx_status_t status = function_.SetInterface(nullptr, nullptr);
  if (status != ZX_OK) {
    ZX_PANIC("SetInterface failed: %s", zx_status_get_string(status));
  }

  zxlogf(INFO, "state_ = State::kStoppingUsb");
  state_ = State::kStoppingUsb;

  CheckUsbStopComplete();
}

void UsbAdbDevice::SendQueued() {
  if (state_ != State::kOnline) {
    ZX_PANIC("Unexpected state: %d", state_);
  }
  while (SendQueuedOnce()) {
  }
}

// Returns true if any progress was made. Returns false if we didn't send
// anything, and therefore calling this again won't be useful until something
// changes.
bool UsbAdbDevice::SendQueuedOnce() {
  if (tx_pending_reqs_.empty()) {
    return false;
  }

  auto& current = tx_pending_reqs_.front();
  std::vector<fuchsia_hardware_usb_request::Request> requests;
  while (current.start < current.request.data().size()) {
    auto req = bulk_in_ep_.GetRequest();
    if (!req) {
      break;
    }
    req->clear_buffers();

    size_t to_copy = std::min(current.request.data().size() - current.start, kVmoDataSize);
    auto actual = req->CopyTo(0, current.request.data().data() + current.start, to_copy,
                              bulk_in_ep_.GetMapped());
    size_t actual_total = 0;
    for (size_t i = 0; i < actual.size(); i++) {
      // Fill in size of data.
      (*req)->data()->at(i).size(actual[i]);
      actual_total += actual[i];
    }
    auto status = req->CacheFlush(bulk_in_ep_.GetMapped());
    if (status != ZX_OK) {
      zxlogf(ERROR, "Cache flush failed %s", zx_status_get_string(status));
    }

    requests.emplace_back(req->take_request());
    current.start += actual_total;
  }

  if (requests.empty()) {
    return false;
  }
  auto result = bulk_in_ep_->QueueRequests(std::move(requests));
  if (result.is_error()) {
    zxlogf(ERROR, "Failed to QueueRequests %s", result.error_value().FormatDescription().c_str());
  }

  if (current.start == current.request.data().size()) {
    CompleteTxn(current.completer, ZX_OK);
    tx_pending_reqs_.pop();
  }

  return true;
}

void UsbAdbDevice::ReceiveQueued() {
  if (state_ != State::kOnline) {
    ZX_PANIC("Unexpected state: %d", state_);
  }
  while (ReceiveQueuedOnce()) {
  }
}

bool UsbAdbDevice::ReceiveQueuedOnce() {
  if (pending_replies_.empty() || rx_requests_.empty()) {
    return false;
  }

  auto completion = std::move(pending_replies_.front());
  pending_replies_.pop();

  auto req = usb::FidlRequest(std::move(completion.request().value()));

  if (*completion.status() != ZX_OK) {
    zxlogf(ERROR, "RxComplete called with error %s.", zx_status_get_string(*completion.status()));
    rx_requests_.front().Reply(fit::error(ZX_ERR_INTERNAL));
  } else {
    // This should always be true because when we registered VMOs, we only registered one per
    // request.
    ZX_ASSERT(req->data()->size() == 1);
    auto addr = bulk_out_ep_.GetMappedAddr(req.request(), 0);
    if (!addr.has_value()) {
      zxlogf(ERROR, "Failed to get mapped");
      rx_requests_.front().Reply(fit::error(ZX_ERR_INTERNAL));
    } else {
      auto status = req.CacheFlushInvalidate(bulk_out_ep_.GetMapped());
      if (status != ZX_OK) {
        zxlogf(ERROR, "Cache flush and invalidate failed %s", zx_status_get_string(status));
      }
      rx_requests_.front().Reply(fit::ok(
          std::vector<uint8_t>(reinterpret_cast<uint8_t*>(*addr),
                               reinterpret_cast<uint8_t*>(*addr) + *completion.transfer_size())));
    }
  }
  rx_requests_.pop();

  req.reset_buffers(bulk_out_ep_.GetMapped());

  std::vector<fuchsia_hardware_usb_request::Request> requests;
  requests.emplace_back(req.take_request());
  auto result = bulk_out_ep_->QueueRequests(std::move(requests));
  if (result.is_error()) {
    zxlogf(ERROR, "Failed to QueueRequests %s", result.error_value().FormatDescription().c_str());
  }

  return true;
}

void UsbAdbDevice::QueueTx(QueueTxRequest& request, QueueTxCompleter::Sync& completer) {
  std::lock_guard<async::sequence_checker> _(checker_);
  size_t length = request.data().size();
  if (length == 0) {
    zxlogf(INFO, "Invalid argument - Length = 0");
    completer.Reply(fit::error(ZX_ERR_INVALID_ARGS));
    return;
  }

  switch (state_) {
    case State::kStoppingUsb:
      // Return early during shutdown.
      completer.Reply(fit::error(ZX_ERR_BAD_STATE));
      return;
    case State::kOnline:
    case State::kAwaitingUsbConnection:
      tx_pending_reqs_.emplace(
          txn_req_t{.request = std::move(request), .start = 0, .completer = completer.ToAsync()});
      SendQueued();
  }
}

void UsbAdbDevice::Receive(ReceiveCompleter::Sync& completer) {
  std::lock_guard<async::sequence_checker> _(checker_);
  switch (state_) {
    case State::kStoppingUsb:
      // Return early during shutdown.
      completer.Reply(fit::error(ZX_ERR_BAD_STATE));
      return;
    case State::kAwaitingUsbConnection:
      rx_requests_.emplace(completer.ToAsync());
      break;
    case State::kOnline:
      rx_requests_.emplace(completer.ToAsync());
      ReceiveQueued();
      break;
  }
}

void UsbAdbDevice::RxComplete(fendpoint::Completion completion) {
  // This should always be true because when we registered VMOs, we only registered one per request.
  ZX_ASSERT(completion.request()->data()->size() == 1);

  switch (state_) {
    case State::kAwaitingUsbConnection:
      ZX_PANIC("Completion arrived before we sent any requests?");
    case State::kStoppingUsb:
      bulk_out_ep_.PutRequest(usb::FidlRequest(std::move(completion.request().value())));
      CheckUsbStopComplete();
      return;
    case State::kOnline:
      pending_replies_.push(std::move(completion));
      ReceiveQueued();
      return;
  }
}

void UsbAdbDevice::TxComplete(fendpoint::Completion completion) {
  switch (state_) {
    case State::kAwaitingUsbConnection:
      ZX_PANIC("Completion arrived before we sent any requests?");
    case State::kStoppingUsb:
      bulk_in_ep_.PutRequest(usb::FidlRequest(std::move(completion.request().value())));
      CheckUsbStopComplete();
      return;
    case State::kOnline:
      bulk_in_ep_.PutRequest(usb::FidlRequest(std::move(completion.request().value())));

      // Do not queue requests if status is ZX_ERR_IO_NOT_PRESENT, as the underlying connection
      // could be disconnected or USB_RESET is being processed. Calling adb_send_locked in such
      // scenario will deadlock and crash the driver (see https://fxbug.dev/42174506).
      if (*completion.status() != ZX_ERR_IO_NOT_PRESENT) {
        SendQueued();
      }
      return;
  }
}

void UsbAdbDevice::RxCompleteCallback(fendpoint::Completion completion) {
  async::PostTask(dispatcher(), [this, completion = std::move(completion)]() mutable {
    std::lock_guard<async::sequence_checker> _(checker_);
    RxComplete(std::move(completion));
  });
}

void UsbAdbDevice::TxCompleteCallback(fendpoint::Completion completion) {
  async::PostTask(dispatcher(), [this, completion = std::move(completion)]() mutable {
    std::lock_guard<async::sequence_checker> _(checker_);
    TxComplete(std::move(completion));
  });
}

size_t UsbAdbDevice::UsbFunctionInterfaceGetDescriptorsSize() { return sizeof(descriptors_); }

void UsbAdbDevice::UsbFunctionInterfaceGetDescriptors(uint8_t* buffer, size_t buffer_size,
                                                      size_t* out_actual) {
  const size_t length = std::min(sizeof(descriptors_), buffer_size);
  std::memcpy(buffer, &descriptors_, length);
  *out_actual = length;
}

zx_status_t UsbAdbDevice::UsbFunctionInterfaceControl(const usb_setup_t* setup,
                                                      const uint8_t* write_buffer,
                                                      size_t write_size, uint8_t* out_read_buffer,
                                                      size_t read_size, size_t* out_read_actual) {
  if (out_read_actual != NULL) {
    *out_read_actual = 0;
  }

  return ZX_OK;
}
void UsbAdbDevice::EnableEndpoints() {
  switch (state_) {
    case State::kOnline:
      zxlogf(INFO, "USB endpoints already enabled");
      return;
    case State::kStoppingUsb:
      zxlogf(ERROR, "This is unexpected: UsbFunctionInterface is disconnected while stopping");
      return;
    case State::kAwaitingUsbConnection:
      zxlogf(INFO, "Enabling USB endpoints");
      break;
  }

  zx_status_t status = function_.ConfigEp(&descriptors_.bulk_out_ep, nullptr);
  if (status != ZX_OK) {
    ZX_PANIC("Failed to Config BULK OUT ep - %d.", status);
  }

  status = function_.ConfigEp(&descriptors_.bulk_in_ep, nullptr);
  if (status != ZX_OK) {
    ZX_PANIC("Failed to Config BULK IN ep - %d.", status);
  }

  // queue RX requests
  std::vector<fuchsia_hardware_usb_request::Request> requests;
  while (auto req = bulk_out_ep_.GetRequest()) {
    req->reset_buffers(bulk_out_ep_.GetMapped());
    auto status = req->CacheFlushInvalidate(bulk_out_ep_.GetMapped());
    if (status != ZX_OK) {
      ZX_PANIC("Cache flush and invalidate failed %d", status);
    }

    requests.emplace_back(req->take_request());
  }
  auto result = bulk_out_ep_->QueueRequests(std::move(requests));
  if (result.is_error()) {
    ZX_PANIC("Failed to QueueRequests %s", result.error_value().FormatDescription().c_str());
  }

  if (adb_binding_.has_value()) {
    auto result = fidl::WireSendEvent(*adb_binding_)->OnStatusChanged(fadb::StatusFlags::kOnline);
    if (!result.ok()) {
      zxlogf(ERROR, "Could not call UsbAdbImpl.OnStatusChanged.");
    }
  }

  zxlogf(INFO, "state_ = State::kOnline");
  state_ = State::kOnline;
}

zx_status_t UsbAdbDevice::UsbFunctionInterfaceSetConfigured(bool configured, usb_speed_t speed) {
  zxlogf(INFO, "configured? - %d  speed - %d.", configured, speed);
  async::PostTask(dispatcher(), [this, configured]() {
    std::lock_guard<async::sequence_checker> _(checker_);
    if (configured) {
      EnableEndpoints();
    } else {
      switch (state_) {
        case State::kAwaitingUsbConnection:
          // It's normal to receive SetConfigured(false) while the connection is
          // starting up - ignore it.
          break;
        case State::kOnline:
          ResetOrStopUsb();
          break;
        case State::kStoppingUsb:
          zxlogf(
              WARNING,
              "Received SetConfigured(false) while stopping. This is unexpected, but probably fine.");
          break;
      }
    }
  });
  return ZX_OK;
}

zx_status_t UsbAdbDevice::UsbFunctionInterfaceSetInterface(uint8_t interface, uint8_t alt_setting) {
  zxlogf(INFO, "interface - %d alt_setting - %d.", interface, alt_setting);

  // We don't support any alt_settings - just validate that the main setting has
  // been requested, and then don't do anything.
  if (interface != descriptors_.adb_intf.b_interface_number || alt_setting > 0) {
    return ZX_ERR_INVALID_ARGS;
  }
  return ZX_OK;
}

void UsbAdbDevice::CheckUsbStopComplete() {
  if (state_ != State::kStoppingUsb) {
    ZX_PANIC("Unexpected state: %d", state_);
  }

  if (!bulk_in_ep_.RequestsFull() || !bulk_out_ep_.RequestsFull()) {
    // Still waiting for outstanding USB requests to return.
    // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
    zxlogf(INFO, "Not all USB requests complete (in:%d out:%d)", bulk_in_ep_.RequestsFull(),
           bulk_out_ep_.RequestsFull());
    return;
  }

  zxlogf(INFO, "All USB requests complete. Completing USB stop.");

  if (adb_binding_.has_value()) {
    auto result = fidl::WireSendEvent(*adb_binding_)->OnStatusChanged(fadb::StatusFlags(0));
    if (!result.ok()) {
      zxlogf(ERROR, "Could not call UsbAdbImpl.OnStatusChanged.");
    }
  }

  adb_binding_.reset();

  // TODO(b/417808660): Replace logs with Inspect once the bug is fixed.
  zxlogf(INFO, "Calling stop_completers_");
  while (!stop_completers_.empty()) {
    stop_completers_.back().Reply(zx::ok());
    stop_completers_.pop_back();
  }

  // Is this a proper shutdown, or a restart of USB?
  if (shutdown_callback_.has_value()) {
    zxlogf(INFO, "Shutting down driver.");
    shutdown_callback_.value()(zx::ok());
    shutdown_callback_.reset();
  } else {
    zxlogf(INFO, "Restarting USB connection.");
    StartUsb();
  }
}

void UsbAdbDevice::PrepareStop(fdf::PrepareStopCompleter completer) {
  std::lock_guard<async::sequence_checker> _(checker_);
  shutdown_callback_.emplace(std::move(completer));
  ResetOrStopUsb();
}

zx_status_t UsbAdbDevice::InitEndpoint(
    fidl::ClientEnd<fuchsia_hardware_usb_function::UsbFunction>& client, uint8_t direction,
    uint8_t* ep_addrs, usb::EndpointClient<UsbAdbDevice>& ep, uint32_t req_count) {
  auto status = function_.AllocEp(direction, ep_addrs);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_function_alloc_ep failed - %s.", zx_status_get_string(status));
    return status;
  }

  status = ep.Init(*ep_addrs, client, usb_dispatcher_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to init UsbEndpoint %s", zx_status_get_string(status));
    return status;
  }

  // TODO(127854): When we support active pinning of VMOs, adb may want to use VMOs that are not
  // perpetually pinned.
  auto actual =
      ep.AddRequests(req_count, kVmoDataSize, fuchsia_hardware_usb_request::Buffer::Tag::kVmoId);
  if (actual != req_count) {
    zxlogf(ERROR, "Wanted %u requests, only got %zu requests", req_count, actual);
  }
  return actual == 0 ? ZX_ERR_INTERNAL : ZX_OK;
}

zx::result<> UsbAdbDevice::Start() {
  std::lock_guard<async::sequence_checker> _(checker_);
  zx::result<ddk::UsbFunctionProtocolClient> function =
      compat::ConnectBanjo<ddk::UsbFunctionProtocolClient>(incoming());
  if (function.is_error()) {
    FDF_SLOG(ERROR, "Failed to connect function", KV("status", function.status_string()));
    return function.take_error();
  }
  function_ = *function;

  auto client = incoming()->Connect<fuchsia_hardware_usb_function::UsbFunctionService::Device>();

  if (client.is_error()) {
    zxlogf(ERROR, "Failed to connect fidl protocol");
    return client.take_error();
  }

  auto status = function_.AllocInterface(&descriptors_.adb_intf.b_interface_number);
  if (status != ZX_OK) {
    zxlogf(ERROR, "usb_function_alloc_interface failed - %s.", zx_status_get_string(status));
    return zx::error(status);
  }

  status = InitEndpoint(*client, USB_DIR_OUT, &descriptors_.bulk_out_ep.b_endpoint_address,
                        bulk_out_ep_, kBulkRxCount);
  if (status != ZX_OK) {
    zxlogf(ERROR, "InitEndpoint failed - %s.", zx_status_get_string(status));
    return zx::error(status);
  }
  status = InitEndpoint(*client, USB_DIR_IN, &descriptors_.bulk_in_ep.b_endpoint_address,
                        bulk_in_ep_, kBulkTxCount);
  if (status != ZX_OK) {
    zxlogf(ERROR, "InitEndpoint failed - %s.", zx_status_get_string(status));
    return zx::error(status);
  }
  auto serve_result = outgoing()->AddService<fadb::Service>(fadb::Service::InstanceHandler({
      .adb = device_bindings_.CreateHandler(this, fdf::Dispatcher::GetCurrent()->async_dispatcher(),
                                            fidl::kIgnoreBindingClosure),
  }));
  if (serve_result.is_error()) {
    zxlogf(ERROR, "Failed to add Device service %s", serve_result.status_string());
    return serve_result.take_error();
  }

  StartUsb();
  return zx::ok();
}

void UsbAdbDevice::StartUsb() {
  zx_status_t status = function_.SetInterface(this, &usb_function_interface_protocol_ops_);
  if (status != ZX_OK) {
    ZX_PANIC("SetInterface failed %s", zx_status_get_string(status));
  }

  zxlogf(INFO, "state_ = State::kAwaitingUsbConnection");
  state_ = State::kAwaitingUsbConnection;
}

}  // namespace usb_adb_function

FUCHSIA_DRIVER_EXPORT(usb_adb_function::UsbAdbDevice);
