Skip to content

Commit

Permalink
refactoring report_protocol to include per-direction report ID limit
Browse files Browse the repository at this point in the history
  • Loading branch information
benedekkupper committed Nov 16, 2023
1 parent 6de20da commit f3bbcbd
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 25 deletions.
2 changes: 1 addition & 1 deletion hid-rp/hid/app/opaque.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace hid::app::opaque
{
template<unsigned BYTE_SIZE, report::type TYPE, report::id::type REPORT_ID>
template<unsigned BYTE_SIZE, hid::report::type TYPE, hid::report::id::type REPORT_ID = 0>
struct report : public hid::report::base<TYPE, REPORT_ID>
{
std::array<uint8_t, BYTE_SIZE> payload {};
Expand Down
97 changes: 73 additions & 24 deletions hid-rp/hid/report_protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define __HID_RDF_REPORT_PROTOCOL_HPP_

#include <algorithm>
#include <array>
#include "hid/rdf/parser.hpp"
#include "hid/rdf/global_items.hpp"

Expand All @@ -22,50 +23,87 @@ namespace hid
/// to establish a proper size data channel between the host and the device.
/// This class can gather all parameters from the HID report descriptor at compile-time,
/// and also performs verification of the descriptor (compiler error when the descriptor is faulty).
struct report_protocol
class report_protocol
{
public:
using descriptor_view_type = rdf::ce_descriptor_view;
using size_type = std::uint16_t;

descriptor_view_type descriptor;
size_type max_input_size = 0;
size_type max_output_size = 0;
size_type max_feature_size = 0;
report::id::type max_report_id = 0;
constexpr descriptor_view_type descriptor() const
{
return descriptor_;
}

constexpr size_type max_report_size() const
{
return *std::max_element(max_report_sizes_.begin(), max_report_sizes_.end());
}
constexpr size_type max_report_size(report::type type) const
{
return max_report_sizes_[static_cast<size_t>(type) - 1];
}

constexpr bool uses_report_ids() const
{
return max_report_id >= report::id::min();
return max_report_id() >= report::id::min();
}
constexpr report::id::type max_report_id() const
{
return *std::max_element(max_report_ids_.begin(), max_report_ids_.end());
}
constexpr report::id::type max_report_id(report::type type) const
{
return max_report_ids_[static_cast<size_t>(type) - 1];
}

/// @brief Define the report protocol manually, with no report ID use.
/// @param desc_view: View of the HID report descriptor
/// @param max_input_size: The size of the longest INPUT report in bytes, including the report ID (if used)
/// @param max_output_size: The size of the longest OUTPUT report in bytes, including the report ID (if used)
/// @param max_feature_size: The size of the longest FEATURE report in bytes, including the report ID (if used)
/// @param max_report_id: The highest used report ID (or 0 if IDs are not used)
constexpr report_protocol(const descriptor_view_type& desc_view,
size_type max_input_size,
size_type max_output_size,
size_type max_feature_size)
: descriptor_(desc_view),
max_report_sizes_(std::to_array({ max_input_size, max_output_size, max_feature_size }))
{}

/// @brief Define the report protocol manually.
/// @param desc_view: View of the HID report descriptor
/// @param max_input_size: The size of the longest INPUT report in bytes, including the report ID (if used)
/// @param max_output_size: The size of the longest OUTPUT report in bytes, including the report ID (if used)
/// @param max_feature_size: The size of the longest FEATURE report in bytes, including the report ID (if used)
/// @param max_report_id: The highest used report ID (or 0 if IDs are not used)
constexpr report_protocol(const descriptor_view_type &desc_view,
constexpr report_protocol(const descriptor_view_type& desc_view,
size_type max_input_size,
size_type max_output_size,
size_type max_feature_size,
report::id::type max_report_id = 0)
: descriptor(desc_view),
max_input_size(max_input_size),
max_output_size(max_output_size),
max_feature_size(max_feature_size),
max_report_id(max_report_id)
report::id::type max_input_id,
report::id::type max_output_id,
report::id::type max_feature_id)
: descriptor_(desc_view),
max_report_sizes_(std::to_array({ max_input_size, max_output_size, max_feature_size })),
max_report_ids_(std::to_array({ max_input_id, max_output_id, max_feature_id }))
{}

/// @brief Define the report protocol by parsing the descriptor in compile-time.
/// @param desc_view: View of the HID report descriptor
consteval report_protocol(const descriptor_view_type &desc_view)
: descriptor(desc_view)
consteval report_protocol(const descriptor_view_type& desc_view)
: descriptor_(desc_view)
{
auto parsed = report_protocol::parser(desc_view);
max_input_size = parsed.max_report_size(report::type::INPUT);
max_output_size = parsed.max_report_size(report::type::OUTPUT);
max_feature_size = parsed.max_report_size(report::type::FEATURE);
max_report_id = parsed.max_report_id();
max_report_sizes_ = std::to_array({
parsed.max_report_size(report::type::INPUT),
parsed.max_report_size(report::type::OUTPUT),
parsed.max_report_size(report::type::FEATURE)
});
max_report_ids_ = std::to_array({
parsed.max_report_id(report::type::INPUT),
parsed.max_report_id(report::type::OUTPUT),
parsed.max_report_id(report::type::FEATURE)
});
}

/// @brief This class parses the HID report descriptor, gathering all report size
Expand Down Expand Up @@ -118,12 +156,17 @@ namespace hid

constexpr bool uses_report_ids() const
{
return max_report_id_ > 0;
return max_report_id() > 0;
}

constexpr report::id::type max_report_id() const
{
return max_report_id_;
return *std::max_element(max_report_ids_.begin(), max_report_ids_.end());
}

constexpr report::id::type max_report_id(report::type type) const
{
return max_report_ids_[static_cast<size_t>(type) - 1];
}

private:
Expand Down Expand Up @@ -152,7 +195,8 @@ namespace hid
HID_RDF_ASSERT(sizes[0] == 0, ex_report_id_missing);
}
}
max_report_id_ = std::max(max_report_id_, report_id);
auto& rid = max_report_ids_[static_cast<size_t>(rtype) - 1];
rid = std::max(rid, report_id);
}

// get the items defining the size of this/these report data elements
Expand Down Expand Up @@ -219,8 +263,13 @@ namespace hid

std::array<std::array<size_type, report::id::max()>, 3> report_bit_sizes_ {};
std::array<std::array<unsigned, report::id::max()>, 3> report_tlc_indexes_ {};
report::id::type max_report_id_ = 0;
std::array<report::id::type, 3> max_report_ids_ {};
};

private:
descriptor_view_type descriptor_;
std::array<size_type, 3> max_report_sizes_{};
std::array<report::id::type, 3> max_report_ids_{};
};
}

Expand Down

0 comments on commit f3bbcbd

Please sign in to comment.