Skip to content

Commit

Permalink
split HID usage and its page
Browse files Browse the repository at this point in the history
  • Loading branch information
cvuchener committed Aug 9, 2021
1 parent 433b06b commit d843ed4
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 37 deletions.
12 changes: 6 additions & 6 deletions src/libhidpp/hid/RawDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void RawDevice::logReportDescriptor () const
if (!debug)
return;
for (const auto &collection: _report_desc.collections) {
debug << "Collection: " << std::hex << collection.usage << std::dec << std::endl;
debug << "Collection: " << std::hex << uint32_t (collection.usage) << std::dec << std::endl;
for (const auto &[id, fields]: collection.reports) {
const char *type;
switch (id.type) {
Expand All @@ -45,12 +45,12 @@ void RawDevice::logReportDescriptor () const
f.count, f.size);
struct {
Log &log;
void operator() (const std::vector<uint32_t> &usages) const {
for (uint32_t usage: usages)
log << " " << usage;
void operator() (const std::vector<Usage> &usages) const {
for (auto usage: usages)
log << " " << uint32_t (usage);
}
void operator() (const std::pair<uint32_t, uint32_t> &usages) const {
log << " [" << usages.first << ", " << usages.second << "]";
void operator() (const std::pair<Usage, Usage> &usages) const {
log << " [" << uint32_t (usages.first) << ", " << uint32_t (usages.second) << "]";
}
} print_usage{debug};
debug << " Usages:" << std::hex;
Expand Down
22 changes: 9 additions & 13 deletions src/libhidpp/hid/RawDevice_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,6 @@ struct preparsed_data_item
};
static_assert(sizeof(preparsed_data_item) == 104);

static inline uint32_t make_usage(uint16_t usage_page, uint16_t usage)
{
return (uint32_t (usage_page) << 16) | usage;
}

using namespace HID;

struct RawDevice::PrivateImpl
Expand Down Expand Up @@ -243,7 +238,7 @@ RawDevice::RawDevice (const std::string &path):
auto item = reinterpret_cast<const preparsed_data_item *> (header+1);

auto &collection = _report_desc.collections.emplace_back ();
collection.usage = make_usage (header->usage_page, header->usage);
collection.usage = {header->usage_page, header->usage};

for (auto [report_type, item_count]: {
std::make_tuple (ReportID::Type::Input, header->input_item_count),
Expand All @@ -258,24 +253,25 @@ RawDevice::RawDevice (const std::string &path):
if (pos_it->second != -1 && pos_it->second >= pos) {
// Split items are in reverse order, try merging them if the position goes backward
auto &f = it->second.back ();
auto usages = std::get_if<std::vector<uint32_t>> (&f.usages);
auto usages = std::get_if<std::vector<Usage>> (&f.usages);
if (!usages || item->usage_minimum != item->usage_maximum) {
Log::error ("reportdesc") << "Split item is a range item" << std::endl;
continue;
}
auto item_usage = Usage {item->usage_page, item->usage_minimum};
if (item->bit_size != f.size || item->bit_field != f.flags.bits)
Log::error ("reportdesc") << "Split item mismatch" << std::endl;
if (pos_it->second == pos) {
if (item->report_count != f.count)
Log::error ("reportdesc") << "Split item report count mismatch" << std::endl;
usages->insert (usages->begin (), make_usage(item->usage_page, item->usage_minimum));
usages->insert (usages->begin (), item_usage);
}
else {
if (pos_it->second - pos != item->bit_size)
Log::error ("reportdesc") << "Split item unexpected position" << std::endl;
f.count += item->report_count;
if (usages->size () > 1 || usages->front () != item->usage_minimum)
usages->insert (usages->begin (), make_usage (item->usage_page, item->usage_minimum));
if (usages->size () > 1 || usages->front () != item_usage)
usages->insert (usages->begin (), item_usage);
}
}
else {
Expand All @@ -285,11 +281,11 @@ RawDevice::RawDevice (const std::string &path):
f.count = item->report_count;
f.size = item->bit_size;
if (item->usage_minimum == item->usage_maximum)
f.usages = std::vector {make_usage(item->usage_page, item->usage_minimum)};
f.usages = std::vector {Usage {item->usage_page, item->usage_minimum}};
else
f.usages = std::make_pair (
make_usage (item->usage_page, item->usage_minimum),
make_usage (item->usage_page, item->usage_maximum));
Usage {item->usage_page, item->usage_minimum},
Usage {item->usage_page, item->usage_maximum});
}
pos_it->second = pos;
}
Expand Down
24 changes: 13 additions & 11 deletions src/libhidpp/hid/ReportDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,17 @@ struct item_t
uint8_t tag;
unsigned int size;
const uint8_t *data;
uint32_t get_usage (uint16_t default_page) const {
if (size > 4)
HID::Usage get_usage (uint16_t default_page) const {
switch (size) {
case 1:
return HID::Usage (default_page, data[0]);
case 2:
return HID::Usage (default_page, get<uint16_t> ());
case 4:
return HID::Usage (get<uint32_t> ());
default:
throw std::runtime_error ("invalid item size");
uint32_t usage = 0;
if (size <= 2)
usage = uint32_t (default_page) << 16;
for (unsigned int i = 0; i < size; ++i)
usage |= (data[i] & 0xff) << (8*i);
return usage;
}
}
template <typename T>
std::enable_if_t<std::is_unsigned_v<T>, T> get () const {
Expand Down Expand Up @@ -140,8 +142,8 @@ ReportDescriptor ReportDescriptor::fromRawData (const uint8_t *data, std::size_t
std::stack<global_context_t> global;
global.push({});
struct local_context_t {
std::vector<uint32_t> usages;
uint32_t usage_min, usage_max;
std::vector<HID::Usage> usages;
HID::Usage usage_min, usage_max;
} local;
enum {
Closed,
Expand All @@ -167,7 +169,7 @@ ReportDescriptor ReportDescriptor::fromRawData (const uint8_t *data, std::size_t
auto [it, inserted] = descriptor.collections.back ().reports.emplace (id, 0);
ReportField::Flags flags = {item.get<unsigned int> ()};
if (!local.usages.empty () ||
local.usage_min != 0 || local.usage_max != 0 ||
local.usage_min != Usage () || local.usage_max != Usage () ||
!flags.Constant ()) { // exclude padding fields
auto &f = it->second.emplace_back ();
f.flags = flags;
Expand Down
40 changes: 37 additions & 3 deletions src/libhidpp/hid/ReportDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,40 @@ struct ReportID
}
};

struct Usage
{
uint16_t usage_page, usage;

constexpr Usage () noexcept:
usage_page (0), usage (0)
{
}

constexpr Usage (uint16_t usage_page, uint16_t usage) noexcept:
usage_page (usage_page),
usage (usage)
{
}

explicit constexpr Usage (uint32_t usage) noexcept:
usage_page (usage >> 16),
usage (usage)
{
}

explicit constexpr operator uint32_t () const noexcept {
return uint32_t (usage_page) << 16 | usage;
}

inline bool operator== (Usage other) const noexcept {
return usage_page == other.usage_page && usage == other.usage;
}

inline bool operator!= (Usage other) const noexcept {
return usage_page != other.usage_page || usage != other.usage;
}
};

struct ReportField
{
struct Flags {
Expand Down Expand Up @@ -78,8 +112,8 @@ struct ReportField
} flags;
unsigned int count, size;
std::variant<
std::vector<uint32_t>, // usage list
std::pair<uint32_t, uint32_t> // usage range
std::vector<Usage>, // usage list
std::pair<Usage, Usage> // usage range
> usages;
};

Expand All @@ -94,7 +128,7 @@ struct ReportCollection
UsageSwitch = 5,
UsageModifier = 6,
} type;
uint32_t usage;
Usage usage;
std::map<ReportID, std::vector<ReportField>> reports;
};

Expand Down
8 changes: 4 additions & 4 deletions src/libhidpp/hidpp/Report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

using namespace HIDPP;

static bool hasReport(const HID::ReportCollection &collection, HID::ReportID::Type type, uint8_t id, uint32_t usage, unsigned int count)
static bool hasReport(const HID::ReportCollection &collection, HID::ReportID::Type type, uint8_t id, HID::Usage usage, unsigned int count)
{
using namespace HID;
auto it = collection.reports.find (ReportID {type, id});
Expand All @@ -35,7 +35,7 @@ static bool hasReport(const HID::ReportCollection &collection, HID::ReportID::Ty
if (fields.size () != 1)
return false;
const auto &field = fields.front ();
if (auto usages = std::get_if<std::vector<uint32_t>> (&field.usages)) {
if (auto usages = std::get_if<std::vector<Usage>> (&field.usages)) {
return field.flags.Data () && field.flags.Array () &&
field.count == count && field.size == 8 &&
usages->size () == 1 && usages->front () == usage;
Expand All @@ -46,8 +46,8 @@ static bool hasReport(const HID::ReportCollection &collection, HID::ReportID::Ty

bool HIDPP::checkReportDescriptor (const HID::ReportDescriptor &rdesc)
{
static constexpr uint32_t ShortReportUsage = 0xFF000001;
static constexpr uint32_t LongReportUsage = 0xFF000002;
static constexpr auto ShortReportUsage = HID::Usage (0xFF000001);
static constexpr auto LongReportUsage = HID::Usage (0xFF000002);
static constexpr unsigned int ShortReportCount = 6;
static constexpr unsigned int LongReportCount = 19;
bool has_short_input = false;
Expand Down

0 comments on commit d843ed4

Please sign in to comment.