// 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 "src/ui/lib/input_reader/fdio_hid_decoder.h"

#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/hardware/input/c/fidl.h>
#include <unistd.h>
#include <zircon/status.h>

#include <hid/acer12.h>
#include <hid/egalax.h>
#include <hid/eyoyo.h>
#include <hid/ft3x27.h>
#include <hid/paradise.h>
#include <hid/samsung.h>
#include <trace/event.h>

#include "src/lib/fxl/arraysize.h"
#include "src/lib/fxl/logging.h"

namespace {

bool log_err(zx_status_t status, const std::string& what, const std::string& name) {
  FXL_LOG(ERROR) << "hid: could not get " << what << " from " << name
                 << " (status=" << zx_status_get_string(status) << ")";
  return false;
}

}  // namespace

namespace ui_input {

FdioHidDecoder::FdioHidDecoder(const std::string& name, fbl::unique_fd fd)
    : caller_(std::move(fd)), name_(name) {}

FdioHidDecoder::~FdioHidDecoder() = default;

bool FdioHidDecoder::Init() {
  zx_status_t status;
  zx_handle_t svc = caller_.borrow_channel();

  // Get the Boot Protocol if there is one.
  fuchsia_hardware_input_BootProtocol boot_protocol;
  status = fuchsia_hardware_input_DeviceGetBootProtocol(svc, &boot_protocol);
  if (status != ZX_OK) {
    return log_err(status, "boot protocol", name_);
  }

  if (boot_protocol == fuchsia_hardware_input_BootProtocol_KBD) {
    boot_mode_ = BootMode::KEYBOARD;
  } else if (boot_protocol == fuchsia_hardware_input_BootProtocol_MOUSE) {
    boot_mode_ = BootMode::MOUSE;
  } else {
    boot_mode_ = BootMode::NONE;
  }

  // Get the report descriptor.
  uint16_t report_desc_len;
  status = fuchsia_hardware_input_DeviceGetReportDescSize(svc, &report_desc_len);
  if (status != ZX_OK)
    return log_err(status, "report descriptor length", name_);

  report_descriptor_.resize(report_desc_len);
  size_t actual;
  status = fuchsia_hardware_input_DeviceGetReportDesc(svc, report_descriptor_.data(),
                                                      report_descriptor_.size(), &actual);
  if (status != ZX_OK)
    return log_err(status, "report descriptor", name_);
  report_descriptor_.resize(actual);

  // Use lower 32 bits of channel koid as trace ID.
  zx_info_handle_basic_t info;
  zx_object_get_info(svc, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
  trace_id_ = info.koid & 0xffffffff;
  status = fuchsia_hardware_input_DeviceSetTraceId(svc, trace_id_);
  if (status != ZX_OK)
    return log_err(status, "failed to set trace ID", name_);

  return true;
}

zx::event FdioHidDecoder::GetEvent() {
  zx::event event;

  auto resp = ::llcpp::fuchsia::device::Controller::Call::GetEventHandle(
      zx::unowned_channel(caller_.borrow_channel()));
  zx_status_t status = resp.status();
  if (status == ZX_OK) {
    event = std::move(resp->event);
  }
  if (status != ZX_OK) {
    log_err(status, "event handle", name_);
    return {};
  }
  return event;
}

const std::vector<uint8_t>& FdioHidDecoder::ReadReportDescriptor(int* bytes_read) {
  *bytes_read = report_descriptor_.size();
  return report_descriptor_;
}

size_t FdioHidDecoder::Read(uint8_t* data, size_t data_size) {
  size_t size;
  zx_status_t call_status;
  zx_status_t status = fuchsia_hardware_input_DeviceGetReports(
      caller_.borrow_channel(), &call_status, data, data_size, &size);
  if ((call_status != ZX_OK) || (status != ZX_OK)) {
    return 0;
  }
  return size;
}

zx_status_t FdioHidDecoder::Send(ReportType type, uint8_t report_id,
                                 const std::vector<uint8_t>& report) {
  FXL_CHECK(type != ReportType::INPUT);

  fuchsia_hardware_input_ReportType fidl_report_type;
  switch (type) {
    case ReportType::INPUT:
      fidl_report_type = fuchsia_hardware_input_ReportType_INPUT;
      break;
    case ReportType::OUTPUT:
      fidl_report_type = fuchsia_hardware_input_ReportType_OUTPUT;
      break;
    case ReportType::FEATURE:
      fidl_report_type = fuchsia_hardware_input_ReportType_FEATURE;
      break;
  }

  zx_handle_t svc = caller_.borrow_channel();

  zx_status_t call_status;
  zx_status_t status = fuchsia_hardware_input_DeviceSetReport(
      svc, fidl_report_type, report_id, report.data(), report.size(), &call_status);

  if (status != ZX_OK) {
    return status;
  } else if (call_status != ZX_OK) {
    return call_status;
  }
  return ZX_OK;
}

zx_status_t FdioHidDecoder::GetReport(ReportType type, uint8_t report_id,
                                      std::vector<uint8_t>* report) {
  zx_status_t res, call_status;
  uint16_t size;

  fuchsia_hardware_input_ReportType real_type;
  switch (type) {
    case ReportType::INPUT:
      real_type = fuchsia_hardware_input_ReportType_INPUT;
      break;
    case ReportType::OUTPUT:
      real_type = fuchsia_hardware_input_ReportType_OUTPUT;
      break;
    case ReportType::FEATURE:
      real_type = fuchsia_hardware_input_ReportType_FEATURE;
      break;
  }

  res = fuchsia_hardware_input_DeviceGetReportSize(caller_.borrow_channel(), real_type, report_id,
                                                   &call_status, &size);
  if (res != ZX_OK || call_status != ZX_OK) {
    FXL_LOG(ERROR) << "hid: could not get report (id " << report_id << " type " << real_type
                   << ") size (status=" << zx_status_get_string(res) << ", "
                   << zx_status_get_string(call_status) << ")";
    return call_status;
  }

  report->resize(size);

  size_t actual;
  res =
      fuchsia_hardware_input_DeviceGetReport(caller_.borrow_channel(), real_type, report_id,
                                             &call_status, report->data(), report->size(), &actual);
  if (res != ZX_OK || call_status != ZX_OK) {
    FXL_LOG(ERROR) << "hid: could not get report: " << zx_status_get_string(res) << " "
                   << zx_status_get_string(call_status);
    return call_status;
  }
  report->resize(actual);

  return ZX_OK;
}

}  // namespace ui_input
