Skip to content

Commit 2708264

Browse files
author
Stephen
committed
Allow computation of max report size for other types
1 parent 8949182 commit 2708264

File tree

2 files changed

+61
-27
lines changed

2 files changed

+61
-27
lines changed

libusb/hid.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ extern "C" {
6969
#define DETACH_KERNEL_DRIVER
7070
#endif
7171

72+
enum report_descr_type : uint8_t {
73+
REPORT_DESCR_INPUT = 0x80,
74+
REPORT_DESCR_OUTPUT = 0x90,
75+
REPORT_DESCR_FEATURE = 0xB0,
76+
};
77+
7278
/* Uncomment to enable the retrieval of Usage and Usage Page in
7379
hid_enumerate(). Warning, on platforms different from FreeBSD
7480
this is very invasive as it requires the detach
@@ -279,17 +285,17 @@ static int get_usage(uint8_t *report_descriptor, size_t size,
279285
return -1; /* failure */
280286
}
281287

282-
/* Retrieves the largest input report size (in bytes) from the passed in report descriptor.
288+
/* Retrieves the largest report size (in bytes) from the passed in report descriptor.
283289
The return value is the size on success and -1 on failure. */
284-
static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_size)
290+
static size_t get_max_report_size(uint8_t * report_descriptor, int desc_size, enum report_descr_type report_type)
285291
{
286292
int i = 0;
287293
int size_code;
288294
int data_len, key_size;
289295

290296
int64_t report_size = -1, report_count = -1;
291-
ssize_t cur_size = 0;
292-
ssize_t max_size = -1;
297+
size_t cur_size = 0;
298+
size_t max_size = 0;
293299

294300
while (i < desc_size) {
295301
int key = report_descriptor[i];
@@ -322,7 +328,7 @@ static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_si
322328
if (key_cmd == 0x74) { /* Report Size */
323329
report_size = get_bytes(report_descriptor, desc_size, data_len, i);
324330
}
325-
if (key_cmd == 0x80) { /* Input */
331+
if (key_cmd == report_type) { /* Input / Output / Feature */
326332
if (report_count < 0 || report_size < 0) {
327333
/* We are missing size or count. That isn't good. */
328334
return 0;
@@ -344,13 +350,14 @@ static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_si
344350
max_size = cur_size;
345351
}
346352

347-
if (max_size < 0) {
348-
return -1;
353+
if (max_size == 0) {
354+
// No matching reports found
355+
return 0;
356+
} else {
357+
/* report_size is in bits. Determine the total size convert to bytes
358+
(rounded up), and add one byte for the report number. */
359+
return ((max_size + 7) / 8) + 1;
349360
}
350-
351-
/* report_size is in bits. Determine the total size convert to bytes
352-
(rounded up), and add one byte for the report number. */
353-
return ((max_size + 7) / 8) + 1;
354361
}
355362

356363
#if defined(__FreeBSD__) && __FreeBSD__ < 10
@@ -1305,7 +1312,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa
13051312

13061313
int desc_size = hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, report_descriptor, sizeof(report_descriptor));
13071314
if (desc_size > 0) {
1308-
dev->max_input_report_size = get_max_input_report_size(report_descriptor, desc_size);
1315+
dev->max_input_report_size = get_max_report_size(report_descriptor, desc_size, REPORT_DESCR_INPUT);
13091316
} else {
13101317
dev->max_input_report_size = -1;
13111318
}

libusb/test/max_input_report_size_test.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77

88
#include "../hid.c"
99

10-
static ssize_t parse_max_input_report_size(const char * filename)
10+
struct max_report_sizes {
11+
size_t input;
12+
size_t output;
13+
size_t feature;
14+
};
15+
16+
static int parse_max_input_report_size(const char * filename, struct max_report_sizes * sizes)
1117
{
1218
FILE* file = fopen(filename, "r");
1319
if (file == NULL) {
@@ -20,16 +26,20 @@ static ssize_t parse_max_input_report_size(const char * filename)
2026
while (fgets(line, sizeof(line), file) != NULL) {
2127
unsigned short temp_ushort;
2228
if (sscanf(line, "pp_data->caps_info[0]->ReportByteLength = %hu\n", &temp_ushort) == 1) {
23-
fclose(file);
24-
return (ssize_t)temp_ushort;
29+
sizes->input = (size_t)temp_ushort;
30+
}
31+
if (sscanf(line, "pp_data->caps_info[1]->ReportByteLength = %hu\n", &temp_ushort) == 1) {
32+
sizes->output = (size_t)temp_ushort;
33+
}
34+
if (sscanf(line, "pp_data->caps_info[2]->ReportByteLength = %hu\n", &temp_ushort) == 1) {
35+
sizes->feature = (size_t)temp_ushort;
2536
}
2637
}
2738
}
2839

29-
fprintf(stderr, "Unable to find pp_data->caps_info[0]->ReportByteLength in %s\n", filename);
3040
fclose(file);
3141

32-
return -1;
42+
return 0;
3343
}
3444

3545
static bool read_hex_data_from_text_file(const char *filename, unsigned char *data_out, size_t data_size, size_t *actual_read)
@@ -97,19 +107,36 @@ int main(int argc, char* argv[])
97107
return EXIT_FAILURE;
98108
}
99109

100-
ssize_t expected = parse_max_input_report_size(argv[1]);
101-
if (expected < 0) {
102-
fprintf(stderr, "Unable to expected max input report size from %s\n", argv[1]);
110+
struct max_report_sizes expected;
111+
if (parse_max_input_report_size(argv[1], &expected) < 0) {
112+
fprintf(stderr, "Unable to get expected max report sizes from %s\n", argv[1]);
103113
return EXIT_FAILURE;
104114
}
105115

106-
ssize_t res = (ssize_t)get_max_input_report_size(report_descriptor, report_descriptor_size);
116+
struct max_report_sizes computed = {
117+
.input = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_INPUT),
118+
.output = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_OUTPUT),
119+
.feature = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_FEATURE)
120+
};
107121

108-
if (res != expected) {
109-
fprintf(stderr, "Failed to properly compute size. Got %zd, expected %zd\n", res, expected);
110-
return EXIT_FAILURE;
111-
} else {
112-
printf("Properly computed size: %zd\n", res);
113-
return EXIT_SUCCESS;
122+
int ret = EXIT_SUCCESS;
123+
124+
if (expected.input != computed.input) {
125+
fprintf(stderr, "Failed to properly compute input size. Got %zu, expected %zu\n", computed.input, expected.input);
126+
ret = EXIT_FAILURE;
114127
}
128+
if (expected.output != computed.output) {
129+
fprintf(stderr, "Failed to properly compute output size. Got %zu, expected %zu\n", computed.output, expected.output);
130+
ret = EXIT_FAILURE;
131+
}
132+
if (expected.feature != computed.feature) {
133+
fprintf(stderr, "Failed to properly compute feature size. Got %zu, expected %zu\n", computed.feature, expected.feature);
134+
ret = EXIT_FAILURE;
135+
}
136+
137+
if (ret == EXIT_SUCCESS) {
138+
printf("Properly computed sizes: %zu, %zu, %zu\n", computed.input, computed.output, computed.feature);
139+
}
140+
141+
return ret;
115142
}

0 commit comments

Comments
 (0)