Skip to content

Commit be95db0

Browse files
committed
define boot protocol compatible report layouts explicitly
1 parent 84b98bd commit be95db0

5 files changed

Lines changed: 80 additions & 3 deletions

File tree

hid-rp/hid/app/keyboard.hpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ template <uint8_t REPORT_ID = 0, std::size_t ROLLOVER_LIMIT = 6>
4040
}
4141

4242
template <std::uint8_t REPORT_ID = 0, std::size_t ROLLOVER_LIMIT = 6>
43-
struct keys_input_report : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
43+
struct keys_input_report : hid::report::base<hid::report::type::INPUT, REPORT_ID>
4444
{
4545
hid::report_bitset<page::keyboard_keypad, page::keyboard_keypad::KEYBOARD_LEFT_CONTROL,
4646
page::keyboard_keypad::KEYBOARD_RIGHT_GUI>
@@ -74,6 +74,18 @@ struct keys_input_report : public hid::report::base<hid::report::type::INPUT, RE
7474
}
7575
return false;
7676
}
77+
78+
static constexpr boot::mode boot_mode()
79+
requires((REPORT_ID == 0) and (ROLLOVER_LIMIT == 6))
80+
{
81+
return boot::mode::KEYBOARD;
82+
}
83+
};
84+
85+
// Boot protocol has predefined report layout
86+
struct boot_input_report final : keys_input_report<0, 6>
87+
{
88+
using keys_input_report::keys_input_report;
7789
};
7890

7991
template <uint8_t REPORT_ID>
@@ -97,9 +109,21 @@ template <uint8_t REPORT_ID>
97109
}
98110

99111
template <uint8_t REPORT_ID = 0>
100-
struct output_report : public hid::report::base<hid::report::type::OUTPUT, REPORT_ID>
112+
struct output_report : hid::report::base<hid::report::type::OUTPUT, REPORT_ID>
101113
{
102114
hid::report_bitset<page::leds, page::leds::NUM_LOCK, page::leds::KANA> leds;
115+
116+
static constexpr boot::mode boot_mode()
117+
requires(REPORT_ID == 0)
118+
{
119+
return boot::mode::KEYBOARD;
120+
}
121+
};
122+
123+
// Boot protocol has predefined report layout
124+
struct boot_output_report final : output_report<0>
125+
{
126+
using output_report::output_report;
103127
};
104128

105129
template <uint8_t REPORT_ID = 0>

hid-rp/hid/app/mouse.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ struct report : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
2222
x = 0;
2323
y = 0;
2424
}
25+
26+
static constexpr boot::mode boot_mode()
27+
requires((REPORT_ID == 0) and (BUTTONS_COUNT == 3))
28+
{
29+
return boot::mode::MOUSE;
30+
}
31+
};
32+
33+
// Boot protocol has predefined report layout
34+
struct boot_report final : report<0, 3>
35+
{
36+
using report::report;
2537
};
2638

2739
template <uint8_t REPORT_ID = 0, std::size_t BUTTONS_COUNT = 3>

hid-rp/hid/report.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,18 @@ static_assert(base<type::OUTPUT, 0x42>::selector() == selector(0x242));
147147

148148
template <class T, report::type TYPE = T::type(), id::type REPORT_ID = T::ID>
149149
concept Data = std::is_base_of_v<base<TYPE, REPORT_ID>, T>;
150+
151+
template <class T>
152+
concept BootCompatibleData =
153+
Data<T> and std::convertible_to<decltype(T::selector()), report::selector> and
154+
std::convertible_to<decltype(T::boot_mode()), boot::mode> and
155+
(((sizeof(T) == 8) and (T::boot_mode() == boot::mode::KEYBOARD) and
156+
(T::selector().type() == type::INPUT)) or
157+
((sizeof(T) == 1) and (T::boot_mode() == boot::mode::KEYBOARD) and
158+
(T::selector().type() == type::OUTPUT)) or
159+
((sizeof(T) == 3) and (T::boot_mode() == boot::mode::MOUSE) and
160+
(T::selector().type() == type::INPUT)));
161+
150162
} // namespace report
163+
151164
} // namespace hid

hid-rp/hid/report_array.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class report_array
2222
bool set(T usage, bool value = true)
2323
{
2424
auto num = static_cast<numeric_type>(usage);
25-
auto it = std::find(arr_.begin(), arr_.end(), value ? static_cast<numeric_type>(0) : num);
25+
auto* it = std::find(arr_.begin(), arr_.end(), value ? static_cast<numeric_type>(0) : num);
2626
if (it != arr_.end())
2727
{
2828
*it = value ? num : static_cast<numeric_type>(0);

test/keyboard.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "test_framework.hpp"
55

66
using namespace hid::app::keyboard;
7+
using namespace hid::page;
78

89
SUITE(keyboard_)
910
{
@@ -54,4 +55,31 @@ SUITE(keyboard_)
5455
CHECK(hid::rdf::get_application_usage_id(hid::rdf::descriptor_view(desc5)) ==
5556
hid::page::generic_desktop::KEYBOARD);
5657
};
58+
59+
TEST_CASE("report structures")
60+
{
61+
static_assert(keys_input_report<0>::type() == hid::report::type::INPUT);
62+
static_assert(keys_input_report<0>::ID == 0);
63+
static_assert(keys_input_report<0>::has_id() == false);
64+
static_assert(keys_input_report<0>::selector() ==
65+
hid::report::selector(hid::report::type::INPUT, 0));
66+
static_assert(hid::report::BootCompatibleData<boot_input_report>);
67+
static_assert(not hid::report::BootCompatibleData<keys_input_report<5>>);
68+
69+
keys_input_report<0> report0;
70+
report0.set_key_state(keyboard_keypad::KEYBOARD_LEFT_CONTROL, true);
71+
report0.set_key_state(keyboard_keypad::KEYBOARD_RIGHT_GUI, true);
72+
report0.set_key_state(keyboard_keypad::KEYPAD_HEXADECIMAL, true);
73+
CHECK(report0.modifiers.test(keyboard_keypad::KEYBOARD_LEFT_CONTROL));
74+
CHECK(report0.modifiers.test(keyboard_keypad::KEYBOARD_RIGHT_GUI));
75+
CHECK(report0.scancodes.test(keyboard_keypad::KEYPAD_HEXADECIMAL));
76+
77+
static_assert(output_report<5>::type() == hid::report::type::OUTPUT);
78+
static_assert(output_report<5>::ID == 5);
79+
static_assert(output_report<5>::has_id() == true);
80+
static_assert(output_report<5>::selector() ==
81+
hid::report::selector(hid::report::type::OUTPUT, 5));
82+
static_assert(hid::report::BootCompatibleData<boot_output_report>);
83+
static_assert(not hid::report::BootCompatibleData<output_report<5>>);
84+
};
5785
};

0 commit comments

Comments
 (0)