// Copyright 2014 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 "permission_broker/hidraw_subsystem_udev_rule.h"

#include <fcntl.h>
#include <libudev.h>
#include <linux/hidraw.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <string>

#include "base/logging.h"

using std::string;

namespace permission_broker {

namespace {

const int kShortHeaderLength = 1;
const int kLongHeaderLength = 3;

enum ItemType {
  TYPE_MAIN = 0,
  TYPE_GLOBAL = 1,
  TYPE_LOCAL = 2,
  TYPE_RESERVED = 3
};

enum MainItemTag {
  MAIN_TAG_DEFAULT = 0x00,
  MAIN_TAG_INPUT = 0x08,
  MAIN_TAG_OUTPUT = 0x09,
  MAIN_TAG_COLLECTION = 0x0a,
  MAIN_TAG_FEATURE = 0x0b,
  MAIN_TAG_END_COLLECTION = 0x0c
};

enum GlobalItemTag {
  GLOBAL_TAG_USAGE_PAGE = 0x00,
  GLOBAL_TAG_LOGICAL_MINIMUM = 0x01,
  GLOBAL_TAG_LOGICAL_MAXIMUM = 0x02,
  GLOBAL_TAG_PHYSICAL_MINIMUM = 0x03,
  GLOBAL_TAG_PHYSICAL_MAXIMUM = 0x04,
  GLOBAL_TAG_UNIT_EXPONENT = 0x05,
  GLOBAL_TAG_UNIT = 0x06,
  GLOBAL_TAG_REPORT_SIZE = 0x07,
  GLOBAL_TAG_REPORT_ID = 0x08,
  GLOBAL_TAG_REPORT_COUNT = 0x09,
  GLOBAL_TAG_PUSH = 0x0A,
  GLOBAL_TAG_POP = 0x0B
};

enum LocalItemTag {
  LOCAL_TAG_USAGE = 0x00,
  LOCAL_TAG_USAGE_MINIMUM = 0x01,
  LOCAL_TAG_USAGE_MAXIMUM = 0x02,
  LOCAL_TAG_DESIGNATOR_INDEX = 0x03,
  LOCAL_TAG_DESIGNATOR_MINIMUM = 0x04,
  LOCAL_TAG_DESIGNATOR_MAXIMUM = 0x05,
  LOCAL_TAG_STRING_INDEX = 0x07,
  LOCAL_TAG_STRING_MINIMUM = 0x08,
  LOCAL_TAG_STRING_MAXIMUM = 0x09,
  LOCAL_TAG_DELIMITER = 0x0A
};

enum ReservedItemTag {
  RESERVED_TAG_LONG = 0x0f,
};

struct DescriptorItem {
  ItemType type;
  union {
    MainItemTag main;
    GlobalItemTag global;
    LocalItemTag local;
    ReservedItemTag reserved;
    uint32_t raw;
  } tag;
  uint32_t data_value;
  int depth;
};

// Attempts to populate a ReportDescriptor for a given hidraw device.
bool GetHidReportDescriptor(struct udev_device* device,
                            HidReportDescriptor* descriptor) {
  const char* dev_node = udev_device_get_devnode(device);
  int device_fd = open(dev_node, O_RDONLY);
  if (device_fd < 0) {
    return false;
  }
  unsigned size = 0;
  if (ioctl(device_fd, HIDIOCGRDESCSIZE, &size) < 0) {
    close(device_fd);
    return false;
  }
  hidraw_report_descriptor report_descriptor;
  report_descriptor.size = size;
  if (size > sizeof(report_descriptor.value) ||
      ioctl(device_fd, HIDIOCGRDESC, &report_descriptor) < 0) {
    close(device_fd);
    return false;
  }
  close(device_fd);
  if (report_descriptor.size > sizeof(descriptor->data)) {
    return false;
  }
  descriptor->size = report_descriptor.size;
  memcpy(&descriptor->data[0], &report_descriptor.value[0], descriptor->size);
  return true;
}

bool ParseDescriptorItem(const HidReportDescriptor& descriptor,
                         int offset,
                         int current_depth,
                         DescriptorItem* item,
                         int* bytes_read,
                         int* new_depth) {
  if (offset >= descriptor.size)
    return false;
  uint8_t header = descriptor.data[offset];
  int data_size = header & 0x03;
  item->type = static_cast<ItemType>((header >> 2) & 0x03);
  item->tag.raw = (header & 0xf0) >> 4;
  item->depth = current_depth;
  item->data_value = 0;

  // Long-form items are ignored.
  if (item->type == TYPE_RESERVED && item->tag.reserved == RESERVED_TAG_LONG) {
    if (offset + kShortHeaderLength >= descriptor.size) {
      return false;
    }
    int long_descriptor_size = descriptor.data[offset + kShortHeaderLength];
    *bytes_read = kLongHeaderLength + long_descriptor_size;
    return true;
  }

  if (offset + data_size + 1 > descriptor.size) {
    return false;
  }
  memcpy(&item->data_value, &descriptor.data[offset + 1], data_size);
  *bytes_read = kShortHeaderLength + data_size;

  if (item->type != TYPE_MAIN) {
    return true;
  }

  if (item->tag.main == MAIN_TAG_END_COLLECTION) {
    if (current_depth == 0) {
      return false;
    }
    *new_depth = current_depth - 1;
  } else if (item->tag.main == MAIN_TAG_COLLECTION) {
    *new_depth = current_depth + 1;
  }

  return true;
}

// Attempts to extract all toplevel items from a descriptor, preserving order.
// Returns false if any header contents are missing or invalid.
bool ParseToplevelDescriptorItems(const HidReportDescriptor& descriptor,
                                  std::vector<DescriptorItem>* items) {
  int depth = 0;
  int offset = 0;
  while (offset < descriptor.size) {
    int bytes_read;
    DescriptorItem item;
    if (!ParseDescriptorItem(descriptor, offset, depth, &item, &bytes_read,
                             &depth)) {
      return false;
    }
    if (item.depth == 0) {
      items->push_back(item);
    }
    offset += bytes_read;
  }
  return offset == descriptor.size;
}

}  // namespace

HidrawSubsystemUdevRule::HidrawSubsystemUdevRule(const string& name)
    : Rule(name) {}

Rule::Result HidrawSubsystemUdevRule::ProcessDevice(
    struct udev_device* device) {
  const char* const subsystem = udev_device_get_subsystem(device);
  if (!subsystem || strcmp(subsystem, "hidraw"))
    return IGNORE;
  return ProcessHidrawDevice(device);
}

// static
bool HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
    const HidReportDescriptor& descriptor, std::vector<HidUsage>* usages) {
  std::vector<DescriptorItem> items;
  if (!ParseToplevelDescriptorItems(descriptor, &items)) {
    return false;
  }
  for (int i = 0; i < static_cast<int>(items.size()) - 2; ++i) {
    DescriptorItem& first = items[i];
    if (first.type != TYPE_GLOBAL || first.tag.global != GLOBAL_TAG_USAGE_PAGE)
      continue;
    DescriptorItem& second = items[i + 1];
    if (second.type != TYPE_LOCAL || second.tag.local != LOCAL_TAG_USAGE)
      continue;
    DescriptorItem& third = items[i + 2];
    if (third.type != TYPE_MAIN || third.tag.main != MAIN_TAG_COLLECTION)
      continue;
    usages->push_back(HidUsage(static_cast<HidUsage::Page>(first.data_value),
                               static_cast<uint16_t>(second.data_value)));
  }
  return true;
}

// static
bool HidrawSubsystemUdevRule::GetHidToplevelUsages(
    struct udev_device* device, std::vector<HidUsage>* usages) {
  const char* dev_node = udev_device_get_devnode(device);

  HidReportDescriptor descriptor;
  if (!GetHidReportDescriptor(device, &descriptor)) {
    LOG(INFO) << "Unable to query descriptor for " << dev_node;
    return false;
  }

  if (!ParseToplevelCollectionUsages(descriptor, usages)) {
    LOG(INFO) << "Error parsing descriptor for " << dev_node;
    return false;
  }

  return true;
}

}  // namespace permission_broker
