Skip to content

Commit

Permalink
improve the usage handling and add report field helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
benedekkupper committed Feb 19, 2024
1 parent 64c6dd6 commit 7020f2f
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 263 deletions.
79 changes: 23 additions & 56 deletions hid-rp/hid/app/keyboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
#include "hid/page/leds.hpp"
#include "hid/rdf/descriptor.hpp"
#include "hid/report.hpp"
#include "hid/report_array.hpp"
#include "hid/report_bitset.hpp"

namespace hid::app::keyboard
{
template <uint8_t REPORT_ID>
template <uint8_t REPORT_ID = 0, std::size_t ROLLOVER_LIMIT = 6>
static constexpr auto keys_input_report_descriptor()
{
using namespace hid::page;
Expand All @@ -33,81 +35,54 @@ 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),
// key codes
report_size(8),
report_count(6),
report_count(ROLLOVER_LIMIT),
logical_limits<1, 1>(0, keyboard_keypad::KEYPAD_HEXADECIMAL),
usage_limits(nullusage, keyboard_keypad::KEYPAD_HEXADECIMAL),
input::array()
);
// clang-format on
}

template <uint8_t REPORT_ID>
template <std::uint8_t REPORT_ID = 0, std::size_t ROLLOVER_LIMIT = 6>
struct keys_input_report : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
{
uint8_t modifiers = 0;
uint8_t reserved = 0;
std::array<uint8_t, 6> scancodes = {};
hid::report::bitset<page::keyboard_keypad, page::keyboard_keypad::KEYBOARD_LEFT_CONTROL,
page::keyboard_keypad::KEYBOARD_RIGHT_GUI>
modifiers;
std::uint8_t reserved{};
hid::report::array<page::keyboard_keypad, ROLLOVER_LIMIT> scancodes;

constexpr keys_input_report() = default;

constexpr bool set_key_state(page::keyboard_keypad key, bool pressed)
{
using namespace hid::page;

if (key >= keyboard_keypad::LEFTCTRL)
if (modifiers.set(key, pressed))
{
return true;
}
if (scancodes.set(key, pressed))
{
uint8_t mask =
1 << (static_cast<uint8_t>(key) - static_cast<uint8_t>(keyboard_keypad::LEFTCTRL));
if (pressed)
{
modifiers |= mask;
}
else
{
modifiers &= ~mask;
}
return true;
}
else if (pressed)
if (pressed)
{
for (auto& code : scancodes)
{
if (code == 0)
{
code = static_cast<uint8_t>(key);
return true;
}
}
// scancodes buffer full, need to raise rollover error
for (auto& code : scancodes)
{
code = static_cast<uint8_t>(keyboard_keypad::ERRORROLLOVER);
}
return false;
scancodes.fill(keyboard_keypad::ERROR_ROLLOVER);
}
else
{
for (auto& code : scancodes)
{
if (code == static_cast<uint8_t>(key))
{
code = 0;
return true;
}
// clear rollover error when a key is released
else if (code == static_cast<uint8_t>(keyboard_keypad::ERRORROLLOVER))
{
code = 0;
}
}
return false;
// clear rollover error when a key is released
scancodes.reset();
}
return false;
}
};
static_assert(sizeof(keys_input_report<0>) == 8);
Expand All @@ -133,18 +108,10 @@ static constexpr auto leds_output_report_descriptor()
// clang-format on
}

template <uint8_t REPORT_ID>
template <uint8_t REPORT_ID = 0>
struct output_report : public hid::report::base<hid::report::type::OUTPUT, REPORT_ID>
{
uint8_t leds = 0;

constexpr output_report() = default;

constexpr bool get_led_state(page::leds led) const
{
return ((leds >> (static_cast<uint8_t>(led) - static_cast<uint8_t>(page::leds::NUM_LOCK))) &
1) != 0;
}
hid::report::bitset<page::leds, page::leds::NUM_LOCK, page::leds::KANA> leds;
};

template <uint8_t REPORT_ID = 0>
Expand Down
21 changes: 5 additions & 16 deletions hid-rp/hid/app/mouse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,17 @@
#include "hid/page/generic_desktop.hpp"
#include "hid/rdf/descriptor.hpp"
#include "hid/report.hpp"
#include "hid/report_bitset.hpp"

namespace hid::app::mouse
{
template <uint8_t REPORT_ID>
template <uint8_t REPORT_ID = 0>
struct report : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
{
uint8_t buttons = 0;
int8_t x = 0;
int8_t y = 0;
hid::report::bitset<page::button, page::button(1), page::button(3)> buttons;
std::int8_t x{};
std::int8_t y{};

constexpr void set_button_state(page::button b, bool pressed)
{
uint8_t mask = 1 << (static_cast<uint8_t>(b) - 1);
if (pressed)
{
buttons |= mask;
}
else
{
buttons &= ~mask;
}
}
constexpr void reset_movement()
{
x = 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
Loading

0 comments on commit 7020f2f

Please sign in to comment.