// 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 "src/ui/input/drivers/pc-ps2/device.h"

#include <fidl/fuchsia.hardware.input/cpp/wire.h>
#include <fidl/fuchsia.hardware.input/cpp/wire_types.h>
#include <lib/ddk/driver.h>
#include <zircon/syscalls.h>

#include <sstream>

#include <ddktl/device.h>
#include <hid/boot.h>

#include "src/ui/input/drivers/pc-ps2/commands.h"
#include "src/ui/input/drivers/pc-ps2/controller.h"
#include "src/ui/input/drivers/pc-ps2/keymap.h"

#ifdef PS2_TEST
extern zx::interrupt GetInterrupt(uint32_t irq);
#endif

namespace i8042 {

namespace finput = fuchsia_hardware_input::wire;

namespace {

constexpr uint16_t kIrqPort1 = 0x1;
constexpr uint16_t kIrqPort2 = 0xc;

constexpr uint8_t kMouseButtonCount = 3;
constexpr uint8_t kMouseAlwaysOne = (1 << 3);
constexpr uint8_t kMouseButtonMask = 0x7;

struct PortInfo {
  Command enable;
  Command disable;
  uint32_t irq;
  const char* devname;
};

__UNUSED constexpr PortInfo kPortInfo[2] = {
    /*[kPort1] =*/
    PortInfo{
        .enable = kCmdPort1Enable,
        .disable = kCmdPort1Disable,
        .irq = kIrqPort1,
        .devname = "i8042-keyboard",
    },
    /*[kPort2] =*/
    PortInfo{
        .enable = kCmdPort2Enable,
        .disable = kCmdPort2Disable,
        .irq = kIrqPort2,
        .devname = "i8042-mouse",
    },
};

}  // namespace

void PS2InputReport::ToFidlInputReport(fuchsia_input_report::wire::InputReport& input_report,
                                       fidl::AnyArena& allocator) {
  if (type == fuchsia_hardware_input::BootProtocol::kKbd) {
    ZX_ASSERT(std::holds_alternative<PS2KbdInputReport>(report));
    auto kbd = std::get<PS2KbdInputReport>(report);
    fidl::VectorView<fuchsia_input::wire::Key> keys3(allocator, kbd.num_pressed_keys_3);
    size_t idx = 0;
    for (const auto& key : kbd.pressed_keys_3) {
      keys3[idx++] = key;
    }

    auto kbd_input_rpt = fuchsia_input_report::wire::KeyboardInputReport(allocator);
    kbd_input_rpt.set_pressed_keys3(allocator, keys3);

    input_report.set_keyboard(allocator, kbd_input_rpt);
  } else if (type == fuchsia_hardware_input::BootProtocol::kMouse) {
    ZX_ASSERT(std::holds_alternative<PS2MouseInputReport>(report));
    auto mouse = std::get<PS2MouseInputReport>(report);
    std::vector<uint8_t> pressed_buttons;
    for (uint8_t i = 0; i < kMouseButtonCount; i++) {
      if (mouse.buttons & (1 << i)) {
        pressed_buttons.push_back(i + 1);
      }
    }
    fidl::VectorView<uint8_t> buttons(allocator, pressed_buttons.size());
    size_t idx = 0;
    for (const auto& button : pressed_buttons) {
      buttons[idx++] = button;
    }

    auto mouse_input_rpt = fuchsia_input_report::wire::MouseInputReport(allocator);
    mouse_input_rpt.set_pressed_buttons(allocator, buttons);
    mouse_input_rpt.set_movement_x(allocator, mouse.rel_x);
    mouse_input_rpt.set_movement_y(allocator, mouse.rel_y);

    input_report.set_mouse(allocator, mouse_input_rpt);
  }

  input_report.set_event_time(allocator, event_time.get());
}

zx_status_t I8042Device::Bind(Controller* parent, Port port) {
  auto dev = std::make_unique<I8042Device>(parent, port);
  zx_status_t status = dev->Bind();
  if (status == ZX_OK) {
    // The DDK takes ownership of the device.
    __UNUSED auto unused = dev.release();
  }

  return status;
}

zx_status_t I8042Device::Bind() {
  auto identity = Identify();
  if (identity.is_error()) {
    zxlogf(ERROR, "Identify failed: %s", identity.status_string());
    return identity.error_value();
  }

  protocol_ = *identity;
  if (protocol_ == fuchsia_hardware_input::BootProtocol::kKbd) {
    report_.report = PS2KbdInputReport{};
  } else if (protocol_ == fuchsia_hardware_input::BootProtocol::kMouse) {
    report_.report = PS2MouseInputReport{};
  }

#ifndef PS2_TEST
  // Map interrupt. We should get this from ACPI eventually.
  // Please do not use get_root_resource() in new code. See fxbug.dev/31358.
  zx_status_t status = zx::interrupt::create(*zx::unowned_resource(get_root_resource()),
                                             kPortInfo[port_].irq, ZX_INTERRUPT_REMAP_IRQ, &irq_);
  if (status != ZX_OK) {
    return status;
  }
#else
  irq_ = GetInterrupt(kPortInfo[port_].irq);
  zx_status_t status;
#endif

  status = loop_.StartThread("i8042-reader-thread");
  if (status != ZX_OK) {
    return status;
  }

  status = DdkAdd(ddk::DeviceAddArgs(kPortInfo[port_].devname));
  if (status != ZX_OK) {
    return status;
  }

  // Start the IRQ thread.
  irq_thread_ = std::thread([this]() { IrqThread(); });

  return ZX_OK;
}

void I8042Device::DdkUnbind(ddk::UnbindTxn txn) {
  if (!irq_thread_.joinable()) {
    txn.Reply();
    return;
  }
  {
    std::scoped_lock lock(unbind_lock_);
    unbind_.emplace(std::move(txn));
  }
  // Destroy the IRQ, causing the IRQ handler to finish.
  irq_.destroy();
  unbind_ready_.notify_all();
}

zx::status<finput::BootProtocol> I8042Device::Identify() {
  // Before sending IDENTIFY, disable scanning.
  // Otherwise a keyboard button pressed by the user could interfere with the value returned by
  // IDENTIFY.
  auto ret = controller_->SendDeviceCommand(kCmdDeviceScanDisable, port_);
  if (ret.is_error()) {
    zxlogf(ERROR, "Disable scan failed: %s", ret.status_string());
    return ret.take_error();
  }
  if (ret->empty() || ret.value()[0] != kAck) {
    zxlogf(ERROR, "Disable scan failed: bad response (size = %zu, first value = 0x%x)", ret->size(),
           ret->empty() ? -1 : ret.value()[0]);
    return zx::error(ZX_ERR_IO);
  }

  ret = controller_->SendDeviceCommand(kCmdDeviceIdentify, port_);
  if (ret.is_error()) {
    zxlogf(ERROR, "Identify failed: %s", ret.status_string());
    return ret.take_error();
  }
  if (ret->empty() || ret.value()[0] != kAck) {
    zxlogf(ERROR, "Identify failed: bad response");
    return zx::error(ZX_ERR_IO);
  }

  auto& ident = ret.value();
  if (ident.size() == 1) {
    zxlogf(WARNING, "i8042 device has no identity?");
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  std::ostringstream buf;
  for (size_t i = 1; i < ident.size(); i++) {
    buf << "0x" << std::hex << static_cast<int>(ident[i]) << ", ";
  }

  auto str = buf.str();
  zxlogf(INFO, "Identify: %s", str.empty() ? "(no response)" : str.data());

  finput::BootProtocol proto = finput::BootProtocol::kNone;
  if (ident[1] == 0xab) {
    proto = finput::BootProtocol::kKbd;
  } else {
    proto = finput::BootProtocol::kMouse;
  }

  // Re-enable the device.
  ret = controller_->SendDeviceCommand(kCmdDeviceScanEnable, port_);
  if (ret.is_error()) {
    return ret.take_error();
  }
  if (ret->empty() || ret.value()[0] != kAck) {
    return zx::error(ZX_ERR_IO);
  }
  return zx::ok(proto);
}

void I8042Device::GetInputReportsReader(GetInputReportsReaderRequestView request,
                                        GetInputReportsReaderCompleter::Sync& completer) {
  std::scoped_lock lock(hid_lock_);
  zx_status_t status =
      input_report_readers_.CreateReader(loop_.dispatcher(), std::move(request->reader));
  if (status == ZX_OK) {
#ifdef PS2_TEST
    sync_completion_signal(&next_reader_wait_);
#endif
  }
}

void I8042Device::GetDescriptor(GetDescriptorRequestView request,
                                GetDescriptorCompleter::Sync& completer) {
  fidl::Arena allocator;
  auto descriptor = fuchsia_input_report::wire::DeviceDescriptor(allocator);

  fuchsia_input_report::wire::DeviceInfo device_info;
  device_info.vendor_id = static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle);

  if (protocol_ == fuchsia_hardware_input::BootProtocol::kKbd) {
    device_info.product_id =
        static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kPcPs2Keyboard);
    std::vector<fuchsia_input::wire::Key> keys3;
    // Add usual HID keys
    for (const auto& key : kSet1UsageMap) {
      if (key) {
        keys3.push_back(key.value());
      }

      if (keys3.size() >= fuchsia_input_report::wire::kKeyboardMaxNumKeys) {
        zxlogf(ERROR, "Too many keys!");
        completer.Reply({});
        return;
      }
    }
    for (const auto& key : kSet1ExtendedUsageMap) {
      if (key) {
        keys3.push_back(key.value());
      }

      if (keys3.size() >= fuchsia_input_report::wire::kKeyboardMaxNumKeys) {
        zxlogf(ERROR, "Too many keys!");
        completer.Reply({});
        return;
      }
    }

    fidl::VectorView<fuchsia_input::wire::Key> fidl_keys3(allocator, keys3.size());
    size_t idx = 0;
    for (const auto& key : keys3) {
      fidl_keys3[idx++] = key;
    }

    auto kbd_in_desc = fuchsia_input_report::wire::KeyboardInputDescriptor(allocator);
    kbd_in_desc.set_keys3(allocator, fidl_keys3);

    fidl::VectorView<fuchsia_input_report::wire::LedType> leds(allocator, 5);
    leds[0] = fuchsia_input_report::wire::LedType::kNumLock;
    leds[1] = fuchsia_input_report::wire::LedType::kCapsLock;
    leds[2] = fuchsia_input_report::wire::LedType::kScrollLock;
    leds[3] = fuchsia_input_report::wire::LedType::kCompose;
    leds[4] = fuchsia_input_report::wire::LedType::kKana;
    auto kbd_out_desc = fuchsia_input_report::wire::KeyboardOutputDescriptor(allocator);
    kbd_out_desc.set_leds(allocator, leds);

    auto kbd_descriptor = fuchsia_input_report::wire::KeyboardDescriptor(allocator);
    kbd_descriptor.set_input(allocator, kbd_in_desc);
    kbd_descriptor.set_output(allocator, kbd_out_desc);
    descriptor.set_keyboard(allocator, kbd_descriptor);
  } else if (protocol_ == fuchsia_hardware_input::BootProtocol::kMouse) {
    device_info.product_id =
        static_cast<uint32_t>(fuchsia_input_report::wire::VendorGoogleProductId::kPcPs2Mouse);
    fidl::VectorView<uint8_t> buttons(allocator, kMouseButtonCount);
    buttons[0] = 0x01;
    buttons[1] = 0x02;
    buttons[2] = 0x03;

    constexpr fuchsia_input_report::wire::Axis movement_x{
        .range = {.min = -127, .max = 127},
        .unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
    };
    constexpr fuchsia_input_report::wire::Axis movement_y{
        .range = {.min = -127, .max = 127},
        .unit = {.type = fuchsia_input_report::wire::UnitType::kNone, .exponent = 0},
    };

    auto mouse_in_desc = fuchsia_input_report::wire::MouseInputDescriptor(allocator);
    mouse_in_desc.set_buttons(allocator, buttons);
    mouse_in_desc.set_movement_x(allocator, movement_x);
    mouse_in_desc.set_movement_y(allocator, movement_y);

    auto mouse_descriptor = fuchsia_input_report::wire::MouseDescriptor(allocator);
    mouse_descriptor.set_input(allocator, mouse_in_desc);
    descriptor.set_mouse(allocator, mouse_descriptor);
  }
  descriptor.set_device_info(allocator, device_info);

  completer.Reply(descriptor);
}

void I8042Device::IrqThread() {
  while (true) {
    zx::time timestamp;
    zx_status_t status = irq_.wait(&timestamp);
    if (status != ZX_OK) {
      break;
    }

    bool retry;
    do {
      retry = false;

      auto status = controller_->ReadStatus();
      if (status.obf()) {
        retry = true;
        uint8_t data = controller_->ReadData();
        if (protocol_ == finput::BootProtocol::kKbd) {
          ProcessScancode(timestamp, data);
        } else if (protocol_ == finput::BootProtocol::kMouse) {
          ProcessMouse(timestamp, data);
        }
      }
    } while (retry);
  }

  std::scoped_lock lock(unbind_lock_);
  unbind_ready_.wait(unbind_lock_,
                     [this]() __TA_REQUIRES(unbind_lock_) { return unbind_.has_value(); });
  unbind_->Reply();
}

void I8042Device::ProcessScancode(zx::time timestamp, uint8_t code) {
  report_.event_time = timestamp;
  report_.type = fuchsia_hardware_input::wire::BootProtocol::kKbd;

  bool multi = (last_code_ == kExtendedScancode);
  last_code_ = code;

  bool key_up = !!(code & kKeyUp);
  code &= kScancodeMask;

  std::optional<fuchsia_input::wire::Key> key;
  if (multi) {
    key = kSet1ExtendedUsageMap[code];
  } else {
    key = kSet1UsageMap[code];
  }
  if (!key)
    return;

  if (key_up) {
    RemoveKey(*key);
  } else {
    AddKey(*key);
  }

  {
    std::scoped_lock lock(hid_lock_);
    input_report_readers_.SendReportToAllReaders(report_);
  }
}

KeyStatus I8042Device::AddKey(fuchsia_input::wire::Key key) {
  for (size_t i = 0; i < keyboard_report().num_pressed_keys_3; i++) {
    if (keyboard_report().pressed_keys_3[i] == key) {
      return KeyStatus::kKeyExists;
    }
  }
  keyboard_report().pressed_keys_3[keyboard_report().num_pressed_keys_3++] = key;
  return KeyStatus::kKeyAdded;
}

KeyStatus I8042Device::RemoveKey(fuchsia_input::wire::Key key) {
  size_t idx = -1;
  for (size_t i = 0; i < keyboard_report().num_pressed_keys_3; i++) {
    if (keyboard_report().pressed_keys_3[i] == key) {
      idx = i;
      break;
    }
  }

  if (idx == -1UL) {
    return KeyStatus::kKeyNotFound;
  }

  for (size_t i = idx; i < keyboard_report().num_pressed_keys_3 - 1; i++) {
    keyboard_report().pressed_keys_3[i] = keyboard_report().pressed_keys_3[i + 1];
  }
  keyboard_report().num_pressed_keys_3--;
  return KeyStatus::kKeyRemoved;
}

void I8042Device::ProcessMouse(zx::time timestamp, uint8_t code) {
  report_.type = fuchsia_hardware_input::wire::BootProtocol::kMouse;
  report_.event_time = timestamp;
  // PS/2 mouse reports span 3 bytes. last_code_ tracks which byte we're up to.
  switch (last_code_) {
    case 0:
      // The first byte should always have this bit set. If it's not set, ignore the packet.
      if (!(code & kMouseAlwaysOne)) {
        return;
      }
      mouse_report().buttons = code;
      break;
    case 1: {
      int state = mouse_report().buttons;
      int d = code;
      mouse_report().rel_x = static_cast<int8_t>(d - ((state << 4) & 0x100));
      break;
    }
    case 2: {
      int state = mouse_report().buttons;
      int d = code;
      // PS/2 maps the y-axis backwards so invert the rel_y value
      mouse_report().rel_y = static_cast<int8_t>(((state << 3) & 0x100) - d);
      mouse_report().buttons &= kMouseButtonMask;

      std::scoped_lock lock(hid_lock_);
      input_report_readers_.SendReportToAllReaders(report_);
      report_.Reset();
      break;
    }
  }

  last_code_ = (last_code_ + 1) % 3;
}

}  // namespace i8042
