// 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 "garnet/bin/ui/input_reader/fdio_hid_decoder.h"

#include <fuchsia/device/c/fidl.h>
#include <fuchsia/hardware/input/c/fidl.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 <src/lib/fxl/arraysize.h>
#include <src/lib/fxl/logging.h>
#include <trace/event.h>
#include <unistd.h>
#include <zircon/status.h>

namespace {

#define HID_REPORT_TRACE_ID(trace_id, report_id) \
  (((uint64_t)(report_id) << 32) | (trace_id))

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() {
  uint16_t max_len = 0;
  zx_status_t status = fuchsia_hardware_input_DeviceGetMaxInputReportSize(
      caller_.borrow_channel(), &max_len);
  report_.resize(max_len);

  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, "ioctl 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;

  zx_status_t call_status;
  zx_status_t status = fuchsia_device_ControllerGetEventHandle(
      caller_.borrow_channel(), &call_status, event.reset_and_get_address());
  if (status == ZX_OK) {
    status = call_status;
  }
  if (status != ZX_OK) {
    log_err(status, "event handle", name_);
    return {};
  }
  return event;
}

void FdioHidDecoder::SetupDevice(Device device) {
  switch (device) {
    case Device::EYOYO:
      setup_eyoyo_touch(caller_.fd().get());
      break;
    case Device::SAMSUNG:
      setup_samsung_touch(caller_.fd().get());
      break;
    case Device::FT3X27:
      setup_ft3x27_touch(caller_.fd().get());
      break;
    default:
      break;
  }
}

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

const std::vector<uint8_t>& FdioHidDecoder::Read(int* bytes_read) {
  *bytes_read = read(caller_.fd().get(), report_.data(), report_.size());

  TRACE_FLOW_END("input", "hid_report",
                 HID_REPORT_TRACE_ID(trace_id_, reports_read_));
  ++reports_read_;

  return report_;
}

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
