Skip to content

Commit

Permalink
improve the usage handling (at the cost of name
Browse files Browse the repository at this point in the history
  • Loading branch information
benedekkupper committed Feb 19, 2024
1 parent 64c6dd6 commit e64ec54
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 100 deletions.
12 changes: 6 additions & 6 deletions hid-rp/hid/app/keyboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static constexpr auto keys_input_report_descriptor()
report_count(8),
logical_limits<1, 1>(0, 1),
usage_page<keyboard_keypad>(),
usage_limits(keyboard_keypad::LEFTCTRL, keyboard_keypad::RIGHTGUI),
usage_limits(keyboard_keypad::KEYBOARD_LEFT_CONTROL, keyboard_keypad::KEYBOARD_RIGHT_GUI),
input::absolute_variable(),
// reserved byte
input::padding(8),
Expand All @@ -60,10 +60,10 @@ struct keys_input_report : public hid::report::base<hid::report::type::INPUT, RE
{
using namespace hid::page;

if (key >= keyboard_keypad::LEFTCTRL)
if (key >= keyboard_keypad::KEYBOARD_LEFT_CONTROL)
{
uint8_t mask =
1 << (static_cast<uint8_t>(key) - static_cast<uint8_t>(keyboard_keypad::LEFTCTRL));
uint8_t mask = 1 << (static_cast<uint8_t>(key) -
static_cast<uint8_t>(keyboard_keypad::KEYBOARD_LEFT_CONTROL));
if (pressed)
{
modifiers |= mask;
Expand All @@ -87,7 +87,7 @@ struct keys_input_report : public hid::report::base<hid::report::type::INPUT, RE
// scancodes buffer full, need to raise rollover error
for (auto& code : scancodes)
{
code = static_cast<uint8_t>(keyboard_keypad::ERRORROLLOVER);
code = static_cast<uint8_t>(keyboard_keypad::ERROR_ROLLOVER);
}
return false;
}
Expand All @@ -101,7 +101,7 @@ struct keys_input_report : public hid::report::base<hid::report::type::INPUT, RE
return true;
}
// clear rollover error when a key is released
else if (code == static_cast<uint8_t>(keyboard_keypad::ERRORROLLOVER))
else if (code == static_cast<uint8_t>(keyboard_keypad::ERROR_ROLLOVER))
{
code = 0;
}
Expand Down
12 changes: 2 additions & 10 deletions hid-rp/hid/rdf/global_items.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,11 @@ constexpr auto report_size(T value)
return short_item<DATA_SIZE>(global::tag::REPORT_SIZE, value);
}

template <typename T>
constexpr auto usage_page(T usage)
{
constexpr std::size_t PAGE_ID_SIZE = global::usage_page_size<T>();
return short_item<PAGE_ID_SIZE>(global::tag::USAGE_PAGE,
static_cast<usage_id_type>(usage) >> USAGE_PAGE_OFFSET);
}
template <typename T>
template <UsageType T>
constexpr auto usage_page()
{
constexpr std::size_t PAGE_ID_SIZE = global::usage_page_size<T>();
return short_item<PAGE_ID_SIZE>(global::tag::USAGE_PAGE,
(page::info<T>::base_id) >> USAGE_PAGE_OFFSET);
return short_item<PAGE_ID_SIZE>(global::tag::USAGE_PAGE, page::info<T>::page_id);
}

constexpr auto push_globals()
Expand Down
53 changes: 25 additions & 28 deletions hid-rp/hid/rdf/local_items.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,62 +16,59 @@

namespace hid::rdf
{
template <std::size_t DATA_SIZE = 2, typename T>
template <std::size_t DATA_SIZE = 2, UsageType T>
constexpr auto usage(T value)
{
constexpr std::size_t ID_SIZE = std::min(local::usage_size<T>(), DATA_SIZE);
static_assert((ID_SIZE > 0) and (ID_SIZE <= sizeof(usage_index_type)));
return short_item<ID_SIZE>(local::tag::USAGE, static_cast<usage_index_type>(value));
constexpr std::size_t ID_SIZE = std::min(sizeof(T), DATA_SIZE);
static_assert((ID_SIZE > 0) and (ID_SIZE <= sizeof(usage_id_t)));
return short_item<ID_SIZE>(local::tag::USAGE, static_cast<usage_id_t>(value));
}

/// @note Extended usage contains the usage page as well, otherwise the global usage page is
/// considered.
/// Extended usage is identified not by tag, but by the data size of the item.
template <typename T>
template <UsageType T>
constexpr auto usage_extended(T value)
{
constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type);
return short_item<EXT_ID_SIZE>(local::tag::USAGE, static_cast<usage_id_type>(value));
return short_item<sizeof(usage_t)>(local::tag::USAGE, usage_t(value));
}

/// @note Usages are local items, there must be a min-max pair each time
/// (hence no definition for usage_min or usage_max).
template <std::size_t DATA_MIN_SIZE = 2, std::size_t DATA_MAX_SIZE = 2, typename T>
template <std::size_t DATA_MIN_SIZE = 2, std::size_t DATA_MAX_SIZE = 2, UsageType T>
constexpr auto usage_limits(T min, T max)
{
constexpr std::size_t MIN_ID_SIZE = std::min(local::usage_size<T>(), DATA_MIN_SIZE);
constexpr std::size_t MAX_ID_SIZE = std::min(local::usage_size<T>(), DATA_MAX_SIZE);
static_assert((MIN_ID_SIZE > 0) and (MIN_ID_SIZE <= sizeof(usage_index_type)));
static_assert((MAX_ID_SIZE > 0) and (MAX_ID_SIZE <= sizeof(usage_index_type)));
return short_item<MIN_ID_SIZE>(local::tag::USAGE_MINIMUM, static_cast<usage_index_type>(min)),
short_item<MAX_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_index_type>(max));
constexpr std::size_t MIN_ID_SIZE = std::min(sizeof(T), DATA_MIN_SIZE);
constexpr std::size_t MAX_ID_SIZE = std::min(sizeof(T), DATA_MAX_SIZE);
static_assert((MIN_ID_SIZE > 0) and (MIN_ID_SIZE <= sizeof(usage_id_t)));
static_assert((MAX_ID_SIZE > 0) and (MAX_ID_SIZE <= sizeof(usage_id_t)));
return short_item<MIN_ID_SIZE>(local::tag::USAGE_MINIMUM, static_cast<usage_id_t>(min)),
short_item<MAX_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_id_t>(max));
}

template <std::size_t DATA_MAX_SIZE = 2, typename T>
template <std::size_t DATA_MAX_SIZE = 2, UsageType T>
constexpr auto usage_limits(nullusage_t min, T max)
{
constexpr std::size_t MIN_ID_SIZE = 1;
constexpr std::size_t MAX_ID_SIZE = std::min(local::usage_size<T>(), DATA_MAX_SIZE);
static_assert((MAX_ID_SIZE > 0) and (MAX_ID_SIZE <= sizeof(usage_index_type)));
return short_item<MIN_ID_SIZE>(local::tag::USAGE_MINIMUM, static_cast<usage_index_type>(min)),
short_item<MAX_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_index_type>(max));
constexpr std::size_t MAX_ID_SIZE = std::min(sizeof(T), DATA_MAX_SIZE);
static_assert((MAX_ID_SIZE > 0) and (MAX_ID_SIZE <= sizeof(usage_id_t)));
return short_item<MIN_ID_SIZE>(local::tag::USAGE_MINIMUM, static_cast<usage_id_t>(min)),
short_item<MAX_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_id_t>(max));
}

template <typename T>
template <UsageType T>
constexpr auto usage_extended_limits(T min, T max)
{
constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type);
return short_item<EXT_ID_SIZE>(local::tag::USAGE_MINIMUM, static_cast<usage_id_type>(min)),
short_item<EXT_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_id_type>(max));
return short_item<sizeof(usage_t)>(local::tag::USAGE_MINIMUM, usage_t(min)),
short_item<sizeof(usage_t)>(local::tag::USAGE_MAXIMUM, usage_t(max));
}

template <typename T>
template <UsageType T>
constexpr auto usage_extended_limits(nullusage_t min, T max)
{
constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type);
return short_item<EXT_ID_SIZE>(local::tag::USAGE_MINIMUM,
static_cast<usage_id_type>(max) & USAGE_PAGE_ID_MASK),
short_item<EXT_ID_SIZE>(local::tag::USAGE_MAXIMUM, static_cast<usage_id_type>(max));
auto ui = usage_t(max);
return short_item<sizeof(usage_t)>(local::tag::USAGE_MINIMUM, usage_t(ui.page_id(), 0)),
short_item<sizeof(usage_t)>(local::tag::USAGE_MAXIMUM, ui);
}

} // namespace hid::rdf
Expand Down
14 changes: 7 additions & 7 deletions hid-rp/hid/rdf/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,18 @@ class parser
/// @param usage_item: the USAGE / USAGE_MINIMUM / USAGE_MAXIMUM type local item
/// @param global_state: the global items state at the current main item
/// @return The complete usage ID
constexpr static usage_id_type get_usage(const item_type& usage_item,
const global_item_store& global_state)
constexpr static usage_t get_usage(const item_type& usage_item,
const global_item_store& global_state)
{
if (usage_item.data_size() == sizeof(usage_id_type))
if (usage_item.data_size() == sizeof(usage_t))
{
return usage_item.value_unsigned();
return usage_t(usage_item.value_unsigned());
}
else
{
const auto* page = global_state.get_item(global::tag::USAGE_PAGE);
HID_RDF_ASSERT(page != nullptr, ex_usage_page_missing);
return (page->value_unsigned() << USAGE_PAGE_OFFSET) | usage_item.value_unsigned();
return usage_t(page->value_unsigned(), usage_item.value_unsigned());
}
}

Expand Down Expand Up @@ -342,7 +342,7 @@ class parser
/// @return the complete usage ID of the first top-level collection
/// @throws if errors are encountered during parsing, a @ref parser_exception is raised
template <typename TIterator>
constexpr usage_id_type get_application_usage_id(const descriptor_view_base<TIterator>& desc_view)
constexpr usage_t get_application_usage_id(const descriptor_view_base<TIterator>& desc_view)
{
/// @brief Internal class that implements the parsing logic for the specific task.
struct application_usage_id_parser : public parser<TIterator>
Expand Down Expand Up @@ -375,7 +375,7 @@ constexpr usage_id_type get_application_usage_id(const descriptor_view_base<TIte
return control::BREAK;
}

usage_id_type usage_ = 0;
usage_t usage_{0};
};

auto usage = application_usage_id_parser(desc_view).usage_;
Expand Down
2 changes: 0 additions & 2 deletions hid-rp/hid/rdf/short_item.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ class short_item : public array<1 + DATA_SIZE>
constexpr short_item(TTag tag, TData data)
: short_item(tag)
{
static_assert(std::is_integral_v<TData> or std::is_enum_v<TData>);

auto d = static_cast<std::uint32_t>(data);
for (byte_type i = 0; i < DATA_SIZE; ++i)
{
Expand Down
95 changes: 49 additions & 46 deletions hid-rp/hid/usage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,8 @@

namespace hid
{
/// @brief Full identifier of a usage. Consists of 16 bits usage page ID and 16 bits usage index.
using usage_id_type = std::uint32_t;

/// @brief Relative identifier of a usage within a usage page.
using usage_index_type = std::uint16_t;

constexpr usage_id_type USAGE_INDEX_MASK = std::numeric_limits<usage_index_type>::max();
constexpr std::size_t USAGE_PAGE_OFFSET = (8 * sizeof(usage_index_type));
constexpr usage_id_type USAGE_PAGE_ID_MASK = std::numeric_limits<std::uint16_t>::max()
<< USAGE_PAGE_OFFSET;
using page_id_t = std::uint16_t;
using usage_id_t = std::uint16_t;

namespace page
{
Expand All @@ -34,58 +26,69 @@ namespace page
template <typename T>
struct info
{
constexpr static usage_id_type max_usage = 0;
constexpr static usage_id_type base_id = 0;
constexpr static page_id_t page_id = 0;
constexpr static const char* name = "invalid";
};
} // namespace page

namespace rdf
{
namespace local
{
/// @brief This concept matches types with valid page information,
/// which is necessary for determining the full usage value.
template <typename T>
constexpr std::size_t usage_size()
{
return (page::info<T>::max_usage & USAGE_INDEX_MASK) > std::numeric_limits<std::uint8_t>::max()
? 2
: 1;
}
} // namespace local
namespace global
concept UsageType = (sizeof(T) <= sizeof(usage_id_t)) and (page::info<T>::page_id > 0);

namespace rdf::global
{
template <typename T>
template <UsageType T>
constexpr std::size_t usage_page_size()
{
return (page::info<T>::base_id >> USAGE_PAGE_OFFSET) > std::numeric_limits<std::uint8_t>::max()
? 2
: 1;
return page::info<T>::page_id > std::numeric_limits<std::uint8_t>::max() ? 2 : 1;
}
} // namespace global
} // namespace rdf
} // namespace rdf::global

class nullusage_t
/// @brief The usage_t class holds the entire usage information in one class,
/// combining the page ID and usage ID into a single 32-bit variable.
class usage_t
{
// The usage page isn't encoded, so it's not a full usage type
public:
constexpr nullusage_t() {}
constexpr operator usage_index_type() const { return 0; }
template <typename T>
constexpr bool operator==(const T& rhs) const
{
return (static_cast<usage_id_type>(rhs) & USAGE_INDEX_MASK) ==
static_cast<usage_index_type>(*this);
}
template <typename T>
constexpr bool operator!=(const T& rhs) const
{
return !(*this == rhs);
}
using type = std::uint32_t;

constexpr explicit usage_t(type value)
: value_(value)
{}
constexpr usage_t(page_id_t page, usage_id_t u)
: value_((page << 16) | u)
{}
template <UsageType T>
constexpr usage_t(T u)
: value_((page::info<T>::page_id << 16) | static_cast<type>(u))
{}
constexpr operator type&() { return value_; }
constexpr operator type() const { return value_; }
constexpr page_id_t page_id() const { return value_ >> 16; }
constexpr usage_id_t id() const { return value_ & std::numeric_limits<usage_id_t>::max(); }

constexpr bool operator<=>(const usage_t&) const = default;

private:
type value_;
};

/// @brief Variable that expresses null usage state (for usage_limits min)
/// @brief Type and variable that expresses a never valid null usage state.
class nullusage_t : public usage_t
{
public:
constexpr nullusage_t()
: usage_t(0)
{}
};
constexpr nullusage_t nullusage;

namespace page
{
// alias definition to simplify descriptor definition
using hid::nullusage;
} // namespace page

} // namespace hid

#endif // __HID_RDF_USAGE_HPP_

0 comments on commit e64ec54

Please sign in to comment.