// Copyright 2017 The Chromium OS 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 <algorithm>
#include <map>
#include <utility>
#include <vector>

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>

#include "u2fd/uhid_device.h"

namespace u2f {

namespace {

const char kUHidNode[] = "/dev/uhid";

const char* GetUhidEventName(int event) {
  switch (event) {
    case UHID_START:
      return "START";
    case UHID_STOP:
      return "STOP";
    case UHID_OPEN:
      return "OPEN";
    case UHID_CLOSE:
      return "CLOSE";
    case UHID_OUTPUT:
      return "OUTPUT";
    default:
      NOTREACHED();
      return "UNKNOWN";
  }
}

}  // namespace

UHidDevice::UHidDevice(uint32_t vendor_id,
                       uint32_t product_id,
                       const std::string& name,
                       const std::string& phys)
    : created_(false),
      vendor_id_(vendor_id),
      product_id_(product_id),
      name_(name),
      phys_(phys) {}

UHidDevice::~UHidDevice() {
  if (created_)
    DestroyDev();
}

bool UHidDevice::Init(uint32_t hid_version, const std::string& report_desc) {
  DCHECK(!fd_.is_valid());
  fd_ = base::ScopedFD(HANDLE_EINTR(open(kUHidNode, O_RDWR)));
  if (!fd_.is_valid()) {
    PLOG(ERROR) << "Cannot open uhid node at " << kUHidNode;
    return false;
  }
  VLOG(1) << kUHidNode << " opened successfully.";

  if (!CreateDev(hid_version, report_desc)) {
    LOG(ERROR) << "Cannot create HID device.";
    return false;
  }
  created_ = true;

  watcher_ = base::FileDescriptorWatcher::WatchReadable(
      fd_.get(), base::Bind(&UHidDevice::FdEvent, base::Unretained(this)));
  if (!watcher_) {
    LOG(ERROR) << "Unable to watch " << kUHidNode << " events";
    return false;
  }

  return true;
}

void UHidDevice::FdEvent() {
  struct uhid_event ev;

  ssize_t ret = read(fd_.get(), &ev, sizeof(ev));
  if (ret < 0) {
    PLOG(ERROR) << "Cannot read uhid";
    return;
  }
  if (ret != sizeof(ev)) {
    LOG(ERROR) << "Read " << ret << " byte(s) from " << kUHidNode
               << "; expected " << sizeof(ev);
    return;
  }

  switch (ev.type) {
    case UHID_START:
    case UHID_STOP:
    case UHID_OPEN:
    case UHID_CLOSE:
      VLOG(2) << "uhid event " << GetUhidEventName(ev.type);
      break;
    case UHID_OUTPUT:
      VLOG(1) << "uhid event " << GetUhidEventName(ev.type);
      if (ev.u.output.rtype != UHID_OUTPUT_REPORT)
        break;
      VLOG(2) << "HID Report: "
              << base::HexEncode(ev.u.output.data, ev.u.output.size);

      if (!on_output_report_.is_null()) {
        std::string report(reinterpret_cast<char*>(ev.u.output.data),
                           ev.u.output.size);
        on_output_report_.Run(report);
      }
      break;
    default:
      LOG(WARNING) << "Invalid event from uhid: " << ev.type;
  }
}

bool UHidDevice::WriteEvent(const struct uhid_event& ev) {
  return base::WriteFileDescriptor(
      fd_.get(), reinterpret_cast<const char*>(&ev), sizeof(ev));
}

bool UHidDevice::SendReport(const std::string& report) {
  if (report.size() > UINT16_MAX)
    return false;

  struct uhid_event ev = {
      .type = UHID_INPUT2,
      .u.input2.size = static_cast<uint16_t>(report.size()),
  };

  if (report.size() > sizeof(ev.u.input2.data))
    return false;

  std::copy(report.begin(), report.end(), ev.u.input2.data);

  return WriteEvent(ev) == 0;
}

bool UHidDevice::CreateDev(uint32_t interface_version,
                           const std::string& report_desc) {
  if (report_desc.size() > UINT16_MAX)
    return false;

  struct uhid_event ev = {
      .type = UHID_CREATE2,
      .u.create2.rd_size = static_cast<uint16_t>(report_desc.size()),
      .u.create2.bus = BUS_VIRTUAL,
      .u.create2.vendor = vendor_id_,
      .u.create2.product = product_id_,
      .u.create2.version = interface_version,
  };
  if (report_desc.size() > sizeof(ev.u.create2.rd_data))
    return false;

  base::strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name_.c_str(),
                sizeof(ev.u.create2.name));
  snprintf(reinterpret_cast<char*>(ev.u.create2.phys),
           sizeof(ev.u.create2.phys), "%s-%04X:%04X", phys_.c_str(),
           ev.u.create2.vendor, ev.u.create2.product);
  memcpy(ev.u.create2.rd_data, report_desc.data(),
         std::min(report_desc.size(), sizeof(ev.u.create2.rd_data)));

  return WriteEvent(ev);
}

void UHidDevice::DestroyDev() {
  const struct uhid_event ev = {.type = UHID_DESTROY};

  WriteEvent(ev);
}

void UHidDevice::SetOutputReportHandler(
    const HidInterface::OutputReportCallback& on_output_report) {
  on_output_report_ = on_output_report;
}

}  // namespace u2f
