Skip to content

Commit

Permalink
make report helpers more flexible
Browse files Browse the repository at this point in the history
  • Loading branch information
benedekkupper committed Feb 22, 2024
1 parent aa88e0e commit ce590e8
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 31 deletions.
8 changes: 4 additions & 4 deletions hid-rp/hid/app/keyboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ static constexpr auto keys_input_report_descriptor()
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>
{
hid::report::bitset<page::keyboard_keypad, page::keyboard_keypad::KEYBOARD_LEFT_CONTROL,
page::keyboard_keypad::KEYBOARD_RIGHT_GUI>
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;
hid::report_array<page::keyboard_keypad, ROLLOVER_LIMIT> scancodes;

constexpr keys_input_report() = default;

Expand Down Expand Up @@ -111,7 +111,7 @@ static constexpr auto leds_output_report_descriptor()
template <uint8_t REPORT_ID = 0>
struct output_report : public hid::report::base<hid::report::type::OUTPUT, REPORT_ID>
{
hid::report::bitset<page::leds, page::leds::NUM_LOCK, page::leds::KANA> leds;
hid::report_bitset<page::leds, page::leds::NUM_LOCK, page::leds::KANA> leds;
};

template <uint8_t REPORT_ID = 0>
Expand Down
2 changes: 1 addition & 1 deletion hid-rp/hid/app/mouse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace hid::app::mouse
template <uint8_t REPORT_ID = 0>
struct report : public hid::report::base<hid::report::type::INPUT, REPORT_ID>
{
hid::report::bitset<page::button, page::button(1), page::button(3)> buttons;
hid::report_bitset<page::button, page::button(1), page::button(3)> buttons;
std::int8_t x{};
std::int8_t y{};

Expand Down
32 changes: 17 additions & 15 deletions hid-rp/hid/report_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,49 @@

#include <algorithm>
#include <array>
#include "hid/usage.hpp"
#include "sized_unsigned.hpp"

namespace hid::report
namespace hid
{

/// @brief This class stores usages in an array, as a report field.
/// @tparam T the usage type
/// @tparam SIZE the maximum number of usages that can be stored
/// @tparam TStorage the storage type, which might be different from the usage type
template <UsageType T, std::size_t SIZE, typename TStorage = T>
class array
template <typename T, std::size_t SIZE, typename TStorage = T>
class report_array
{
using numeric_type =
std::conditional_t<std::is_same_v<T, TStorage>, T, sized_unsigned_t<sizeof(T)>>;

public:
bool set(T usage, bool value = true)
{
auto n = static_cast<TStorage>(usage);
auto it = std::find(arr_.begin(), arr_.end(), value ? static_cast<TStorage>(0) : n);
auto n = static_cast<numeric_type>(usage);
auto it = std::find(arr_.begin(), arr_.end(), value ? static_cast<numeric_type>(0) : n);
if (it != arr_.end())
{
*it = value ? n : static_cast<TStorage>(0);
*it = value ? n : static_cast<numeric_type>(0);
return true;
}
return false;
}
constexpr void reset() { arr_.fill(static_cast<TStorage>(0)); }
constexpr void reset() { arr_.fill(static_cast<numeric_type>(0)); }
constexpr bool reset(T usage) { return set(usage, false); }
constexpr bool flip(T usage) { return set(usage, !test(usage)); }
bool test(T usage) const
{
return std::find(arr_.begin(), arr_.end(), static_cast<TStorage>(usage)) != arr_.end();
return std::find(arr_.begin(), arr_.end(), static_cast<numeric_type>(usage)) != arr_.end();
}
constexpr void fill(T usage) { arr_.fill(static_cast<TStorage>(usage)); }
constexpr array() = default;

constexpr bool operator==(const array&) const = default;
constexpr bool operator!=(const array&) const = default;
constexpr void fill(T usage) { arr_.fill(static_cast<numeric_type>(usage)); }
constexpr report_array() = default;
constexpr bool operator==(const report_array&) const = default;
constexpr bool operator!=(const report_array&) const = default;

private:
std::array<TStorage, SIZE> arr_{};
};

} // namespace hid::report
} // namespace hid

#endif // __HID_REPORT_ARRAY_HPP_
23 changes: 12 additions & 11 deletions hid-rp/hid/report_bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@

#include <array>
#include <cassert>
#include "hid/usage.hpp"
#include "sized_unsigned.hpp"

namespace hid::report
namespace hid
{

/// @brief This class stores usages in a bitset, as a report field.
/// @tparam T the usage type
/// @tparam MIN the minimum usage to be stored on a bit
/// @tparam MAX the maximum usage to be stored on a bit
template <UsageType T, T MIN, T MAX>
class bitset
template <typename T, T MIN, T MAX>
class report_bitset
{
using numeric_type = sized_unsigned_t<sizeof(T)>;

public:
constexpr static T min() { return MIN; }
constexpr static T max() { return MAX; }
Expand All @@ -39,7 +41,7 @@ class bitset
{
if (in_range(usage))
{
auto n = static_cast<usage_id_t>(usage) - static_cast<usage_id_t>(min());
auto n = static_cast<numeric_type>(usage) - static_cast<numeric_type>(min());
if (value)
{
bits_[n / 8] |= 1 << (n % 8);
Expand All @@ -62,21 +64,20 @@ class bitset
{
if (in_range(usage))
{
auto n = static_cast<usage_id_t>(usage) - static_cast<usage_id_t>(min());
auto n = static_cast<numeric_type>(usage) - static_cast<numeric_type>(min());
return bits_[n / 8] & (1 << (n % 8));
}
assert(false);
return false;
}
constexpr bitset() = default;

constexpr bool operator==(const bitset&) const = default;
constexpr bool operator!=(const bitset&) const = default;
constexpr report_bitset() = default;
constexpr bool operator==(const report_bitset&) const = default;
constexpr bool operator!=(const report_bitset&) const = default;

private:
std::array<std::uint8_t, (size() + 7) / 8> bits_{};
};

} // namespace hid::report
} // namespace hid

#endif // __HID_REPORT_BITSET_HPP_
48 changes: 48 additions & 0 deletions hid-rp/sized_unsigned.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// @file
///
/// @author Benedek Kupper
/// @date 2024
///
/// @copyright
/// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
/// If a copy of the MPL was not distributed with this file, You can obtain one at
/// https://mozilla.org/MPL/2.0/.
///
#ifndef __SIZED_UNSIGNED_HPP_
#define __SIZED_UNSIGNED_HPP_

#include <type_traits>

/// @brief Lookup unsigned integer of matching size
template <std::size_t SIZE, class T = void>
struct sized_unsigned
{};

template <std::size_t SIZE>
struct sized_unsigned<SIZE, std::enable_if_t<SIZE == 1>>
{
typedef std::uint8_t type;
};
template <std::size_t SIZE>
struct sized_unsigned<SIZE, std::enable_if_t<SIZE == 2>>
{
typedef std::uint16_t type;
};
template <std::size_t SIZE>
struct sized_unsigned<SIZE, std::enable_if_t<SIZE == 4>>
{
typedef std::uint32_t type;
};
template <std::size_t SIZE>
struct sized_unsigned<SIZE, std::enable_if_t<SIZE == 8>>
{
typedef std::uint64_t type;
};

template <std::size_t SIZE>
using sized_unsigned_t = typename sized_unsigned<SIZE>::type;

template <typename T>
concept IntegerConvertable = std::is_convertible_v<T, sized_unsigned_t<sizeof(T)>>;

#endif // __SIZED_UNSIGNED_HPP_

0 comments on commit ce590e8

Please sign in to comment.