// Copyright 2016 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/input_interpreter.h"

#include <fuchsia/ui/input/cpp/fidl.h>
#include <hid-parser/parser.h>
#include <hid-parser/report.h>
#include <hid-parser/usages.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/ui/input/cpp/formatting.h>
#include <src/lib/fxl/arraysize.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/time/time_point.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <trace/event.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include "garnet/bin/ui/input_reader/device.h"
#include "garnet/bin/ui/input_reader/fdio_hid_decoder.h"
#include "garnet/bin/ui/input_reader/protocols.h"

namespace {

int64_t InputEventTimestampNow() {
  return fxl::TimePoint::Now().ToEpochDelta().ToNanoseconds();
}

fuchsia::ui::input::InputReport CloneReport(
    const fuchsia::ui::input::InputReport& report) {
  fuchsia::ui::input::InputReport result;
  fidl::Clone(report, &result);
  return result;
}

}  // namespace

namespace ui_input {

InputInterpreter::InputInterpreter(
    std::unique_ptr<HidDecoder> hid_decoder,
    fuchsia::ui::input::InputDeviceRegistry* registry)
    : registry_(registry), hid_decoder_(std::move(hid_decoder)) {
  FXL_DCHECK(hid_decoder_);
}

InputInterpreter::~InputInterpreter() {}

bool InputInterpreter::Initialize() {
  if (!hid_decoder_->Init())
    return false;

  if (!ParseProtocol())
    return false;

  hardcoded_.Initialize(protocol_);

  event_ = hid_decoder_->GetEvent();
  if (!event_)
    return false;

  NotifyRegistry();
  return true;
}

void InputInterpreter::NotifyRegistry() {
  hardcoded_.NotifyRegistry(registry_);

  // Register the generic device's descriptors.
  for (size_t i = 0; i < devices_.size(); i++) {
    fuchsia::ui::input::DeviceDescriptor descriptor;
    InputDevice& device = devices_[i];
    if (device.descriptor.has_keyboard) {
      fidl::Clone(device.descriptor.keyboard_descriptor, &descriptor.keyboard);
    }
    if (device.descriptor.has_mouse) {
      fidl::Clone(device.descriptor.mouse_descriptor, &descriptor.mouse);
    }
    if (device.descriptor.has_stylus) {
      fidl::Clone(device.descriptor.stylus_descriptor, &descriptor.stylus);
    }
    if (device.descriptor.has_touchscreen) {
      fidl::Clone(device.descriptor.touchscreen_descriptor,
                  &descriptor.touchscreen);
    }
    if (device.descriptor.has_sensor) {
      fidl::Clone(device.descriptor.sensor_descriptor, &descriptor.sensor);
    }
    if (device.descriptor.has_media_buttons) {
      fidl::Clone(device.descriptor.buttons_descriptor,
                  &descriptor.media_buttons);
    }
    registry_->RegisterDevice(std::move(descriptor),
                              device.input_device.NewRequest());
  }
}

bool InputInterpreter::Read(bool discard) {
  TRACE_DURATION("input", "hid_read");

  // If positive |rc| is the number of bytes read. If negative the error
  // while reading.
  int rc = 1;
  auto report = hid_decoder_->Read(&rc);

  if (rc < 1) {
    FXL_LOG(ERROR) << "Failed to read from input: " << rc << " for " << name();
    // TODO(cpu) check whether the device was actually closed or not.
    return false;
  }

  hardcoded_.Read(report, rc, discard);

  for (size_t i = 0; i < devices_.size(); i++) {
    InputDevice& device = devices_[i];
    if (device.device->ReportId() != 0 &&
        device.device->ReportId() != report[0]) {
      continue;
    }
    if (device.device->ParseReport(report.data(), rc, device.report.get())) {
      if (!discard) {
        device.report->event_time = InputEventTimestampNow();
        device.report->trace_id = TRACE_NONCE();
        TRACE_FLOW_BEGIN("input", "hid_read_to_listener",
                         device.report->trace_id);
        device.input_device->DispatchReport(CloneReport(*device.report));
      }
    }
  }

  return true;
}

Protocol InputInterpreter::ExtractProtocol(hid::Usage input) {
  using ::hid::usage::Consumer;
  using ::hid::usage::Digitizer;
  using ::hid::usage::GenericDesktop;
  using ::hid::usage::Page;
  using ::hid::usage::Sensor;
  struct {
    hid::Usage usage;
    Protocol protocol;
  } usage_to_protocol[] = {
      {{static_cast<uint16_t>(Page::kConsumer),
        static_cast<uint32_t>(Consumer::kConsumerControl)},
       Protocol::MediaButtons},
      {{static_cast<uint16_t>(Page::kDigitizer),
        static_cast<uint32_t>(Digitizer::kTouchScreen)},
       Protocol::Touch},
      {{static_cast<uint16_t>(Page::kDigitizer),
        static_cast<uint32_t>(Digitizer::kTouchPad)},
       Protocol::Touchpad},
      {{static_cast<uint16_t>(Page::kDigitizer),
        static_cast<uint32_t>(Digitizer::kStylus)},
       Protocol::Stylus},
      {{static_cast<uint16_t>(Page::kDigitizer),
        static_cast<uint32_t>(Digitizer::kPen)},
       Protocol::Stylus},
      {{static_cast<uint16_t>(Page::kGenericDesktop),
        static_cast<uint32_t>(GenericDesktop::kMouse)},
       Protocol::Mouse},
      {{static_cast<uint16_t>(Page::kGenericDesktop),
        static_cast<uint32_t>(GenericDesktop::kPointer)},
       Protocol::Pointer},
      // Add more sensors here
  };

  if (input.page == Page::kSensor) {
    return Protocol::Sensor;
  }

  for (auto& j : usage_to_protocol) {
    if (input.page == j.usage.page && input.usage == j.usage.usage) {
      return j.protocol;
    }
  }
  return Protocol::Other;
}

bool InputInterpreter::ParseHidFeatureReportDescriptor(
    const hid::ReportDescriptor& report_desc) {
  // Traverse up the nested collections to the Application collection.
  auto collection = report_desc.input_fields[0].col;
  while (collection != nullptr) {
    if (collection->type == hid::CollectionType::kApplication) {
      break;
    }
    collection = collection->parent;
  }

  if (collection == nullptr) {
    FXL_LOG(INFO) << "Can't process HID feature report descriptor for "
                  << name() << "; Needed a valid Collection but didn't get one";
    return false;
  }

  // If we have a touchscreen feature report then we enable multitouch mode.
  if (collection->usage ==
      hid::USAGE(hid::usage::Page::kDigitizer,
                 hid::usage::Digitizer::kTouchScreenConfiguration)) {
    std::vector<uint8_t> feature_report(report_desc.feature_byte_sz);
    if (report_desc.report_id != 0) {
      feature_report[0] = report_desc.report_id;
    }
    for (size_t i = 0; i < report_desc.feature_count; i++) {
      const hid::ReportField& field = report_desc.input_fields[i];
      if (field.attr.usage ==
          hid::USAGE(hid::usage::Page::kDigitizer,
                     hid::usage::Digitizer::kTouchScreenInputMode)) {
        InsertUint(feature_report.data(), feature_report.size(), field.attr,
                   static_cast<uint32_t>(
                       hid::usage::TouchScreenInputMode::kMultipleInput));
      }
    }
    hid_decoder_->Send(HidDecoder::ReportType::FEATURE, report_desc.report_id,
                       feature_report);
  }
  return true;
}

bool InputInterpreter::ParseHidInputReportDescriptor(
    const hid::ReportDescriptor* input_desc) {
  FXL_CHECK(input_desc);

  // Traverse up the nested collections to the Application collection.
  hid::Collection* collection = input_desc->input_fields[0].col;
  while (collection != nullptr) {
    if (collection->type == hid::CollectionType::kApplication) {
      break;
    }
    collection = collection->parent;
  }

  if (collection == nullptr) {
    FXL_LOG(INFO) << "Can't process HID report descriptor for " << name()
                  << "; Needed a valid Collection but didn't get one";
    return false;
  }

  InputDevice input_device = {};
  input_device.report = fuchsia::ui::input::InputReport::New();

  // Most modern gamepads report themselves as Joysticks. Madness.
  if (collection->usage.page == hid::usage::Page::kGenericDesktop &&
      collection->usage.usage == hid::usage::GenericDesktop::kJoystick &&
      hardcoded_.ParseGamepadDescriptor(input_desc->input_fields,
                                        input_desc->input_count)) {
    protocol_ = Protocol::Gamepad;
    return true;
  } else {
    protocol_ = ExtractProtocol(collection->usage);
    switch (protocol_) {
      case Protocol::LightSensor:
        hardcoded_.ParseAmbientLightDescriptor(input_desc->input_fields,
                                               input_desc->input_count);
        return true;
      case Protocol::MediaButtons: {
        FXL_VLOG(2) << "Device " << name() << " has HID media buttons";

        input_device.device = std::make_unique<Buttons>();
        input_device.report->media_buttons =
            fuchsia::ui::input::MediaButtonsReport::New();
        break;
      }
      case Protocol::Pointer: {
        FXL_VLOG(2) << "Device " << name() << " has HID pointer";

        input_device.device = std::make_unique<Pointer>();
        input_device.report->touchscreen =
            fuchsia::ui::input::TouchscreenReport::New();
        break;
      }
      case Protocol::Sensor: {
        FXL_VLOG(2) << "Device " << name() << " has HID sensor";

        input_device.device = std::make_unique<Sensor>();
        input_device.report->sensor = fuchsia::ui::input::SensorReport::New();
        break;
      }
      case Protocol::Touchpad: {
        FXL_VLOG(2) << "Device " << name() << " has HID touchpad";

        input_device.device = std::make_unique<Touchpad>();
        input_device.report->mouse = fuchsia::ui::input::MouseReport::New();
        break;
      }
      case Protocol::Touch: {
        FXL_VLOG(2) << "Device " << name() << " has HID touch";

        input_device.device = std::make_unique<TouchScreen>();
        input_device.report->touchscreen =
            fuchsia::ui::input::TouchscreenReport::New();
        break;
      }
      case Protocol::Mouse: {
        FXL_VLOG(2) << "Device " << name() << " has HID mouse";

        input_device.device = std::make_unique<Mouse>();
        input_device.report->mouse = fuchsia::ui::input::MouseReport::New();
        break;
      }
      case Protocol::Stylus: {
        FXL_VLOG(2) << "Device " << name() << " has HID stylus";

        input_device.device = std::make_unique<Stylus>();
        input_device.report->stylus = fuchsia::ui::input::StylusReport::New();
        break;
      }
      // Add more protocols here
      default:
        // Not being able to match on a given HID report descriptor is not
        // an error and will happen frequently. We only need to match a single
        // report in the report descriptor to be valid.
        return true;
    }
  }

  if (!input_device.device->ParseReportDescriptor(*input_desc,
                                                  &input_device.descriptor)) {
    FXL_LOG(INFO) << "Can't process HID report descriptor for " << name()
                  << "; Failed to do generic device parsing";
    return false;
  }
  devices_.push_back(std::move(input_device));

  FXL_LOG(INFO) << "hid-parser successful for " << name() << " with usage page "
                << collection->usage.page << " and usage "
                << collection->usage.usage;

  return true;
}

bool InputInterpreter::ParseProtocol() {
  HidDecoder::BootMode boot_mode = hid_decoder_->ReadBootMode();
  // For most keyboards and mouses Zircon requests the boot protocol
  // which has a fixed layout. This covers the following two cases:
  if (boot_mode == HidDecoder::BootMode::KEYBOARD) {
    protocol_ = Protocol::Keyboard;
    return true;
  }
  if (boot_mode == HidDecoder::BootMode::MOUSE) {
    protocol_ = Protocol::BootMouse;
    return true;
  }

  int desc_size;
  auto desc = hid_decoder_->ReadReportDescriptor(&desc_size);
  if (desc_size == 0) {
    return false;
  }

  // See if we match a hardcoded descriptor. This involves memcmp() of the
  // known hardcoded descriptors.
  Protocol protocol = hardcoded_.MatchProtocol(desc, hid_decoder_.get());
  if (protocol != Protocol::Other) {
    protocol_ = protocol;
    return true;
  }

  // For the rest of devices we use the new way; with the hid-parser
  // library.

  hid::DeviceDescriptor* dev_desc = nullptr;
  auto parse_res =
      hid::ParseReportDescriptor(desc.data(), desc.size(), &dev_desc);
  if (parse_res != hid::ParseResult::kParseOk) {
    FXL_LOG(INFO) << "hid-parser: error " << int(parse_res)
                  << " parsing report descriptor for " << name();
    return false;
  }

  auto count = dev_desc->rep_count;
  if (count == 0) {
    FXL_LOG(ERROR) << "no report descriptors for " << name();
    return false;
  }

  // Parse each input report.
  for (size_t rep = 0; rep < count; rep++) {
    const hid::ReportDescriptor* desc = &dev_desc->report[rep];
    if (desc->input_count != 0) {
      if (!ParseHidInputReportDescriptor(desc)) {
        continue;
      }
    }
    if (desc->feature_count != 0) {
      if (!ParseHidFeatureReportDescriptor(*desc)) {
        return false;
      }
    }
  }

  // If we never parsed a single device correctly then fail.
  if (devices_.size() == 0) {
    FXL_LOG(INFO) << "Can't process HID report descriptor for " << name()
                  << "; All parsing attempts failed.";
    return false;
  }

  return true;
}

}  // namespace ui_input
