// 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 "ft_device.h"

#include <lib/ddk/metadata.h>
#include <lib/driver/compat/cpp/metadata.h>
#include <lib/driver/component/cpp/driver_export2.h>
#include <lib/driver/platform-device/cpp/pdev.h>
#include <lib/fit/defer.h>
#include <lib/stdcompat/inplace_vector.h>
#include <lib/zx/clock.h>
#include <lib/zx/process.h>
#include <lib/zx/profile.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <zircon/compiler.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/threads.h>

#include <algorithm>

#include <fbl/algorithm.h>
#include <fbl/auto_lock.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <hwreg/bitfields.h>

#include "lib/device-protocol/display-panel.h"
#include "src/devices/i2c/lib/i2c-channel/i2c-channel.h"

namespace ft {

namespace {

constexpr fuchsia_input::wire::Axis XYAxis(int64_t max) {
  return {
      .range = {.min = 0, .max = max},
      .unit =
          {
              .type = fuchsia_input::wire::UnitType::kOther,
              .exponent = 0,
          },
  };
}

constexpr size_t kFt3x27XMax = 600;
constexpr size_t kFt3x27YMax = 1024;

constexpr size_t kFt6336XMax = 480;
constexpr size_t kFt6336YMax = 800;

constexpr size_t kFt5726XMax = 800;
constexpr size_t kFt5726YMax = 1280;

constexpr size_t kFt5336XMax = 1080;
constexpr size_t kFt5336YMax = 1920;

}  // namespace

void FtDevice::FtInputReport::ToFidlInputReport(
    fidl::WireTableBuilder<::fuchsia_input_report::wire::InputReport>& input_report,
    fidl::AnyArena& allocator) const {
  fidl::VectorView<fuchsia_input_report::wire::ContactInputReport> contact_rpt(allocator,
                                                                               contacts.size());
  for (size_t i = 0; i < contacts.size(); i++) {
    contact_rpt[i] = fuchsia_input_report::wire::ContactInputReport::Builder(allocator)
                         .contact_id(contacts[i].finger_id)
                         .position_x(contacts[i].x)
                         .position_y(contacts[i].y)
                         .Build();
  }

  auto touch_report =
      fuchsia_input_report::wire::TouchInputReport::Builder(allocator).contacts(contact_rpt);
  input_report.event_time(event_time.get()).touch(touch_report.Build());
}

FtDevice::FtInputReport FtDevice::ParseReport(std::span<const uint8_t> buf) {
  FtInputReport report;
  const int contact_count = std::min(int{buf[0]}, int{report.contacts.capacity()});
  for (int i = 0; i < contact_count; i++) {
    const int touch_record_offset = 1 + (i * kTouchRecordSize);
    const TouchRecord* touch_record =
        reinterpret_cast<const TouchRecord*>(&buf[touch_record_offset]);
    if (touch_record->event_type() != FtTouchEventType::kContact) {
      continue;
    }
    report.contacts.push_back(FtInputReport::Contact{
        .finger_id = touch_record->touch_id(),
        .x = touch_record->x(),
        .y = touch_record->y(),
    });
  }
  return report;
}

void FtDevice::HandleIrq(async_dispatcher_t* dispatcher, async::IrqBase* irq, zx_status_t status,
                         const zx_packet_interrupt_t* interrupt) {
  if (status != ZX_OK) {
    if (status != ZX_ERR_CANCELED) {
      fdf::error("Interrupt error: {}", zx_status_get_string(status));
    }
    return;
  }
  TRACE_DURATION("input", "FtDevice Read");
  std::array<uint8_t, (kMaxPoints * kTouchRecordSize) + 1> read_buf;
  zx::result result = Read(FTS_REG_CURPOINT, read_buf);
  if (result.is_ok()) {
    auto timestamp = zx::time(interrupt->timestamp);
    auto report = ParseReport(read_buf);
    report.event_time = timestamp;
    readers_.SendReportToAllReaders(report);

    const zx::duration latency = zx::clock::get_monotonic() - timestamp;

    total_latency_ += latency;
    report_count_++;
    average_latency_usecs_.Set(total_latency_.to_usecs() / report_count_);

    if (latency > max_latency_) {
      max_latency_ = latency;
      max_latency_usecs_.Set(max_latency_.to_usecs());
    }

    if (read_buf[0] > 0) {
      total_report_count_.Add(1);
      last_event_timestamp_.Set(timestamp.get());
    }
  } else {
    fdf::error("Failed to read i2c: {}", result);
  }

  irq_.ack();
}

FtDevice::FtDevice() : fdf::DriverBase2(kDriverName) {}

zx::result<> FtDevice::Start(fdf::DriverContext context) {
  auto incoming_ptr = std::shared_ptr<fdf::Namespace>(context.take_incoming());
  zx::result i2c = i2c::I2cChannel::FromIncoming(*incoming_ptr, "i2c");
  if (i2c.is_error()) {
    fdf::error("Failed to connect to i2c: {}", i2c);
    return i2c.take_error();
  }
  i2c_ = std::move(i2c.value());

  zx::result int_gpio_client =
      incoming_ptr->Connect<fuchsia_hardware_gpio::Service::Device>("gpio-int");
  if (int_gpio_client.is_error()) {
    fdf::error("Failed to connect to interrupt gpio: {}", int_gpio_client);
    return zx::error(ZX_ERR_NO_RESOURCES);
  }
  int_gpio_.Bind(std::move(int_gpio_client.value()));

  zx::result reset_gpio_client =
      incoming_ptr->Connect<fuchsia_hardware_gpio::Service::Device>("gpio-reset");
  if (reset_gpio_client.is_error()) {
    fdf::error("Failed to connect to reset gpio: {}", reset_gpio_client);
    return zx::error(ZX_ERR_NO_RESOURCES);
  }
  reset_gpio_.Bind(std::move(reset_gpio_client.value()));

  {
    fidl::WireResult result = int_gpio_->SetBufferMode(fuchsia_hardware_gpio::BufferMode::kInput);
    if (!result.ok()) {
      fdf::error("Failed to send SetBufferMode request to int gpio: {}", result.status_string());
      return zx::error(result.status());
    }
    if (result->is_error()) {
      fdf::error("Failed to configure int gpio to input: {}",
                 zx_status_get_string(result->error_value()));
      return result->take_error();
    }
  }

  {
    fidl::Arena arena;
    auto config = fuchsia_hardware_gpio::wire::InterruptConfiguration::Builder(arena)
                      .mode(fuchsia_hardware_gpio::InterruptMode::kEdgeLow)
                      .Build();
    fidl::WireResult result = int_gpio_->ConfigureInterrupt(config);
    if (!result.ok()) {
      fdf::error("Failed to send ConfigureInterrupt request to int gpio: {}",
                 result.status_string());
      return zx::error(result.status());
    }
    if (result->is_error()) {
      fdf::error("Failed to configure int gpio: {}", zx_status_get_string(result->error_value()));
      return result->take_error();
    }
  }

  fidl::WireResult interrupt = int_gpio_->GetInterrupt({});
  if (!interrupt.ok()) {
    fdf::error("Failed to send GetInterrupt request to int gpio: {}", interrupt.status_string());
    return zx::error(interrupt.status());
  }
  if (interrupt->is_error()) {
    fdf::error("Failed to get interrupt from int gpio: {}",
               zx_status_get_string(interrupt->error_value()));
    return interrupt->take_error();
  }
  irq_ = std::move(interrupt.value()->interrupt);
  irq_handler_.set_object(irq_.get());
  irq_handler_.Begin(dispatcher());

  zx::result pdev_client =
      incoming_ptr->Connect<fuchsia_hardware_platform_device::Service::Device>("pdev");
  if (pdev_client.is_error()) {
    fdf::error("Failed to connect to platform device: {}", pdev_client);
    return pdev_client.take_error();
  }
  fdf::PDev pdev(std::move(pdev_client.value()));

  zx::result metadata = pdev.GetFidlMetadata<fuchsia_hardware_input_focaltech::Metadata>();
  if (metadata.is_error()) {
    fdf::error("Failed to get metadata: {}", metadata);
    return metadata.take_error();
  }
  const fuchsia_hardware_input_focaltech::Metadata& device_info = metadata.value();
  if (!device_info.device_id().has_value()) {
    fdf::error("Metadata missing `device_id` field");
    return zx::error(ZX_ERR_INTERNAL);
  }
  if (!device_info.needs_firmware().has_value()) {
    fdf::error("Metadata missing `needs_firmware` field");
    return zx::error(ZX_ERR_INTERNAL);
  }

  display::PanelType panel_type = display::PanelType::kUnknown;
  zx::result panel_type_result = compat::GetMetadata<display::PanelType>(
      incoming_ptr, DEVICE_METADATA_DISPLAY_PANEL_TYPE, "pdev");
  if (panel_type_result.is_ok()) {
    panel_type = *panel_type_result.value();
  } else if (panel_type_result.status_value() == ZX_ERR_NOT_FOUND) {
    fdf::warn("Display panel type information not found.");
  } else {
    fdf::error("Failed to get panel type: {}", panel_type_result);
    return panel_type_result.take_error();
  }
  fuchsia_hardware_input_focaltech::DeviceId device_id = device_info.device_id().value();
  switch (device_id) {
    case fuchsia_hardware_input_focaltech::DeviceId::kFt3X27:
      x_max_ = kFt3x27XMax;
      y_max_ = kFt3x27YMax;
      break;
    case fuchsia_hardware_input_focaltech::DeviceId::kFt6336:
      x_max_ = kFt6336XMax;
      y_max_ = kFt6336YMax;
      break;
    case fuchsia_hardware_input_focaltech::DeviceId::kFt5726:
      x_max_ = kFt5726XMax;
      y_max_ = kFt5726YMax;
      break;
    case fuchsia_hardware_input_focaltech::DeviceId::kFt5336:
      // Currently we assume the panel to be always Khadas TS050. If this changes,
      // we may need extra information from the metadata to determine which HID
      // report descriptor to use.
      x_max_ = kFt5336XMax;
      y_max_ = kFt5336YMax;
      break;
    default:
      fdf::error("Unkown device ID {}", static_cast<uint32_t>(device_id));
      return zx::error(ZX_ERR_INTERNAL);
  }

  // Reset the chip -- should be low for at least 1ms, and the chip should take at most 200ms to
  // initialize.
  {
    fidl::WireResult result =
        reset_gpio_->SetBufferMode(fuchsia_hardware_gpio::BufferMode::kOutputLow);
    if (!result.ok()) {
      fdf::error("Failed to send SetBufferMode request to reset gpio: {}", result.status_string());
      return zx::error(result.status());
    }
    if (result->is_error()) {
      fdf::error("Failed to configure reset gpio to output: {}",
                 zx_status_get_string(result->error_value()));
      return result->take_error();
    }
  }
  zx::nanosleep(zx::deadline_after(zx::msec(5)));
  {
    fidl::WireResult result =
        reset_gpio_->SetBufferMode(fuchsia_hardware_gpio::BufferMode::kOutputHigh);
    if (!result.ok()) {
      fdf::error("Failed to send Write request to reset gpio: {}", result.status_string());
      return zx::error(result.status());
    }
    if (result->is_error()) {
      fdf::error("Failed to write to reset gpio: {}", zx_status_get_string(result->error_value()));
      return result->take_error();
    }
  }
  zx::nanosleep(zx::deadline_after(zx::msec(200)));

  zx_status_t status = UpdateFirmwareIfNeeded(device_info, panel_type);
  if (status != ZX_OK) {
    fdf::error("Failed to update firmware: {}", zx_status_get_string(status));
    return zx::error(status);
  }

  node_ = inspector_.GetRoot().CreateChild("Chip_info");
  LogRegisterValue(FTS_REG_TYPE, "TYPE");
  LogRegisterValue(FTS_REG_FIRMID, "FIRMID");
  LogRegisterValue(FTS_REG_VENDOR_ID, "VENDOR_ID");
  LogRegisterValue(FTS_REG_PANEL_ID, "PANEL_ID");
  LogRegisterValue(FTS_REG_RELEASE_ID_HIGH, "RELEASE_ID_HIGH");
  LogRegisterValue(FTS_REG_RELEASE_ID_LOW, "RELEASE_ID_LOW");
  LogRegisterValue(FTS_REG_IC_VERSION, "IC_VERSION");

  node_.CreateBool("needs_firmware_update", device_info.needs_firmware().value(), &values_);
  node_.CreateUint("panel_type", static_cast<uint32_t>(panel_type), &values_);
  fdf::info("Panel type: {}", static_cast<uint32_t>(panel_type));

  // These names must match the strings in //src/diagnostics/config/sampler/input.json.
  metrics_root_ = inspector_.GetRoot().CreateChild("hid-input-report-touch");
  average_latency_usecs_ = metrics_root_.CreateUint("average_latency_usecs", 0);
  max_latency_usecs_ = metrics_root_.CreateUint("max_latency_usecs", 0);
  total_report_count_ = metrics_root_.CreateUint("total_report_count", 0);
  last_event_timestamp_ = metrics_root_.CreateUint("last_event_timestamp", 0);

  zx::result result = outgoing()->AddService<fuchsia_input_report::Service>(
      fuchsia_input_report::Service::InstanceHandler({
          .input_device = bindings_.CreateHandler(this, dispatcher(), fidl::kIgnoreBindingClosure),
      }));
  if (result.is_error()) {
    fdf::error("Failed to add input report service: {}", result);
    return result.take_error();
  }

  zx::result child = AddOwnedChild(kChildNodeName);
  if (child.is_error()) {
    fdf::error("Failed to add child: {}", child);
    return child.take_error();
  }
  child_ = std::move(child.value());

  return zx::ok();
}

void FtDevice::GetInputReportsReader(GetInputReportsReaderRequestView request,
                                     GetInputReportsReaderCompleter::Sync& completer) {
  ZX_PANIC("GetInputReportsReader (v1) is no longer supported; use GetInputReportsReaderV2");
}

void FtDevice::GetInputReportsReaderV2(GetInputReportsReaderV2RequestView request,
                                       GetInputReportsReaderV2Completer::Sync& completer) {
  const uint16_t max_unacknowledged_reports =
      std::clamp<uint16_t>(request->max_unacknowledged_reports_limit, 1, kHalfSecondReportCount);
  if (request->max_unacknowledged_reports_limit != max_unacknowledged_reports) {
    fdf::warn("GetInputReportsReaderV2: requested limit {} clamped to {}",
              request->max_unacknowledged_reports_limit, max_unacknowledged_reports);
  }
  zx_status_t status =
      readers_.CreateReaderV2(dispatcher(), std::move(request->reader), max_unacknowledged_reports);
  if (status != ZX_OK) {
    fdf::error("Failed to create a reader v2 {}", zx_status_get_string(status));
    completer.Close(status);
    return;
  }
  completer.Reply(max_unacknowledged_reports);
}

void FtDevice::GetDescriptor(GetDescriptorCompleter::Sync& completer) {
  fidl::Arena<kFeatureAndDescriptorBufferSize> allocator;

  auto device_info = fuchsia_input_report::wire::DeviceInformation::Builder(allocator);
  device_info.vendor_id(static_cast<uint32_t>(fuchsia_input_report::wire::VendorId::kGoogle));
  device_info.product_id(static_cast<uint32_t>(
      fuchsia_input_report::wire::VendorGoogleProductId::kFocaltechTouchscreen));
  device_info.manufacturer_name(allocator, "FocalTech");
  device_info.product_name(allocator, "FocalTech Touchscreen");

  fidl::VectorView<fuchsia_input_report::wire::ContactInputDescriptor> contacts(allocator,
                                                                                kMaxPoints);
  for (auto& c : contacts) {
    c = fuchsia_input_report::wire::ContactInputDescriptor::Builder(allocator)
            .position_x(XYAxis(x_max_))
            .position_y(XYAxis(y_max_))
            .Build();
  }

  const auto input = fuchsia_input_report::wire::TouchInputDescriptor::Builder(allocator)
                         .touch_type(fuchsia_input_report::wire::TouchType::kTouchscreen)
                         .max_contacts(kMaxPoints)
                         .contacts(contacts)
                         .Build();

  const auto touch =
      fuchsia_input_report::wire::TouchDescriptor::Builder(allocator).input(input).Build();

  const auto descriptor = fuchsia_input_report::wire::DeviceDescriptor::Builder(allocator)
                              .device_information(device_info.Build())
                              .touch(touch)
                              .Build();

  completer.Reply(descriptor);
}

// simple i2c read for reading one register location
//  intended mostly for debug purposes
zx::result<uint8_t> FtDevice::Read(uint8_t addr) {
  std::array<uint8_t, 1> rbuf;
  zx::result result = i2c_.WriteReadSync(std::array<uint8_t, 1>{addr}, rbuf);
  if (result.is_error()) {
    fdf::error("Failed to write and read: {}", result);
    return result.take_error();
  }
  return zx::ok(rbuf[0]);
}

zx::result<> FtDevice::Read(uint8_t addr, std::span<uint8_t> dst) {
  // TODO(bradenkell): Remove this workaround when transfers of more than 8 bytes are supported on
  // the MT8167.
  size_t offset = 0;

  while (offset < dst.size()) {
    const size_t remaining = dst.size() - offset;
    const size_t transfer_size = std::min(remaining, kMaxI2cTransferLength);
    const std::array<uint8_t, 1> write_data = {static_cast<uint8_t>(addr + offset)};

    zx::result result = i2c_.WriteReadSync(write_data, dst.subspan(offset, transfer_size));
    if (result.is_error()) {
      fdf::error("Failed to read i2c: {}", result);
      return result.take_error();
    }

    offset += transfer_size;
  }

  return zx::ok();
}

void FtDevice::LogRegisterValue(uint8_t addr, std::string_view name) {
  zx::result result = Read(addr);
  if (result.is_ok()) {
    uint8_t value = result.value();
    node_.CreateByteVector(name, {&value, sizeof(value)}, &values_);
    fdf::info("  {:16}: {:#02x}", name, value);
  } else {
    node_.CreateString(name, "error", &values_);
    fdf::error("  {:16}: error {}", name, result);
  }
}

}  // namespace ft

FUCHSIA_DRIVER_EXPORT2(ft::FtDevice);
