// Copyright 2017 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 "input.h"

#include <limits.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>
#include <zircon/status.h>

#include <utility>

#include <ddk/debug.h>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>

#include "trace.h"

#define LOCAL_TRACE 0

namespace virtio {

// DDK level ops
static zx_status_t virtio_input_OpenClient(void* ctx, uint32_t id, zx_handle_t handle,
                                           fidl_txn_t* txn) {
  return fuchsia_hardware_pty_DeviceOpenClient_reply(txn, ZX_ERR_NOT_SUPPORTED);
}

static zx_status_t virtio_input_ClrSetFeature(void* ctx, uint32_t clr, uint32_t set,
                                              fidl_txn_t* txn) {
  return fuchsia_hardware_pty_DeviceClrSetFeature_reply(txn, ZX_ERR_NOT_SUPPORTED, 0);
}

static zx_status_t virtio_input_GetWindowSize(void* ctx, fidl_txn_t* txn) {
  fuchsia_hardware_pty_WindowSize wsz = {.width = 0, .height = 0};
  return fuchsia_hardware_pty_DeviceGetWindowSize_reply(txn, ZX_ERR_NOT_SUPPORTED, &wsz);
}

static zx_status_t virtio_input_MakeActive(void* ctx, uint32_t client_pty_id, fidl_txn_t* txn) {
  return fuchsia_hardware_pty_DeviceMakeActive_reply(txn, ZX_ERR_NOT_SUPPORTED);
}

static zx_status_t virtio_input_ReadEvents(void* ctx, fidl_txn_t* txn) {
  return fuchsia_hardware_pty_DeviceReadEvents_reply(txn, ZX_ERR_NOT_SUPPORTED, 0);
}

static zx_status_t virtio_input_SetWindowSize(void* ctx,
                                              const fuchsia_hardware_pty_WindowSize* size,
                                              fidl_txn_t* txn) {
  return fuchsia_hardware_pty_DeviceSetWindowSize_reply(txn, ZX_ERR_NOT_SUPPORTED);
}

static constexpr fuchsia_hardware_pty_Device_ops_t fidl_ops = []() {
  // TODO: Why does this implement fuchsia.hardware.pty/Device?  This device
  // does not provide read/write methods, so shouldn't be usable as a terminal.
  fuchsia_hardware_pty_Device_ops_t ops = {};
  ops.OpenClient = virtio_input_OpenClient;
  ops.ClrSetFeature = virtio_input_ClrSetFeature;
  ops.GetWindowSize = virtio_input_GetWindowSize;
  ops.MakeActive = virtio_input_MakeActive;
  ops.ReadEvents = virtio_input_ReadEvents;
  ops.SetWindowSize = virtio_input_SetWindowSize;
  return ops;
}();

static bool IsQemuTouchscreen(const virtio_input_config_t& config) {
  if (config.u.ids.bustype == 0x06 && config.u.ids.vendor == 0x00 && config.u.ids.product == 0x00) {
    if (config.u.ids.version == 0x01 || config.u.ids.version == 0x00) {
      return true;
    }
  }
  return false;
}

zx_status_t InputDevice::virtio_input_message(void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) {
  return fuchsia_hardware_pty_Device_dispatch(ctx, txn, msg, &fidl_ops);
}

void InputDevice::virtio_input_release(void* ctx) {
  virtio::InputDevice* inp = static_cast<virtio::InputDevice*>(ctx);
  return inp->Release();
}

zx_status_t InputDevice::virtio_input_query(void* ctx, uint32_t options, hid_info_t* info) {
  virtio::InputDevice* inp = static_cast<virtio::InputDevice*>(ctx);
  return inp->Query(options, info);
}

zx_status_t InputDevice::virtio_input_get_descriptor(void* ctx, uint8_t desc_type, void** data,
                                                     size_t* len) {
  virtio::InputDevice* inp = static_cast<virtio::InputDevice*>(ctx);
  return inp->GetDescriptor(desc_type, data, len);
}

zx_status_t InputDevice::virtio_input_get_report(void* ctx, uint8_t rpt_type, uint8_t rpt_id,
                                                 void* data, size_t len, size_t* out_len) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t InputDevice::virtio_input_set_report(void* ctx, uint8_t rpt_type, uint8_t rpt_id,
                                                 const void* data, size_t len) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t InputDevice::virtio_input_get_idle(void* ctx, uint8_t rpt_type, uint8_t* duration) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t InputDevice::virtio_input_set_idle(void* ctx, uint8_t rpt_type, uint8_t duration) {
  return ZX_OK;
}

zx_status_t InputDevice::virtio_input_get_protocol(void* ctx, uint8_t* protocol) {
  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t InputDevice::virtio_input_set_protocol(void* ctx, uint8_t protocol) { return ZX_OK; }

zx_status_t InputDevice::virtio_input_start(void* ctx, const hidbus_ifc_protocol_t* ifc) {
  virtio::InputDevice* inp = static_cast<virtio::InputDevice*>(ctx);
  return inp->Start(ifc);
}

void InputDevice::virtio_input_stop(void* ctx) {
  virtio::InputDevice* inp = static_cast<virtio::InputDevice*>(ctx);
  inp->Stop();
}

InputDevice::InputDevice(zx_device_t* bus_device, zx::bti bti, fbl::unique_ptr<Backend> backend)
    : Device(bus_device, std::move(bti), std::move(backend)) {}

InputDevice::~InputDevice() {}

zx_status_t InputDevice::Init() {
  LTRACEF("Device %p\n", this);

  fbl::AutoLock lock(&lock_);

  // Reset the device and read configuration
  DeviceReset();

  SelectConfig(VIRTIO_INPUT_CFG_ID_NAME, 0);
  LTRACEF_LEVEL(2, "name %s\n", config_.u.string);

  SelectConfig(VIRTIO_INPUT_CFG_ID_SERIAL, 0);
  LTRACEF_LEVEL(2, "serial %s\n", config_.u.string);

  SelectConfig(VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
  if (config_.size >= sizeof(virtio_input_devids_t)) {
    LTRACEF_LEVEL(2, "bustype %d\n", config_.u.ids.bustype);
    LTRACEF_LEVEL(2, "vendor %d\n", config_.u.ids.vendor);
    LTRACEF_LEVEL(2, "product %d\n", config_.u.ids.product);
    LTRACEF_LEVEL(2, "version %d\n", config_.u.ids.version);
  }

  SelectConfig(VIRTIO_INPUT_CFG_EV_BITS, VIRTIO_INPUT_EV_KEY);
  uint8_t cfg_key_size = config_.size;
  SelectConfig(VIRTIO_INPUT_CFG_EV_BITS, VIRTIO_INPUT_EV_REL);
  uint8_t cfg_rel_size = config_.size;
  SelectConfig(VIRTIO_INPUT_CFG_EV_BITS, VIRTIO_INPUT_EV_ABS);
  uint8_t cfg_abs_size = config_.size;

  // At the moment we support keyboards and a specific touchscreen.
  // Support for more devices should be added here.
  SelectConfig(VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
  if (IsQemuTouchscreen(config_)) {
    // QEMU MultiTouch Touchscreen
    SelectConfig(VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_EV_MT_POSITION_X);
    virtio_input_absinfo_t x_info = config_.u.abs;
    SelectConfig(VIRTIO_INPUT_CFG_ABS_INFO, VIRTIO_INPUT_EV_MT_POSITION_Y);
    virtio_input_absinfo_t y_info = config_.u.abs;
    hid_device_ = std::make_unique<HidTouch>(x_info, y_info);
  } else if (cfg_key_size > 0) {
    // Keyboard
    dev_class_ = HID_DEVICE_CLASS_KBD;
    hid_device_ = std::make_unique<HidKeyboard>();
  } else if (cfg_rel_size > 0 || cfg_abs_size > 0) {
    // TODO: This is where a Mouse should be implemented.
    dev_class_ = HID_DEVICE_CLASS_POINTER;
    return ZX_ERR_NOT_SUPPORTED;
  } else {
    return ZX_ERR_NOT_SUPPORTED;
  }

  DriverStatusAck();

  // Plan to clean up unless everything succeeds.
  auto cleanup = fbl::MakeAutoCall([this]() { Release(); });

  // Allocate the main vring
  zx_status_t status = vring_.Init(0, kEventCount);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to allocate vring: %s\n", zx_status_get_string(status));
    return status;
  }

  // Allocate event buffers for the ring.
  // TODO: Avoid multiple allocations, allocate enough for all buffers once.
  for (uint16_t id = 0; id < kEventCount; ++id) {
    static_assert(sizeof(virtio_input_event_t) <= PAGE_SIZE, "");
    status = io_buffer_init(&buffers_[id], bti_.get(), sizeof(virtio_input_event_t),
                            IO_BUFFER_RO | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
      zxlogf(ERROR, "Failed to allocate I/O buffers: %s\n", zx_status_get_string(status));
      return status;
    }
  }

  // Expose event buffers to the host
  vring_desc* desc = nullptr;
  uint16_t id;
  for (uint16_t i = 0; i < kEventCount; ++i) {
    desc = vring_.AllocDescChain(1, &id);
    if (desc == nullptr) {
      zxlogf(ERROR, "Failed to allocate descriptor chain\n");
      return ZX_ERR_NO_RESOURCES;
    }
    ZX_ASSERT(id < kEventCount);
    desc->addr = io_buffer_phys(&buffers_[id]);
    desc->len = sizeof(virtio_input_event_t);
    desc->flags |= VRING_DESC_F_WRITE;
    LTRACE_DO(virtio_dump_desc(desc));
    vring_.SubmitChain(id);
  }

  StartIrqThread();
  DriverStatusOk();

  device_ops_.message = virtio_input_message;
  device_ops_.release = virtio_input_release;

  hidbus_ops_.query = virtio_input_query;
  hidbus_ops_.start = virtio_input_start;
  hidbus_ops_.stop = virtio_input_stop;
  hidbus_ops_.get_descriptor = virtio_input_get_descriptor;
  hidbus_ops_.get_report = virtio_input_get_report;
  hidbus_ops_.set_report = virtio_input_set_report;
  hidbus_ops_.get_idle = virtio_input_get_idle;
  hidbus_ops_.set_idle = virtio_input_set_idle;
  hidbus_ops_.get_protocol = virtio_input_get_protocol;
  hidbus_ops_.set_protocol = virtio_input_set_protocol;

  hidbus_ifc_.ops = nullptr;

  device_add_args_t args = {};
  args.version = DEVICE_ADD_ARGS_VERSION;
  args.name = "virtio-input";
  args.ctx = this;
  args.ops = &device_ops_;
  args.proto_id = ZX_PROTOCOL_HIDBUS;
  args.proto_ops = &hidbus_ops_;

  status = device_add(bus_device_, &args, &device_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to add device: %s\n", zx_status_get_string(status));
    device_ = nullptr;
    return status;
  }

  vring_.Kick();
  cleanup.cancel();
  return ZX_OK;
}

zx_status_t InputDevice::Start(const hidbus_ifc_protocol_t* ifc) {
  fbl::AutoLock lock(&lock_);
  if (hidbus_ifc_.ops != nullptr) {
    return ZX_ERR_ALREADY_BOUND;
  }
  hidbus_ifc_ = *ifc;
  return ZX_OK;
}

void InputDevice::Stop() {
  fbl::AutoLock lock(&lock_);
  hidbus_ifc_.ops = nullptr;
}

void InputDevice::Release() {
  fbl::AutoLock lock(&lock_);
  hidbus_ifc_.ops = nullptr;
  for (size_t i = 0; i < kEventCount; ++i) {
    if (io_buffer_is_valid(&buffers_[i])) {
      io_buffer_release(&buffers_[i]);
    }
  }
}

zx_status_t InputDevice::Query(uint32_t options, hid_info_t* info) {
  info->dev_num = dev_class_;  // Use type for dev_num for now.
  info->device_class = dev_class_;
  info->boot_device = true;
  return ZX_OK;
}

zx_status_t InputDevice::GetDescriptor(uint8_t desc_type, void** data, size_t* len) {
  return hid_device_->GetDescriptor(desc_type, data, len);
}

void InputDevice::ReceiveEvent(virtio_input_event_t* event) {
  hid_device_->ReceiveEvent(event);

  if (event->type == VIRTIO_INPUT_EV_SYN) {
    fbl::AutoLock lock(&lock_);
    if (hidbus_ifc_.ops) {
      size_t size;
      const uint8_t* report = hid_device_->GetReport(&size);
      hidbus_ifc_io_queue(&hidbus_ifc_, report, size);
    }
  }
}

void InputDevice::IrqRingUpdate() {
  auto free_chain = [this](vring_used_elem* used_elem) {
    uint16_t id = static_cast<uint16_t>(used_elem->id & 0xffff);
    vring_desc* desc = vring_.DescFromIndex(id);
    ZX_ASSERT(id < kEventCount);
    ZX_ASSERT(desc->len == sizeof(virtio_input_event_t));

    auto evt = static_cast<virtio_input_event_t*>(io_buffer_virt(&buffers_[id]));
    ReceiveEvent(evt);

    ZX_ASSERT((desc->flags & VRING_DESC_F_NEXT) == 0);
    vring_.FreeDesc(id);
  };

  vring_.IrqRingUpdate(free_chain);

  vring_desc* desc = nullptr;
  uint16_t id;
  bool need_kick = false;
  while ((desc = vring_.AllocDescChain(1, &id))) {
    desc->len = sizeof(virtio_input_event_t);
    vring_.SubmitChain(id);
    need_kick = true;
  }

  if (need_kick) {
    vring_.Kick();
  }
}

void InputDevice::IrqConfigChange() { LTRACEF("IrqConfigChange\n"); }

void InputDevice::SelectConfig(uint8_t select, uint8_t subsel) {
  WriteDeviceConfig(offsetof(virtio_input_config_t, select), select);
  WriteDeviceConfig(offsetof(virtio_input_config_t, subsel), subsel);
  CopyDeviceConfig(&config_, sizeof(config_));
}

}  // namespace virtio
