diff --git a/hid-rp/hid/app/keyboard.hpp b/hid-rp/hid/app/keyboard.hpp index 6c4324b..0d07e5a 100644 --- a/hid-rp/hid/app/keyboard.hpp +++ b/hid-rp/hid/app/keyboard.hpp @@ -33,7 +33,7 @@ static constexpr auto keys_input_report_descriptor() report_count(8), logical_limits<1, 1>(0, 1), usage_page(), - 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), @@ -60,10 +60,10 @@ struct keys_input_report : public hid::report::base= keyboard_keypad::LEFTCTRL) + if (key >= keyboard_keypad::KEYBOARD_LEFT_CONTROL) { - uint8_t mask = - 1 << (static_cast(key) - static_cast(keyboard_keypad::LEFTCTRL)); + uint8_t mask = 1 << (static_cast(key) - + static_cast(keyboard_keypad::KEYBOARD_LEFT_CONTROL)); if (pressed) { modifiers |= mask; @@ -87,7 +87,7 @@ struct keys_input_report : public hid::report::base(keyboard_keypad::ERRORROLLOVER); + code = static_cast(keyboard_keypad::ERROR_ROLLOVER); } return false; } @@ -101,7 +101,7 @@ struct keys_input_report : public hid::report::base(keyboard_keypad::ERRORROLLOVER)) + else if (code == static_cast(keyboard_keypad::ERROR_ROLLOVER)) { code = 0; } diff --git a/hid-rp/hid/rdf/global_items.hpp b/hid-rp/hid/rdf/global_items.hpp index 5b0bfd6..d54b345 100644 --- a/hid-rp/hid/rdf/global_items.hpp +++ b/hid-rp/hid/rdf/global_items.hpp @@ -107,19 +107,11 @@ constexpr auto report_size(T value) return short_item(global::tag::REPORT_SIZE, value); } -template -constexpr auto usage_page(T usage) -{ - constexpr std::size_t PAGE_ID_SIZE = global::usage_page_size(); - return short_item(global::tag::USAGE_PAGE, - static_cast(usage) >> USAGE_PAGE_OFFSET); -} -template +template constexpr auto usage_page() { constexpr std::size_t PAGE_ID_SIZE = global::usage_page_size(); - return short_item(global::tag::USAGE_PAGE, - (page::info::base_id) >> USAGE_PAGE_OFFSET); + return short_item(global::tag::USAGE_PAGE, page::info::page_id); } constexpr auto push_globals() diff --git a/hid-rp/hid/rdf/local_items.hpp b/hid-rp/hid/rdf/local_items.hpp index 6297804..ce8d64c 100644 --- a/hid-rp/hid/rdf/local_items.hpp +++ b/hid-rp/hid/rdf/local_items.hpp @@ -16,62 +16,59 @@ namespace hid::rdf { -template +template constexpr auto usage(T value) { - constexpr std::size_t ID_SIZE = std::min(local::usage_size(), DATA_SIZE); - static_assert((ID_SIZE > 0) and (ID_SIZE <= sizeof(usage_index_type))); - return short_item(local::tag::USAGE, static_cast(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(local::tag::USAGE, static_cast(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 +template constexpr auto usage_extended(T value) { - constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type); - return short_item(local::tag::USAGE, static_cast(value)); + return short_item(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 +template constexpr auto usage_limits(T min, T max) { - constexpr std::size_t MIN_ID_SIZE = std::min(local::usage_size(), DATA_MIN_SIZE); - constexpr std::size_t MAX_ID_SIZE = std::min(local::usage_size(), 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(local::tag::USAGE_MINIMUM, static_cast(min)), - short_item(local::tag::USAGE_MAXIMUM, static_cast(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(local::tag::USAGE_MINIMUM, static_cast(min)), + short_item(local::tag::USAGE_MAXIMUM, static_cast(max)); } -template +template 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(), DATA_MAX_SIZE); - static_assert((MAX_ID_SIZE > 0) and (MAX_ID_SIZE <= sizeof(usage_index_type))); - return short_item(local::tag::USAGE_MINIMUM, static_cast(min)), - short_item(local::tag::USAGE_MAXIMUM, static_cast(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(local::tag::USAGE_MINIMUM, static_cast(min)), + short_item(local::tag::USAGE_MAXIMUM, static_cast(max)); } -template +template constexpr auto usage_extended_limits(T min, T max) { - constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type); - return short_item(local::tag::USAGE_MINIMUM, static_cast(min)), - short_item(local::tag::USAGE_MAXIMUM, static_cast(max)); + return short_item(local::tag::USAGE_MINIMUM, usage_t(min)), + short_item(local::tag::USAGE_MAXIMUM, usage_t(max)); } -template +template constexpr auto usage_extended_limits(nullusage_t min, T max) { - constexpr std::size_t EXT_ID_SIZE = sizeof(usage_id_type); - return short_item(local::tag::USAGE_MINIMUM, - static_cast(max) & USAGE_PAGE_ID_MASK), - short_item(local::tag::USAGE_MAXIMUM, static_cast(max)); + auto ui = usage_t(max); + return short_item(local::tag::USAGE_MINIMUM, usage_t(ui.page_id(), 0)), + short_item(local::tag::USAGE_MAXIMUM, ui); } } // namespace hid::rdf diff --git a/hid-rp/hid/rdf/parser.hpp b/hid-rp/hid/rdf/parser.hpp index 0ee4eee..c51a5de 100644 --- a/hid-rp/hid/rdf/parser.hpp +++ b/hid-rp/hid/rdf/parser.hpp @@ -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()); } } @@ -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 -constexpr usage_id_type get_application_usage_id(const descriptor_view_base& desc_view) +constexpr usage_t get_application_usage_id(const descriptor_view_base& desc_view) { /// @brief Internal class that implements the parsing logic for the specific task. struct application_usage_id_parser : public parser @@ -375,7 +375,7 @@ constexpr usage_id_type get_application_usage_id(const descriptor_view_base constexpr short_item(TTag tag, TData data) : short_item(tag) { - static_assert(std::is_integral_v or std::is_enum_v); - auto d = static_cast(data); for (byte_type i = 0; i < DATA_SIZE; ++i) { diff --git a/hid-rp/hid/usage.hpp b/hid-rp/hid/usage.hpp index ec46765..70f9983 100644 --- a/hid-rp/hid/usage.hpp +++ b/hid-rp/hid/usage.hpp @@ -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::max(); -constexpr std::size_t USAGE_PAGE_OFFSET = (8 * sizeof(usage_index_type)); -constexpr usage_id_type USAGE_PAGE_ID_MASK = std::numeric_limits::max() - << USAGE_PAGE_OFFSET; +using page_id_t = std::uint16_t; +using usage_id_t = std::uint16_t; namespace page { @@ -34,58 +26,69 @@ namespace page template 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 -constexpr std::size_t usage_size() -{ - return (page::info::max_usage & USAGE_INDEX_MASK) > std::numeric_limits::max() - ? 2 - : 1; -} -} // namespace local -namespace global +concept UsageType = (sizeof(T) <= sizeof(usage_id_t)) and (page::info::page_id > 0); + +namespace rdf::global { -template +template constexpr std::size_t usage_page_size() { - return (page::info::base_id >> USAGE_PAGE_OFFSET) > std::numeric_limits::max() - ? 2 - : 1; + return page::info::page_id > std::numeric_limits::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 - constexpr bool operator==(const T& rhs) const - { - return (static_cast(rhs) & USAGE_INDEX_MASK) == - static_cast(*this); - } - template - 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 + constexpr usage_t(T u) + : value_((page::info::page_id << 16) | static_cast(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::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_ diff --git a/modules/hid-usage-tables b/modules/hid-usage-tables index f7feec0..bc36859 160000 --- a/modules/hid-usage-tables +++ b/modules/hid-usage-tables @@ -1 +1 @@ -Subproject commit f7feec0e832519e12eb6566d5f00e3664a81d5a4 +Subproject commit bc36859afa114013c70a6a76ad44f83c091a920f