// 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 <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/hardware/input/llcpp/fidl.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/watcher.h>
#include <lib/zx/event.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/threads.h>
#include <zircon/types.h>

#include <iterator>
#include <optional>
#include <utility>
#include <vector>

#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <hid-parser/parser.h>
#include <hid-parser/report.h>
#include <hid-parser/units.h>
#include <hid-parser/usages.h>

#include "src/lib/listnode/listnode.h"

// defined in report.cpp
void print_report_descriptor(const uint8_t* rpt_desc, size_t desc_len);

#define DEV_INPUT "/dev/class/input"

static bool verbose = false;
#define xprintf(fmt...) \
  do {                  \
    if (verbose)        \
      printf(fmt);      \
  } while (0)

enum class Command { read, read_all, get, set, descriptor, descriptor_all };

void usage(void) {
  printf("usage: hid [-v] <command> [<args>]\n\n");
  printf("  commands:\n");
  printf("    read [<devpath> [num reads]]\n");
  printf("    get <devpath> <in|out|feature> <id>\n");
  printf("    set <devpath> <in|out|feature> <id> [0xXX *]\n");
  printf("    descriptor [<devpath>]\n");
}

constexpr size_t kDevPathSize = 128;

struct input_args_t {
  Command command;

  std::optional<llcpp::fuchsia::hardware::input::Device::SyncClient> sync_client;

  char devpath[kDevPathSize];
  size_t num_reads;

  llcpp::fuchsia::hardware::input::ReportType report_type;
  uint8_t report_id;

  const char** data;
  size_t data_size;
};

static mtx_t print_lock = MTX_INIT;
#define lprintf(fmt...)      \
  do {                       \
    mtx_lock(&print_lock);   \
    printf(fmt);             \
    mtx_unlock(&print_lock); \
  } while (0)

static void print_hex(const uint8_t* buf, size_t len) {
  for (size_t i = 0; i < len; i++) {
    printf("%02x ", buf[i]);
    if (i % 16 == 15)
      printf("\n");
  }
  printf("\n");
}

static zx_status_t parse_uint_arg(const char* arg, uint32_t min, uint32_t max, uint32_t* out_val) {
  if ((arg == NULL) || (out_val == NULL)) {
    return ZX_ERR_INVALID_ARGS;
  }

  bool is_hex = (arg[0] == '0') && (arg[1] == 'x');
  if (sscanf(arg, is_hex ? "%x" : "%u", out_val) != 1) {
    return ZX_ERR_INVALID_ARGS;
  }

  if ((*out_val < min) || (*out_val > max)) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  return ZX_OK;
}

static zx_status_t parse_input_report_type(const char* arg,
                                           llcpp::fuchsia::hardware::input::ReportType* out_type) {
  if ((arg == NULL) || (out_type == NULL)) {
    return ZX_ERR_INVALID_ARGS;
  }

  static const struct {
    const char* name;
    llcpp::fuchsia::hardware::input::ReportType type;
  } LUT[] = {
      {.name = "in", .type = llcpp::fuchsia::hardware::input::ReportType::INPUT},
      {.name = "out", .type = llcpp::fuchsia::hardware::input::ReportType::OUTPUT},
      {.name = "feature", .type = llcpp::fuchsia::hardware::input::ReportType::FEATURE},
  };

  for (size_t i = 0; i < std::size(LUT); ++i) {
    if (!strcasecmp(arg, LUT[i].name)) {
      *out_type = LUT[i].type;
      return ZX_OK;
    }
  }

  return ZX_ERR_INVALID_ARGS;
}

static zx_status_t print_hid_protocol(input_args_t* args) {
  auto result = args->sync_client->GetBootProtocol();
  if (result.status() != ZX_OK) {
    lprintf("hid: could not get protocol from %s (status=%d)\n", args->devpath, result.status());
  } else {
    lprintf("hid: %s proto=%d\n", args->devpath, static_cast<uint32_t>(result->protocol));
  }
  return ZX_OK;
}

static zx_status_t print_report_desc(input_args_t* args) {
  auto result = args->sync_client->GetReportDesc();
  if (result.status() != ZX_OK) {
    lprintf("hid: could not get report descriptor from %s (status=%d)\n", args->devpath,
            result.status());
    return result.status();
  }

  lprintf("hid: %s report descriptor len=%zu\n", args->devpath, result->desc.count());

  mtx_lock(&print_lock);
  printf("hid: %s report descriptor:\n", args->devpath);
  print_hex(result->desc.data(), result->desc.count());
  if (verbose) {
    print_report_descriptor(result->desc.data(), result->desc.count());
  }
  mtx_unlock(&print_lock);
  return ZX_OK;
}

#define TRY(fn)              \
  do {                       \
    zx_status_t status = fn; \
    if (status != ZX_OK)     \
      return status;         \
  } while (0)

static zx_status_t print_hid_status(input_args_t* args) {
  TRY(print_hid_protocol(args));

  hid::DeviceDescriptor* dev_desc = nullptr;
  {
    auto result = args->sync_client->GetReportDesc();
    if (result.status() != ZX_OK) {
      return result.status();
    }
    auto parse_result =
        hid::ParseReportDescriptor(result->desc.data(), result->desc.count(), &dev_desc);
    if (parse_result != hid::ParseResult::kParseOk) {
      return ZX_ERR_INTERNAL;
    }
  }
  auto ac = fbl::MakeAutoCall([&dev_desc]() { hid::FreeDeviceDescriptor(dev_desc); });

  mtx_lock(&print_lock);
  printf("hid: %s num reports: %zu\n", args->devpath, dev_desc->rep_count);

  printf("hid: %s report ids...\n", args->devpath);
  for (size_t i = 0; i < dev_desc->rep_count; i++) {
    if (dev_desc->report[i].input_byte_sz != 0) {
      printf("  ID 0x%02x : TYPE %7s : SIZE %lu bytes\n", dev_desc->report[i].report_id, "Input",
             dev_desc->report[i].input_byte_sz);
    }
    if (dev_desc->report[i].output_byte_sz != 0) {
      printf("  ID 0x%02x : TYPE %7s : SIZE %lu bytes\n", dev_desc->report[i].report_id, "Output",
             dev_desc->report[i].output_byte_sz);
    }
    if (dev_desc->report[i].feature_byte_sz != 0) {
      printf("  ID 0x%02x : TYPE %7s : SIZE %lu bytes\n", dev_desc->report[i].report_id, "Feature",
             dev_desc->report[i].feature_byte_sz);
    }
  }
  mtx_unlock(&print_lock);

  return ZX_OK;
}

static zx_status_t parse_rpt_descriptor(input_args_t* args) {
  TRY(print_report_desc(args));
  return ZX_OK;
}

#undef TRY

static zx_status_t hid_input_read_report(input_args_t* args, const zx::event& report_event,
                                         size_t report_size, uint8_t* report_data,
                                         size_t* returned_size) {
  while (true) {
    auto result = args->sync_client->ReadReport();
    if (result.status() != ZX_OK) {
      return result.status();
    }
    if (result->status == ZX_ERR_SHOULD_WAIT) {
      report_event.wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr);
      continue;
    }
    if (result->data.count() > report_size) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    *returned_size = result->data.count();
    memcpy(report_data, result->data.data(), result->data.count());

    return ZX_OK;
  }
}

static int hid_read_reports(input_args_t* args) {
  zx_status_t status = print_hid_status(args);
  if (status != ZX_OK) {
    return static_cast<int>(status);
  }

  zx::event report_event;
  auto result = args->sync_client->GetReportsEvent();
  if ((result.status() != ZX_OK) || (result->status != ZX_OK)) {
    mtx_lock(&print_lock);
    printf("read returned error: (call_status=%d) (status=%d)\n", result.status(), result->status);
    mtx_unlock(&print_lock);
    return ZX_ERR_INTERNAL;
  }
  report_event = std::move(result->event);

  std::vector<uint8_t> report(llcpp::fuchsia::hardware::input::MAX_REPORT_LEN);
  for (uint32_t i = 0; i < args->num_reads; i++) {
    size_t returned_size;
    status =
        hid_input_read_report(args, report_event, report.size(), report.data(), &returned_size);
    if (status != ZX_OK) {
      mtx_lock(&print_lock);
      printf("hid_input_read_report returned %d\n", status);
      mtx_unlock(&print_lock);
      break;
    }

    mtx_lock(&print_lock);
    printf("read returned %ld bytes\n", returned_size);
    printf("hid: input from %s\n", args->devpath);
    print_hex(report.data(), returned_size);
    mtx_unlock(&print_lock);
  }

  lprintf("hid: closing %s\n", args->devpath);
  return ZX_OK;
}

static int hid_input_thread(void* arg) {
  input_args_t* args = (input_args_t*)arg;
  lprintf("hid: thread started for %s\n", args->devpath);

  zx_status_t status = ZX_OK;
  if (args->command == Command::read) {
    status = hid_read_reports(args);
  } else if (args->command == Command::descriptor) {
    status = parse_rpt_descriptor(args);
  } else {
    lprintf("hid: thread found wrong command %d\n", args->command);
  }

  delete args;
  return status;
}

static zx_status_t hid_input_device_added(int dirfd, int event, const char* fn, void* cookie) {
  if (event != WATCH_EVENT_ADD_FILE) {
    return ZX_OK;
  }

  int fd = openat(dirfd, fn, O_RDONLY);
  if (fd < 0) {
    return ZX_OK;
  }

  input_args_t* args = new input_args_t;
  args->command = *reinterpret_cast<Command*>(cookie);

  zx::channel chan;
  zx_status_t status = fdio_get_service_handle(fd, chan.reset_and_get_address());
  if (status != ZX_OK) {
    return status;
  }
  args->sync_client = llcpp::fuchsia::hardware::input::Device::SyncClient(std::move(chan));

  // TODO: support setting num_reads across all devices. requires a way to
  // signal shutdown to all input threads.
  args->num_reads = ULONG_MAX;
  snprintf(args->devpath, kDevPathSize, "%s", fn);

  thrd_t t;
  int ret = thrd_create_with_name(&t, hid_input_thread, (void*)args, args->devpath);
  if (ret != thrd_success) {
    printf("hid: thread %s did not start (error=%d)\n", args->devpath, ret);
    close(fd);
    return thrd_status_to_zx_status(ret);
  }
  thrd_detach(t);
  return ZX_OK;
}

int watch_all_devices(Command command) {
  int dirfd = open(DEV_INPUT, O_DIRECTORY | O_RDONLY);
  if (dirfd < 0) {
    printf("hid: error opening %s\n", DEV_INPUT);
    return ZX_ERR_INTERNAL;
  }
  fdio_watch_directory(dirfd, hid_input_device_added, ZX_TIME_INFINITE, &command);
  close(dirfd);
  return 0;
}

// Get a single report from the device with a given report id and then print it.
int get_report(input_args_t* args) {
  auto result = args->sync_client->GetReport(args->report_type, args->report_id);
  if (result.status() != ZX_OK || result->status != ZX_OK) {
    printf("hid: could not get report: %d, %d\n", result.status(), result->status);
    return -1;
  }

  printf("hid: got %zu bytes\n", result->report.count());
  print_hex(result->report.data(), result->report.count());
  return 0;
}

int set_report(input_args_t* args) {
  xprintf("hid: setting report (id=0x%02x payload size=%lu)\n", args->report_id, args->data_size);

  std::unique_ptr<uint8_t[]> report(new uint8_t[args->data_size]);
  for (size_t i = 0; i < args->data_size; i++) {
    uint32_t tmp;
    zx_status_t res = parse_uint_arg(args->data[i], 0, 255, &tmp);
    if (res != ZX_OK) {
      printf("Failed to parse payload byte \"%s\" (res = %d)\n", args->data[i], res);
      return res;
    }

    report[i] = static_cast<uint8_t>(tmp);
  }

  fidl::VectorView<uint8_t> report_view =
      fidl::VectorView<uint8_t>(fidl::unowned_ptr(report.get()), args->data_size);
  auto res =
      args->sync_client->SetReport(args->report_type, args->report_id, std::move(report_view));
  if (res.status() != ZX_OK || res->status != ZX_OK) {
    printf("hid: could not set report: %d, %d\n", res.status(), res->status);
    return -1;
  }

  printf("hid: success\n");
  return 0;
}

zx_status_t parse_input_args(int argc, const char** argv, input_args_t* args) {
  zx_status_t status;
  // Move past the first arg which is just the binary.
  argc--;
  argv++;

  if (argc == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (!strcmp("-v", argv[0])) {
    verbose = true;
    argc--;
    argv++;
  }

  if (argc == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  // Parse the command name.
  if (!strcmp("read", argv[0])) {
    if (argc == 1) {
      args->command = Command::read_all;
      return ZX_OK;
    }
    args->command = Command::read;
  } else if (!strcmp("get", argv[0])) {
    args->command = Command::get;
  } else if (!strcmp("set", argv[0])) {
    args->command = Command::set;
  } else if (!strcmp("descriptor", argv[0])) {
    if (argc == 1) {
      args->command = Command::descriptor_all;
      return ZX_OK;
    }
    args->command = Command::descriptor;
  } else {
    return ZX_ERR_INVALID_ARGS;
  }

  if (argc < 2) {
    return ZX_ERR_INVALID_ARGS;
  }

  // Parse <devpath>
  int fd = open(argv[1], O_RDWR);
  if (fd < 0) {
    printf("could not open %s: %d\n", argv[0], errno);
    return ZX_ERR_INTERNAL;
  }
  zx::channel chan;
  status = fdio_get_service_handle(fd, chan.reset_and_get_address());
  if (status != ZX_OK) {
    return status;
  }
  args->sync_client = llcpp::fuchsia::hardware::input::Device::SyncClient(std::move(chan));
  snprintf(args->devpath, kDevPathSize, "%s", argv[1]);

  if (args->command == Command::descriptor) {
    if (argc > 2) {
      return ZX_ERR_INTERNAL;
    }
    return ZX_OK;
  }

  // Parse Read arguments.
  if (args->command == Command::read) {
    if (argc == 3) {
      uint32_t tmp = std::numeric_limits<uint32_t>::max();
      status = parse_uint_arg(argv[2], 0, std::numeric_limits<uint32_t>::max(), &tmp);
      if (status != ZX_OK) {
        return status;
      }
      args->num_reads = tmp;
    } else if (argc == 2) {
      args->num_reads = std::numeric_limits<uint32_t>::max();
    } else {
      return ZX_ERR_INVALID_ARGS;
    }
    return ZX_OK;
  }

  if (argc < 4) {
    return ZX_ERR_INTERNAL;
  }

  // Parse ReportType argument.
  llcpp::fuchsia::hardware::input::ReportType report_type;
  status = parse_input_report_type(argv[2], &report_type);
  if (status != ZX_OK) {
    return status;
  }
  args->report_type = report_type;

  // Parse Report id.
  uint32_t report_id = 255;
  status = parse_uint_arg(argv[3], 0, 255, &report_id);
  if (status != ZX_OK) {
    return status;
  }
  args->report_id = static_cast<uint8_t>(report_id);

  if ((args->command == Command::get) && (argc > 4)) {
    return ZX_ERR_INVALID_ARGS;
  }

  if ((args->command == Command::set) && (argc > 4)) {
    args->data_size = argc - 4;
    args->data = &argv[4];
  }

  return ZX_OK;
}

int main(int argc, const char** argv) {
  input_args_t args = {};
  zx_status_t status = parse_input_args(argc, argv, &args);
  if (status != ZX_OK) {
    usage();
    return 1;
  }

  if (args.command == Command::descriptor) {
    return parse_rpt_descriptor(&args);
  } else if (args.command == Command::get) {
    return get_report(&args);
  } else if (args.command == Command::set) {
    return set_report(&args);
  } else if (args.command == Command::read) {
    return hid_read_reports(&args);
  } else if (args.command == Command::read_all) {
    return watch_all_devices(Command::read);
  } else if (args.command == Command::descriptor_all) {
    return watch_all_devices(Command::descriptor);
  }

  return 1;
}
