Skip to content

Commit f791bba

Browse files
committed
extend the HID examples, change them to Apache 2.0 license
1 parent 875f44e commit f791bba

File tree

4 files changed

+221
-15
lines changed

4 files changed

+221
-15
lines changed

examples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
add_library(${PROJECT_NAME}-example-hid)
22
target_sources(${PROJECT_NAME}-example-hid
33
PUBLIC
4+
high_resolution_mouse.hpp
45
leds_saving_keyboard.hpp
6+
simple_keyboard.hpp
57
)
68
target_include_directories(${PROJECT_NAME}-example-hid
79
PUBLIC

examples/high_resolution_mouse.hpp

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
#ifndef __HIGH_RESOLUTION_MOUSE_HPP_
3+
#define __HIGH_RESOLUTION_MOUSE_HPP_
4+
5+
#include "hid/application.hpp"
6+
#include <hid/app/mouse.hpp>
7+
#include <hid/report_protocol.hpp>
8+
9+
// Linux only works if a report ID is used, see https://bugzilla.kernel.org/show_bug.cgi?id=220144
10+
template <std::uint8_t MOUSE_REPORT_ID = 1, std::int16_t AXIS_LIMIT = 127>
11+
class high_resolution_mouse : public hid::application
12+
{
13+
static constexpr auto LAST_BUTTON = hid::page::button(3);
14+
static constexpr int16_t MAX_SCROLL_RESOLUTION = 120;
15+
static constexpr int16_t WHEEL_LIMIT = 32767;
16+
17+
public:
18+
template <uint8_t REPORT_ID = 0>
19+
struct mouse_report_base : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
20+
{
21+
hid::report_bitset<hid::page::button, hid::page::button(1), LAST_BUTTON> buttons{};
22+
std::conditional_t<(AXIS_LIMIT > std::numeric_limits<int8_t>::max()), hid::le_int16_t,
23+
int8_t>
24+
x{};
25+
std::conditional_t<(AXIS_LIMIT > std::numeric_limits<int8_t>::max()), hid::le_int16_t,
26+
int8_t>
27+
y{};
28+
std::conditional_t<(WHEEL_LIMIT > std::numeric_limits<int8_t>::max()), hid::le_int16_t,
29+
int8_t>
30+
wheel_y{};
31+
std::conditional_t<(WHEEL_LIMIT > std::numeric_limits<int8_t>::max()), hid::le_int16_t,
32+
int8_t>
33+
wheel_x{};
34+
35+
constexpr mouse_report_base() = default;
36+
37+
bool operator==(const mouse_report_base& other) const = default;
38+
bool operator!=(const mouse_report_base& other) const = default;
39+
40+
bool steady() const { return (x == 0) && (y == 0) && (wheel_y == 0) && (wheel_x == 0); }
41+
};
42+
using mouse_report = mouse_report_base<MOUSE_REPORT_ID>;
43+
using resolution_multiplier_report =
44+
hid::app::mouse::resolution_multiplier_report<MAX_SCROLL_RESOLUTION, MOUSE_REPORT_ID>;
45+
46+
private:
47+
alignas(std::uintptr_t) mouse_report in_report_{};
48+
alignas(std::uintptr_t) resolution_multiplier_report multiplier_report_{};
49+
hid::protocol prot_{};
50+
51+
public:
52+
static constexpr auto report_desc()
53+
{
54+
using namespace hid::page;
55+
using namespace hid::rdf;
56+
57+
// clang-format off
58+
return descriptor(
59+
usage_page<generic_desktop>(),
60+
usage(generic_desktop::MOUSE),
61+
collection::application(
62+
conditional_report_id<MOUSE_REPORT_ID>(),
63+
usage(generic_desktop::POINTER),
64+
collection::physical(
65+
// buttons
66+
usage_extended_limits(button(1), LAST_BUTTON),
67+
logical_limits<1, 1>(0, 1),
68+
report_count(static_cast<uint8_t>(LAST_BUTTON)),
69+
report_size(1),
70+
input::absolute_variable(),
71+
input::byte_padding<static_cast<uint8_t>(LAST_BUTTON)>(),
72+
73+
// relative X,Y directions
74+
usage(generic_desktop::X),
75+
usage(generic_desktop::Y),
76+
logical_limits<(AXIS_LIMIT > std::numeric_limits<int8_t>::max() ? 2 : 1)>(-AXIS_LIMIT, AXIS_LIMIT),
77+
report_count(2),
78+
report_size(AXIS_LIMIT > std::numeric_limits<int8_t>::max() ? 16 : 8),
79+
input::relative_variable(),
80+
81+
hid::app::mouse::high_resolution_scrolling<WHEEL_LIMIT, MAX_SCROLL_RESOLUTION>()
82+
)
83+
)
84+
);
85+
// clang-format on
86+
}
87+
static const hid::report_protocol& report_prot()
88+
{
89+
static constexpr const auto rd{report_desc()};
90+
static constexpr const hid::report_protocol rp{rd};
91+
return rp;
92+
}
93+
94+
demo_mouse()
95+
: hid::application(report_prot())
96+
{}
97+
auto send(const mouse_report& report)
98+
{
99+
in_report_ = report;
100+
return send_report(&in_report_);
101+
}
102+
void start(hid::protocol prot) override
103+
{
104+
prot_ = prot;
105+
multiplier_report_ = {};
106+
receive_report(&multiplier_report_);
107+
}
108+
void stop() override { GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN, 1); }
109+
void set_report(hid::report::type type, const std::span<const uint8_t>& data) override
110+
{
111+
if (type != resolution_multiplier_report::type())
112+
{
113+
return;
114+
}
115+
if (data.size() == sizeof(resolution_multiplier_report))
116+
{
117+
multiplier_report_ =
118+
*reinterpret_cast<const resolution_multiplier_report*>(data.data());
119+
}
120+
else
121+
{
122+
multiplier_report_.resolutions = 0;
123+
}
124+
GPIO_PinWrite(BOARD_LED_RED_GPIO, BOARD_LED_RED_GPIO_PIN,
125+
multiplier_report_.resolutions == 0);
126+
receive_report(&multiplier_report_);
127+
}
128+
void get_report(hid::report::selector select, const std::span<uint8_t>& buffer) override
129+
{
130+
if (select == mouse_report::selector())
131+
{
132+
send_report(&in_report_);
133+
return;
134+
}
135+
if (select == resolution_multiplier_report::selector())
136+
{
137+
send_report(&multiplier_report_);
138+
return;
139+
}
140+
// assert(false);
141+
}
142+
// void in_report_sent(const std::span<const uint8_t>& data) override {}
143+
hid::protocol get_protocol() const override { return prot_; }
144+
const auto& multiplier_report() const { return multiplier_report_; }
145+
};
146+
147+
#endif // __HIGH_RESOLUTION_MOUSE_HPP_

examples/leds_saving_keyboard.hpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,24 @@
1-
/// @file
2-
///
3-
/// @author Benedek Kupper
4-
/// @date 2023
5-
///
6-
/// @copyright
7-
/// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
8-
/// If a copy of the MPL was not distributed with this file, You can obtain one at
9-
/// https://mozilla.org/MPL/2.0/.
10-
///
1+
// SPDX-License-Identifier: Apache-2.0
112
#ifndef __LEDS_SAVING_KEYBOARD_HPP_
123
#define __LEDS_SAVING_KEYBOARD_HPP_
134

5+
#include "hid/application.hpp"
146
#include <hid/app/keyboard.hpp>
157
#include <hid/report_protocol.hpp>
168

17-
#include "hid/application.hpp"
18-
199
/// @brief An HID keyboard application that keeps your selected keyboard LED off.
2010
/// Its purpose is to demonstrate USB communication without any user action.
11+
template <std::uint8_t REPORT_ID = 0>
2112
class leds_saving_keyboard : public hid::application
2213
{
23-
using keys_report = hid::app::keyboard::keys_input_report<0>;
24-
using kb_leds_report = hid::app::keyboard::output_report<0>;
14+
using keys_report = hid::app::keyboard::keys_input_report<REPORT_ID>;
15+
using kb_leds_report = hid::app::keyboard::output_report<REPORT_ID>;
2516

2617
public:
27-
static constexpr auto report_desc() { return hid::app::keyboard::app_report_descriptor<0>(); }
18+
static constexpr auto report_desc()
19+
{
20+
return hid::app::keyboard::app_report_descriptor<REPORT_ID>();
21+
}
2822
static const hid::report_protocol& report_prot()
2923
{
3024
static constexpr const auto rd{report_desc()};

examples/simple_keyboard.hpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
#ifndef __SIMPLE_KEYBOARD_HPP_
3+
#define __SIMPLE_KEYBOARD_HPP_
4+
5+
#include "hid/application.hpp"
6+
#include <hid/app/keyboard.hpp>
7+
#include <hid/report_protocol.hpp>
8+
9+
template <std::uint8_t REPORT_ID = 0>
10+
class simple_keyboard : public hid::application
11+
{
12+
public:
13+
using keys_report = hid::app::keyboard::keys_input_report<REPORT_ID>;
14+
using kb_leds_report = hid::app::keyboard::output_report<REPORT_ID>;
15+
16+
static constexpr auto report_desc()
17+
{
18+
return hid::app::keyboard::app_report_descriptor<REPORT_ID>();
19+
}
20+
static const hid::report_protocol& report_prot()
21+
{
22+
static constexpr const auto rd{report_desc()};
23+
static constexpr const hid::report_protocol rp{rd};
24+
return rp;
25+
}
26+
using leds_callback = etl::delegate<void(const kb_leds_report&)>;
27+
28+
demo_keyboard(leds_callback cbk)
29+
: hid::application(report_prot()), cbk_(cbk)
30+
{}
31+
auto send_key(hid::page::keyboard_keypad key, bool set)
32+
{
33+
// TODO: use alternating buffers when send rate is high
34+
keys_buffer_.scancodes.set(key, set);
35+
return send_report(&keys_buffer_);
36+
}
37+
void start(hid::protocol prot) override
38+
{
39+
prot_ = prot;
40+
receive_report(&leds_buffer_);
41+
}
42+
void stop() override {}
43+
void set_report(hid::report::type type, const std::span<const uint8_t>& data) override
44+
{
45+
auto* out_report = reinterpret_cast<const kb_leds_report*>(data.data());
46+
cbk_(*out_report);
47+
receive_report(&leds_buffer_);
48+
}
49+
void get_report(hid::report::selector select, const std::span<uint8_t>& buffer) override
50+
{
51+
send_report(&keys_buffer_);
52+
}
53+
void in_report_sent(const std::span<const uint8_t>& data) override {}
54+
hid::protocol get_protocol() const override { return prot_; }
55+
56+
private:
57+
alignas(std::uintptr_t) keys_report keys_buffer_{};
58+
alignas(std::uintptr_t) kb_leds_report leds_buffer_{};
59+
leds_callback cbk_;
60+
hid::protocol prot_{};
61+
};
62+
63+
#endif // __SIMPLE_KEYBOARD_HPP_

0 commit comments

Comments
 (0)