forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhiddump.cpp
83 lines (65 loc) · 3.04 KB
/
hiddump.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* Copyright (c) 2025, Sönke Holz <[email protected]>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/ArgsParser.h>
#include <LibCore/File.h>
#include <LibHID/ReportDescriptorParser.h>
#include <LibHID/ReportParser.h>
#include <LibMain/Main.h>
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
StringView report_descriptor_file_name;
Optional<StringView> report_file_name;
Core::ArgsParser args;
args.add_positional_argument(report_descriptor_file_name, "HID Report Descriptor", "report-descriptor-file", Core::ArgsParser::Required::Yes);
args.add_option(report_file_name, "Parse HID Input Report from file", "parse-report", 'r', "report-file");
args.parse(arguments);
auto report_descriptor_file = TRY(Core::File::open(report_descriptor_file_name, Core::File::OpenMode::Read));
auto report_descriptor = TRY(report_descriptor_file->read_until_eof());
if (!report_file_name.has_value())
TRY(HID::dump_report_descriptor(report_descriptor));
HID::ReportDescriptorParser parser { report_descriptor };
auto parsed_descriptor = TRY(parser.parse());
if (report_file_name.has_value()) {
auto report_file = TRY(Core::File::open(report_file_name.value(), Core::File::OpenMode::Read));
auto report = TRY(report_file->read_until_eof());
TRY(HID::parse_input_report(parsed_descriptor, report, [](HID::Field const& field, i64 value) -> ErrorOr<IterationDecision> {
if (field.is_array) {
if (!field.usage_minimum.has_value())
return Error::from_errno(ENOTSUP); // TODO: What are we supposed to do here?
outln("Array: {:#x}", value + field.usage_minimum.value());
} else {
outln("{:#x}: {}", field.usage.value(), value);
}
return IterationDecision::Continue;
}));
return 0;
}
outln();
outln("Input Reports:");
for (auto const& [report_id, report] : parsed_descriptor.input_reports) {
outln(" {:#x}:", report_id);
for (auto const& field : report.fields) {
if (field.end_bit_index - field.start_bit_index == 1)
outln(" Bit {}:", field.start_bit_index);
else
outln(" Bits {}..{} ({} bits):", field.start_bit_index, field.end_bit_index, field.end_bit_index - field.start_bit_index);
if (field.is_array)
outln(" Array");
else
outln(" Variable");
outln(" Logical Minimum: {}", field.logical_minimum);
outln(" Logical Maximum: {}", field.logical_maximum);
if (field.usage.has_value())
outln(" Usage: {:#x}", field.usage.value());
if (field.usage_minimum.has_value())
outln(" Usage Minimum: {:#x}", field.usage_minimum.value());
if (field.usage_maximum.has_value())
outln(" Usage Maximum: {:#x}", field.usage_maximum.value());
outln();
}
}
return 0;
}