// Copyright 2017 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 <fbl/alloc_checker.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/vector.h>
#include <hid-parser/item.h>
#include <hid-parser/parser.h>

namespace {

#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))

// Temporary structure to keep report id data.
struct ReportID {
  bool has_report_id;
  uint8_t report_id;
  size_t input_count;
  size_t output_count;
  size_t feature_count;
};

// Takes a every bit from 0 to 15 and converts them into a
// 01 if 1 or 10 if 0.
uint32_t expand_bitfield(uint32_t bitfield) {
  uint32_t result = 0u;
  for (uint8_t ix = 0; ix != 16; ++ix) {
    uint32_t twobit = (bitfield & 0x1) ? 0x02 : 0x01;
    result |= twobit << (2 * ix);
    bitfield >>= 1;
  }
  return result;
}

// Helper template class that translates pointers from two different
// array allocations using memory offsets.
template <typename T>
class Fixup {
 public:
  Fixup(const T* src_base, T* dest_base) : src_base_(src_base), dest_base_(dest_base) {}

  T* operator()(const T* src) {
    return (src == nullptr) ? nullptr : dest_base_ + (src - src_base_);
  }

 private:
  const T* const src_base_;
  T* const dest_base_;
};

}  // namespace

namespace hid {
namespace impl {

// Parsing hid report descriptors is is complicated by the fact that
// there is a fair amount of flexibility on the format. In particular
// the format is to be understood as an opcode-based program that
// sets either some global or local state that at defined points is
// converted in a series of fields.
//
// The expected top level structure is:
//
//  App-Collection --> [Collection ... Collection] -->
//
// Followed by one or more [Input] [Output] [Feature] items, then
// followed by one or more end-collection items.
//
// This is however insufficient. Other items are interspersed that
// qualify the above items, both in purpose and in actual report
// layout.
//
// An example for the simplest mouse input report is instructive:
//
//  Collection-Application(Desktop, Mouse) {
//      Collection-Physical(Pointer) {
//          Input(1-bit, Data, Button, (1,0))
//          Input(1-bit, Data, Button, (1,0))
//          Input(1-bit, Data, Button, (1,0))
//          Input(5-bit, Padding, Button)
//          Input(8-bit, Data, X, (127,-127))
//          Input(8-bit, Data, Y, (127,-127))
//      }
//  }
//
//  All the qualifiers above inside "(" and ")" are opcodes
//  interspersed before the collection or input,output,feature
//  items. The system/utest/hid-parser has many examples captured
//  from real devices.

// Limit on the collection count we can process, complicated devices
// such as touch-pad are in the 10 to 20 range. This limitation can be
// removed with a bit more code if needed. To note, the other variable
// items such fields in a report are only limited by available memory.
constexpr size_t kMaxCollectionCount = 128u;

bool is_valid_collection(uint32_t col) {
  return (col <= static_cast<uint32_t>(CollectionType::kVendor));
}

bool is_app_collection(uint32_t col) {
  return (col == static_cast<uint32_t>(CollectionType::kApplication));
}

bool report_id_has_items(ReportID id) {
  return (id.input_count != 0) || (id.feature_count != 0) || (id.output_count != 0);
}

class ParseState {
 public:
  static char* Alloc(size_t size) {
    fbl::AllocChecker ac;
    auto mem = new (&ac) char[size];
    return ac.check() ? mem : nullptr;
  }

  static void Free(void* mem) { delete[] reinterpret_cast<char*>(mem); }

  ParseState() : usage_range_(), table_(), parent_coll_(nullptr) {
    // First 8 bits of a report are the report ID.
    table_.attributes.offset = 8;
  }

  bool Init() {
    fbl::AllocChecker ac;
    coll_.reserve(kMaxCollectionCount, &ac);
    if (!ac.check())
      return false;

    // Add the initial report ID representing "no report_id".
    ReportID empty_report_id = {false, 0, 0, 0, 0};
    report_ids_.push_back(empty_report_id, &ac);
    if (!ac.check())
      return false;
    table_.report_id = &report_ids_[0];

    return true;
  }

  ParseResult Finish(DeviceDescriptor** device) {
    // A single heap allocation is used to pack the constructed model so
    // that the client can do a single free. There are 3 arrays in
    // order:
    //  - The report array, one entry per unique report id.
    //  - all reports fields
    //  - all collections
    //
    // The bottom two need fixups. Which means that inner pointers that
    // refer to collections in the source need to be translated to pointers
    // valid within the destination memory area.

    // Check if we actually have items or report ids before going forward.
    if (coll_.size() == 0) {
      return kParseMoreNeeded;
    }

    // If there's one report in |report_ids_| then there's just the null id.
    bool no_report_id = report_ids_.size() == 1;

    // If we have ids, then erase the null id since it shouldn't have items in it.
    if (!no_report_id) {
      report_ids_.erase(0);
    }
    size_t report_count = report_ids_.size();

    size_t device_sz = sizeof(DeviceDescriptor) + report_count * sizeof(ReportDescriptor);
    size_t fields_sz = fields_.size() * sizeof(ReportField);
    size_t collect_sz = coll_.size() * sizeof(Collection);

    auto mem = Alloc(device_sz + fields_sz + collect_sz);
    if (mem == nullptr)
      return kParseNoMemory;

    auto dev = new (mem) DeviceDescriptor{report_count};

    mem += device_sz;
    auto dest_fields = reinterpret_cast<ReportField*>(mem);

    mem += fields_sz;
    auto dest_colls = reinterpret_cast<Collection*>(mem);

    Fixup<Collection> coll_fixup(&coll_[0], &dest_colls[0]);

    size_t ix = 0u;
    // Copy and fix the collections first.
    for (const auto& c : coll_) {
      dest_colls[ix] = c;
      dest_colls[ix].parent = coll_fixup(c.parent);
      ++ix;
    }

    // Copy and fix the fields next.
    ix = 0u;
    size_t ifr = 0u;

    for (const ReportID& report_id : report_ids_) {
      size_t field_count = 0;

      // If we don't have report ids, we start at 0 offset.
      // Otherwise we start at an 8 bit offset because the first
      // byte is the report id.
      size_t input_bit_sz = (no_report_id) ? 0 : 8;
      size_t input_count = 0;
      ReportField* input_fields_start = &dest_fields[ix];

      size_t output_bit_sz = (no_report_id) ? 0 : 8;
      size_t output_count = 0;
      ReportField* output_fields_start = &input_fields_start[report_id.input_count];

      size_t feature_bit_sz = (no_report_id) ? 0 : 8;
      size_t feature_count = 0;
      ReportField* feature_fields_start = &output_fields_start[report_id.output_count];

      // Fill the ReportDescriptor entry with the address
      // of the first field, and the report id.
      dev->report[ifr] = {};
      dev->report[ifr].report_id = report_id.report_id;

      dev->report[ifr].input_fields = input_fields_start;
      dev->report[ifr].output_fields = output_fields_start;
      dev->report[ifr].feature_fields = feature_fields_start;

      for (const auto& f : fields_) {
        if (f.report_id != report_id.report_id)
          continue;

        switch (f.type) {
          case NodeType::kInput:
            if (input_count == report_id.input_count)
              return kParseOverflow;
            input_fields_start[input_count] = f;
            input_fields_start[input_count].col = coll_fixup(f.col);
            input_fields_start[input_count].attr.offset = static_cast<uint32_t>(input_bit_sz);
            input_bit_sz += f.attr.bit_sz;
            ++input_count;
            break;
          case NodeType::kOutput:
            if (output_count == report_id.output_count)
              return kParseOverflow;
            output_fields_start[output_count] = f;
            output_fields_start[output_count].col = coll_fixup(f.col);
            output_fields_start[output_count].attr.offset = static_cast<uint32_t>(output_bit_sz);
            output_bit_sz += f.attr.bit_sz;
            ++output_count;
            break;
          case NodeType::kFeature:
            if (feature_count == report_id.feature_count)
              return kParseOverflow;
            feature_fields_start[feature_count] = f;
            feature_fields_start[feature_count].col = coll_fixup(f.col);
            feature_fields_start[feature_count].attr.offset = static_cast<uint32_t>(feature_bit_sz);
            feature_bit_sz += f.attr.bit_sz;
            ++feature_count;
            break;
        }

        ++field_count;
        ++ix;
      }

      // If we haven't seen any fields reset the size to 0.
      if (input_count == 0)
        input_bit_sz = 0;
      if (output_count == 0)
        output_bit_sz = 0;
      if (feature_count == 0)
        feature_bit_sz = 0;

      // Update the report ReportDescriptor with the final information.
      dev->report[ifr].input_count = input_count;
      dev->report[ifr].input_byte_sz = DIV_ROUND_UP(input_bit_sz, 8);

      dev->report[ifr].output_count = output_count;
      dev->report[ifr].output_byte_sz = DIV_ROUND_UP(output_bit_sz, 8);

      dev->report[ifr].feature_count = feature_count;
      dev->report[ifr].feature_byte_sz = DIV_ROUND_UP(feature_bit_sz, 8);

      ++ifr;
    }

    *device = dev;
    return kParseOk;
  }

  ParseResult start_collection(uint32_t data) {  // Main
    if (!is_valid_collection(data))
      return kParseInvalidItemValue;

    // By reserving and doing the size() check here, we ensure
    // never a re-alloc, keeping the intra-collection pointers valid.
    if (coll_.size() > kMaxCollectionCount)
      return kParseOverflow;

    if (parent_coll_ == nullptr) {
      // The first collection must be an application collection.
      if (!is_app_collection(data))
        return kParseUnexpectedCol;
    }

    uint32_t usage = usages_.is_empty() ? 0 : usages_[0];

    Collection col{static_cast<CollectionType>(data), Usage{table_.attributes.usage.page, usage},
                   parent_coll_};

    coll_.push_back(col);
    parent_coll_ = &coll_[coll_.size() - 1];
    return kParseOk;
  }

  ParseResult end_collection(uint32_t data) {
    if (data != 0u)
      return kParseInvalidItemValue;
    if (parent_coll_ == nullptr)
      return kParseInvalidTag;
    // We don't free collection items until Finish().
    parent_coll_ = parent_coll_->parent;
    // TODO(cpu): make sure there are fields between start and end
    // otherwise this is malformed.
    return kParseOk;
  }

  ParseResult add_field(NodeType type, uint32_t data) {  // Main
    if (coll_.size() == 0)
      return kParseUnexpectedItem;

    if (!validate_ranges())
      return kParseInvalidRange;

    auto flags = expand_bitfield(data);
    Attributes attributes = table_.attributes;
    UsageIterator usage_it(this, flags);

    for (uint32_t ix = 0; ix != table_.report_count; ++ix) {
      attributes.usage = usage_it.next_usage();

      auto curr_col = &coll_[coll_.size() - 1];

      ReportField field{table_.report_id->report_id, attributes, type, flags, curr_col};

      // If physical min/max are zero they should be set to logical values.
      if (field.attr.phys_mm.min == 0 && field.attr.phys_mm.max == 0) {
        field.attr.phys_mm.min = field.attr.logc_mm.min;
        field.attr.phys_mm.max = field.attr.logc_mm.max;
      }

      fbl::AllocChecker ac;
      fields_.push_back(field, &ac);
      if (!ac.check())
        return kParseNoMemory;

      switch (type) {
        case kInput:
          table_.report_id->input_count++;
          break;
        case kOutput:
          table_.report_id->output_count++;
          break;
        case kFeature:
          table_.report_id->feature_count++;
          break;
      }
    }

    return kParseOk;
  }

  ParseResult reset_usage() {  //  after each Main
    // Is it an error to drop pending usages?
    usages_.reset();
    usage_range_ = {};
    return kParseOk;
  }

  ParseResult add_usage(uint32_t data) {  // Local
    usages_.push_back(data);
    return kParseOk;
  }

  ParseResult set_usage_min(uint32_t data) {  // Local
    if (data > UINT16_MAX)
      return kParseUnsuported;

    usage_range_.min = data;
    return kParseOk;
  }

  ParseResult set_usage_max(uint32_t data) {  // Local
    // In add_usage() we don't restrict the value while
    // here we do. This is because a very large range can
    // effectively DoS the code in the usage iterator.
    if (data > UINT16_MAX)
      return kParseUnsuported;

    usage_range_.max = data;
    return kParseOk;
  }

  ParseResult set_usage_page(uint32_t data) {  // Global
    if (data > UINT16_MAX)
      return kParseInvalidRange;

    table_.attributes.usage.page = static_cast<uint16_t>(data);
    return kParseOk;
  }

  ParseResult set_logical_min(int32_t data) {  // Global
    table_.attributes.logc_mm.min = data;
    return kParseOk;
  }

  ParseResult set_logical_max(const hid::Item& item) {  // Global
    if (table_.attributes.logc_mm.min >= 0) {
      table_.attributes.logc_mm.max = item.data();
    } else {
      table_.attributes.logc_mm.max = item.signed_data();
    }
    return kParseOk;
  }

  ParseResult set_physical_min(int32_t data) {  // Global
    table_.attributes.phys_mm.min = data;
    return kParseOk;
  }

  ParseResult set_physical_max(const hid::Item& item) {  // Global
    if (table_.attributes.phys_mm.min >= 0) {
      table_.attributes.phys_mm.max = item.data();
    } else {
      table_.attributes.phys_mm.max = item.signed_data();
    }
    return kParseOk;
  }

  ParseResult set_unit(uint32_t data) {
    // The unit parsing is a complicated per nibble
    // accumulation of units. Leave that to application.
    table_.attributes.unit.type = data;
    return kParseOk;
  }

  ParseResult set_unit_exp(uint32_t data) {  // Global
    int32_t exp = static_cast<uint8_t>(data);
    // The exponent uses a weird, not fully specified
    // conversion, for example the value 0xf results
    // in -1 exponent. See USB HID spec doc.
    if (exp > 7)
      exp = exp - 16;
    table_.attributes.unit.exp = exp;
    return kParseOk;
  }

  ParseResult set_report_id(uint32_t data) {  // Global
    if (data == 0)
      return kParserInvalidID;
    if (data > UINT8_MAX)
      return kParseInvalidRange;

    // It's an error to define a report id after items have been defined with no id.
    if (report_id_has_items(report_ids_[0]))
      return kParserMissingID;

    // Check if we've seen the report id before.
    uint8_t id = static_cast<uint8_t>(data);
    ReportID* report_ids = report_ids_.data();
    for (size_t i = 0; i < report_ids_.size(); i++) {
      if (report_ids[i].report_id == id) {
        table_.report_id = &report_ids[i];
        return kParseOk;
      }
    }

    // We haven't, so allocate the new report id.
    ReportID new_report_id = {true, id, 0, 0, 0};
    fbl::AllocChecker ac;
    report_ids_.push_back(new_report_id, &ac);
    if (!ac.check())
      return kParseNoMemory;
    table_.report_id = &report_ids_[report_ids_.size() - 1];

    return kParseOk;
  }

  ParseResult set_report_count(uint32_t data) {  // Global
    if (data > UINT16_MAX) {
      return kParseNoMemory;
    }
    table_.report_count = data;
    return kParseOk;
  }

  ParseResult set_report_size(uint32_t data) {  // Global
    if (data > UINT8_MAX)
      return kParseInvalidRange;
    table_.attributes.bit_sz = static_cast<uint8_t>(data);
    return kParseOk;
  }

  ParseResult push(uint32_t data) {  // Global
    fbl::AllocChecker ac;
    stack_.push_back(table_, &ac);
    return ac.check() ? kParseOk : kParseNoMemory;
  }

  ParseResult pop(uint32_t data) {  // Global
    if (stack_.size() == 0)
      return kParserUnexpectedPop;

    table_ = stack_[stack_.size() - 1];
    stack_.pop_back();
    return kParseOk;
  }

 private:
  struct StateTable {
    Attributes attributes;
    uint32_t report_count;
    ReportID* report_id;
  };

  // Helper class that encapsulates the logic of assigning usages
  // to input, output and feature items. There are 2 ways to
  // assign usages:
  // 1- from the UsageMinimum and UsageMaximum items
  // 2- from the existing Usage items stored in the usages_ vector
  //
  // For method #2, the number of calls to next_usage() can be
  // greater than the available usages. The standard requires in
  // this case to return the last usage in all remaining calls.
  //
  // If the item is an array, only returns the first usage.
  // TODO(cpu): this is not completely right, at least reading
  // from the example in the spec pages 76-77, we are presented
  // the 17-key keypad:
  //      Usage(0), Usage Minimum(53h), Usage Maximum(63h),
  //      Logical Minimum (0), Logical Maximum (17),
  //      Report Size (8), Report Count (3)
  //      Input (Data, Array)
  //  But on the other hand, the adafruit trinket presents:
  //      Report Count (1), Report Size (2)
  //      Usage (Sys Sleep (82)), Usage (Sys Power Down(81)), Usage (Sys Wake Up(83))
  //      Input (Data,Array)
  //
  // In other words, array might need a lookup table to be generated
  // see the header for a potential approach.

  class UsageIterator {
   public:
    UsageIterator(ParseState* ps, uint32_t field_type)
        : usages_(nullptr),
          usage_range_(),
          index_(0),
          last_usage_(0),
          is_array_(FieldTypeFlags::kArray & field_type) {
      usage_page_ = ps->table_.attributes.usage.page;
      if ((ps->usage_range_.max == 0) && (ps->usage_range_.min == 0)) {
        usages_ = &ps->usages_;
        has_usage_ = (usages_->size() != 0);
      } else {
        usage_range_ = ps->usage_range_;
        has_usage_ = true;
      }
    }

    Usage next_usage() {
      Usage usage = {};
      if (!has_usage_) {
        return usage;
      }

      int64_t usage_long = 0;
      if (usages_ == nullptr) {
        usage_long = usage_range_.min + index_;
        if (usage_long > usage_range_.max)
          usage_long = usage_range_.max;
      } else {
        usage_long = (index_ < usages_->size()) ? (*usages_)[index_] : last_usage_;
        last_usage_ = static_cast<uint32_t>(usage_long);
      }
      if (!is_array_) {
        ++index_;
      }

      usage.page = usage_page_;
      usage.usage = static_cast<uint32_t>(usage_long);

      return usage;
    }

   private:
    const fbl::Vector<uint32_t>* usages_;
    MinMax usage_range_;
    int16_t usage_page_;
    uint32_t index_;
    uint32_t last_usage_;
    bool is_array_;
    bool has_usage_;
  };

  bool validate_ranges() const {
    if (usage_range_.min > usage_range_.max)
      return false;
    if (table_.attributes.logc_mm.min > table_.attributes.logc_mm.max)
      return false;
    return true;
  }

  // Internal state per spec:
  MinMax usage_range_;
  StateTable table_;
  fbl::Vector<StateTable> stack_;
  fbl::Vector<uint32_t> usages_;
  // Temporary output model:
  Collection* parent_coll_;
  fbl::Vector<ReportID> report_ids_;
  fbl::Vector<Collection> coll_;
  fbl::Vector<ReportField> fields_;
};

ParseResult ProcessMainItem(const hid::Item& item, ParseState* state) {
  ParseResult res;
  switch (item.tag()) {
    case Item::Tag::kInput:
    case Item::Tag::kOutput:
    case Item::Tag::kFeature:
      res = state->add_field(static_cast<NodeType>(item.tag()), item.data());
      break;
    case Item::Tag::kCollection:
      res = state->start_collection(item.data());
      break;
    case Item::Tag::kEndCollection:
      res = state->end_collection(item.data());
      break;
    default:
      res = kParseInvalidTag;
  }

  return (res == kParseOk) ? state->reset_usage() : res;
}

ParseResult ProcessGlobalItem(const hid::Item& item, ParseState* state) {
  switch (item.tag()) {
    case Item::Tag::kUsagePage:
      return state->set_usage_page(item.data());
    case Item::Tag::kLogicalMinimum:
      return state->set_logical_min(item.signed_data());
    case Item::Tag::kLogicalMaximum:
      return state->set_logical_max(item);
    case Item::Tag::kPhysicalMinimum:
      return state->set_physical_min(item.signed_data());
    case Item::Tag::kPhysicalMaximum:
      return state->set_physical_max(item);
    case Item::Tag::kUnitExponent:
      return state->set_unit_exp(item.data());
    case Item::Tag::kUnit:
      return state->set_unit(item.data());
    case Item::Tag::kReportSize:
      return state->set_report_size(item.data());
    case Item::Tag::kReportId:
      return state->set_report_id(item.data());
    case Item::Tag::kReportCount:
      return state->set_report_count(item.data());
    case Item::Tag::kPush:
      return state->push(item.data());
    case Item::Tag::kPop:
      return state->pop(item.data());
    default:
      return kParseInvalidTag;
  }
}

ParseResult ProcessLocalItem(const hid::Item& item, ParseState* state) {
  switch (item.tag()) {
    case Item::Tag::kUsage:
      return state->add_usage(item.data());
    case Item::Tag::kUsageMinimum:
      return state->set_usage_min(item.data());
    case Item::Tag::kUsageMaximum:
      return state->set_usage_max(item.data());

    case Item::Tag::kDesignatorIndex:  // Fall thru. TODO(cpu) implement.
    case Item::Tag::kDesignatorMinimum:
    case Item::Tag::kDesignatorMaximum:
    case Item::Tag::kStringIndex:
    case Item::Tag::kStringMinimum:
    case Item::Tag::kStringMaximum:
    case Item::Tag::kDelimiter:
      return kParseUnsuported;
    default:
      return kParseInvalidTag;
  }
}

ParseResult ProcessItem(const hid::Item& item, ParseState* state) {
  switch (item.type()) {
    case Item::Type::kMain:
      return ProcessMainItem(item, state);
    case Item::Type::kGlobal:
      return ProcessGlobalItem(item, state);
    case Item::Type::kLocal:
      return ProcessLocalItem(item, state);
    default:
      return kParseInvalidItemType;
  }
}

}  // namespace impl

ParseResult ParseReportDescriptor(const uint8_t* rpt_desc, size_t desc_len,
                                  DeviceDescriptor** device) {
  impl::ParseState state;

  if (rpt_desc == nullptr || device == nullptr)
    return kParseMoreNeeded;

  if (!state.Init())
    return kParseNoMemory;

  const uint8_t* buf = rpt_desc;
  size_t len = desc_len;
  while (len > 0) {
    size_t actual = 0;
    auto item = hid::Item::ReadNext(buf, len, &actual);
    if (actual > len)
      return kParseMoreNeeded;
    if (actual == 0)
      return kParseUnsuported;

    auto pr = ProcessItem(item, &state);
    if (pr != kParseOk)
      return pr;

    len -= actual;
    buf += actual;
  }

  return state.Finish(device);
}

void FreeDeviceDescriptor(DeviceDescriptor* dev_desc) {
  // memory was allocated via ParseState::Alloc()
  impl::ParseState::Free(dev_desc);
}

Collection* GetAppCollection(const ReportField* field) {
  if (field == nullptr)
    return nullptr;

  auto collection = field->col;
  while (collection != nullptr) {
    if (collection->type == hid::CollectionType::kApplication)
      break;
    collection = collection->parent;
  }
  return collection;
}

#undef DIV_ROUND_UP
}  // namespace hid
