From fe758f91c348152a92d2373ffad96b554211d6c3 Mon Sep 17 00:00:00 2001 From: Stephen Date: Tue, 25 Mar 2025 12:16:38 -0700 Subject: [PATCH 1/4] Properly determine libusb read size for large reports Fixes #274 --- libusb/hid.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/libusb/hid.c b/libusb/hid.c index d2ceef5d3..7b7109daf 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -95,6 +95,8 @@ struct hid_device_ { int interface; uint16_t report_descriptor_size; + /* Includes report number. */ + size_t max_input_report_size; /* Endpoint information */ int input_endpoint; @@ -135,6 +137,7 @@ static libusb_context *usb_context = NULL; uint16_t get_usb_code_for_current_locale(void); static int return_data(hid_device *dev, unsigned char *data, size_t length); +static int hid_get_report_descriptor_libusb(libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size, unsigned char *buf, size_t buf_size); static hid_device *new_hid_device(void) { @@ -276,6 +279,74 @@ static int get_usage(uint8_t *report_descriptor, size_t size, return -1; /* failure */ } +/* Retrieves the largest input report size (in bytes) from the report descriptor. + + Requires an opened device with *claimed interface*. + + The return value is the size on success and -1 on failure. */ +static size_t get_max_input_report_size(libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size) +{ + int i = 0; + int size_code; + int data_len, key_size; + + int64_t report_size = 0, report_count = 0; + ssize_t max_size = -1; + + unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + + int desc_size = hid_get_report_descriptor_libusb(handle, interface_num, expected_report_descriptor_size, report_descriptor, sizeof(report_descriptor)); + if (desc_size < 0) { + return -1; + } + + while (i < desc_size) { + int key = report_descriptor[i]; + int key_cmd = key & 0xfc; + + if ((key & 0xf0) == 0xf0) { + /* This is a Long Item. The next byte contains the + length of the data section (value) for this key. + See the HID specification, version 1.11, section + 6.2.2.3, titled "Long Items." */ + if (i+1 < desc_size) + data_len = report_descriptor[i+1]; + else + data_len = 0; /* malformed report */ + key_size = 3; + } else { + /* This is a Short Item. The bottom two bits of the + key contain the size code for the data section + (value) for this key. Refer to the HID + specification, version 1.11, section 6.2.2.2, + titled "Short Items." */ + size_code = key & 0x3; + data_len = (size_code < 3) ? size_code : 4; + key_size = 1; + } + + if (key_cmd == 0x94) { + report_count = get_bytes(report_descriptor, desc_size, data_len, i); + } + if (key_cmd == 0x74) { + report_size = get_bytes(report_descriptor, desc_size, data_len, i); + } + if (key_cmd == 0x80) { // Input + /* report_size is in bits. Determine the total size (count * size), + convert to bytes (rounded up), and add one byte for the report + number. */ + ssize_t size = (((report_count * report_size) + 7) / 8) + 1; + if (size > max_size) + max_size = size; + } + + /* Skip over this key and it's associated data */ + i += data_len + key_size; + } + + return max_size; +} + #if defined(__FreeBSD__) && __FreeBSD__ < 10 /* The libusb version included in FreeBSD < 10 doesn't have this function. In mainline libusb, it's inlined in libusb.h. This function will bear a striking @@ -1024,7 +1095,14 @@ static void *read_thread(void *param) int res; hid_device *dev = param; uint8_t *buf; - const size_t length = dev->input_ep_max_packet_size; + size_t length; + if (dev->max_input_report_size > 0) { + length = dev->max_input_report_size; + } else { + /* If we were unable to reliably determine the maximum input size, fall back + to the max packet size. */ + length = dev->input_ep_max_packet_size; + } /* Set up the transfer object. */ buf = (uint8_t*) malloc(length); @@ -1216,6 +1294,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa dev->interface = intf_desc->bInterfaceNumber; dev->report_descriptor_size = get_report_descriptor_size_from_interface_descriptors(intf_desc); + dev->max_input_report_size = get_max_input_report_size(dev->device_handle, dev->interface, dev->report_descriptor_size); dev->input_endpoint = 0; dev->input_ep_max_packet_size = 0; From 89491825588a29e84570137ae9312aebf95b4a44 Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 27 Mar 2025 12:00:09 -0700 Subject: [PATCH 2/4] Fixes to report size calculation and added tests --- CMakeLists.txt | 4 +- libusb/CMakeLists.txt | 4 + libusb/hid.c | 62 +++++++----- libusb/test/CMakeLists.txt | 69 ++++++++++++++ libusb/test/max_input_report_size_test.c | 115 +++++++++++++++++++++++ 5 files changed, 228 insertions(+), 26 deletions(-) create mode 100644 libusb/test/CMakeLists.txt create mode 100644 libusb/test/max_input_report_size_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d7086813c..b47fcd24a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,8 +70,8 @@ if(HIDAPI_ENABLE_ASAN) endif() endif() -if(WIN32) - # so far only Windows has tests +if(WIN32 OR HIDAPI_WITH_LIBUSB) + # so far only Windows and LibUSB have tests option(HIDAPI_WITH_TESTS "Build HIDAPI (unit-)tests" ${IS_DEBUG_BUILD}) else() set(HIDAPI_WITH_TESTS OFF) diff --git a/libusb/CMakeLists.txt b/libusb/CMakeLists.txt index 4c458c569..c86987021 100644 --- a/libusb/CMakeLists.txt +++ b/libusb/CMakeLists.txt @@ -105,3 +105,7 @@ if(HIDAPI_INSTALL_TARGETS) endif() hidapi_configure_pc("${PROJECT_ROOT}/pc/hidapi-libusb.pc.in") + +if(HIDAPI_WITH_TESTS) + add_subdirectory(test) +endif() diff --git a/libusb/hid.c b/libusb/hid.c index 7b7109daf..68ad17ee1 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -279,27 +279,18 @@ static int get_usage(uint8_t *report_descriptor, size_t size, return -1; /* failure */ } -/* Retrieves the largest input report size (in bytes) from the report descriptor. - - Requires an opened device with *claimed interface*. - +/* Retrieves the largest input report size (in bytes) from the passed in report descriptor. The return value is the size on success and -1 on failure. */ -static size_t get_max_input_report_size(libusb_device_handle *handle, int interface_num, uint16_t expected_report_descriptor_size) +static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_size) { int i = 0; int size_code; int data_len, key_size; - int64_t report_size = 0, report_count = 0; + int64_t report_size = -1, report_count = -1; + ssize_t cur_size = 0; ssize_t max_size = -1; - unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; - - int desc_size = hid_get_report_descriptor_libusb(handle, interface_num, expected_report_descriptor_size, report_descriptor, sizeof(report_descriptor)); - if (desc_size < 0) { - return -1; - } - while (i < desc_size) { int key = report_descriptor[i]; int key_cmd = key & 0xfc; @@ -325,26 +316,41 @@ static size_t get_max_input_report_size(libusb_device_handle *handle, int interf key_size = 1; } - if (key_cmd == 0x94) { + if (key_cmd == 0x94) { /* Report Count */ report_count = get_bytes(report_descriptor, desc_size, data_len, i); } - if (key_cmd == 0x74) { + if (key_cmd == 0x74) { /* Report Size */ report_size = get_bytes(report_descriptor, desc_size, data_len, i); } - if (key_cmd == 0x80) { // Input - /* report_size is in bits. Determine the total size (count * size), - convert to bytes (rounded up), and add one byte for the report - number. */ - ssize_t size = (((report_count * report_size) + 7) / 8) + 1; - if (size > max_size) - max_size = size; + if (key_cmd == 0x80) { /* Input */ + if (report_count < 0 || report_size < 0) { + /* We are missing size or count. That isn't good. */ + return 0; + } + cur_size += (report_count * report_size); + } + if (key_cmd == 0x84) { /* Report ID */ + if (cur_size > max_size) { + max_size = cur_size; + } + cur_size = 0; } /* Skip over this key and it's associated data */ i += data_len + key_size; } - return max_size; + if (cur_size > max_size) { + max_size = cur_size; + } + + if (max_size < 0) { + return -1; + } + + /* report_size is in bits. Determine the total size convert to bytes + (rounded up), and add one byte for the report number. */ + return ((max_size + 7) / 8) + 1; } #if defined(__FreeBSD__) && __FreeBSD__ < 10 @@ -1294,7 +1300,15 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa dev->interface = intf_desc->bInterfaceNumber; dev->report_descriptor_size = get_report_descriptor_size_from_interface_descriptors(intf_desc); - dev->max_input_report_size = get_max_input_report_size(dev->device_handle, dev->interface, dev->report_descriptor_size); + + unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + + int desc_size = hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, report_descriptor, sizeof(report_descriptor)); + if (desc_size > 0) { + dev->max_input_report_size = get_max_input_report_size(report_descriptor, desc_size); + } else { + dev->max_input_report_size = -1; + } dev->input_endpoint = 0; dev->input_ep_max_packet_size = 0; diff --git a/libusb/test/CMakeLists.txt b/libusb/test/CMakeLists.txt new file mode 100644 index 000000000..95d9a2784 --- /dev/null +++ b/libusb/test/CMakeLists.txt @@ -0,0 +1,69 @@ +add_executable(max_input_report_size_test max_input_report_size_test.c) +set_target_properties(max_input_report_size_test + PROPERTIES + C_STANDARD 11 + C_STANDARD_REQUIRED TRUE +) + +if(TARGET usb-1.0) + target_link_libraries(max_input_report_size_test PRIVATE usb-1.0) +else() + include(FindPkgConfig) + pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0>=1.0.9) + target_link_libraries(max_input_report_size_test PRIVATE PkgConfig::libusb) +endif() + +target_link_libraries(max_input_report_size_test PUBLIC hidapi_include) + +# Each test case requires 2 files: +# .pp_data - textual representation of HIDP_PREPARSED_DATA; +# _expected.rpt_desc - reconstructed HID Report Descriptor out of .pp_data file; +# +# (Non-required by test): +# _real.dpt_desc - the original report rescriptor used to create a test case; +set(HID_DESCRIPTOR_RECONSTRUCT_TEST_CASES + 046D_C52F_0001_000C + 046D_C52F_0001_FF00 + 046D_C52F_0002_0001 + 046D_C52F_0002_FF00 + 17CC_1130_0000_FF01 + 046D_0A37_0001_000C + 046A_0011_0006_0001 + 046D_C077_0002_0001 + 046D_C283_0004_0001 + 046D_B010_0006_0001 + 046D_B010_0002_FF00 + 046D_B010_0002_0001 + 046D_B010_0001_FF00 + 046D_B010_0001_000C + 046D_C534_0001_000C + 046D_C534_0001_FF00 + 046D_C534_0002_0001 + 046D_C534_0002_FF00 + 046D_C534_0006_0001 + 046D_C534_0080_0001 + 047F_C056_0001_000C + 047F_C056_0003_FFA0 + 047F_C056_0005_000B + 045E_02FF_0005_0001 + 1532_00A3_0002_0001 +) + +set(CMAKE_VERSION_SUPPORTS_ENVIRONMENT_MODIFICATION "3.22") + +foreach(TEST_CASE ${HID_DESCRIPTOR_RECONSTRUCT_TEST_CASES}) + set(TEST_PP_DATA "${CMAKE_CURRENT_LIST_DIR}/../../windows/test/data/${TEST_CASE}.pp_data") + if(NOT EXISTS "${TEST_PP_DATA}") + message(FATAL_ERROR "Missing '${TEST_PP_DATA}' file for '${TEST_CASE}' test case") + endif() + set(TEST_EXPECTED_DESCRIPTOR "${CMAKE_CURRENT_LIST_DIR}/../../windows/test/data/${TEST_CASE}_expected.rpt_desc") + if(NOT EXISTS "${TEST_EXPECTED_DESCRIPTOR}") + message(FATAL_ERROR "Missing '${TEST_EXPECTED_DESCRIPTOR}' file for '${TEST_CASE}' test case") + endif() + + add_test(NAME "LibUsbHidMaxInputReportSizeTest_${TEST_CASE}" + COMMAND max_input_report_size_test "${TEST_PP_DATA}" "${TEST_EXPECTED_DESCRIPTOR}" + WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" + #WORKING_DIRECTORY "$" + ) +endforeach() diff --git a/libusb/test/max_input_report_size_test.c b/libusb/test/max_input_report_size_test.c new file mode 100644 index 000000000..340f8e92f --- /dev/null +++ b/libusb/test/max_input_report_size_test.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include + +#include "../hid.c" + +static ssize_t parse_max_input_report_size(const char * filename) +{ + FILE* file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(errno)); + return -1; + } + + char line[256]; + { + while (fgets(line, sizeof(line), file) != NULL) { + unsigned short temp_ushort; + if (sscanf(line, "pp_data->caps_info[0]->ReportByteLength = %hu\n", &temp_ushort) == 1) { + fclose(file); + return (ssize_t)temp_ushort; + } + } + } + + fprintf(stderr, "Unable to find pp_data->caps_info[0]->ReportByteLength in %s\n", filename); + fclose(file); + + return -1; +} + +static bool read_hex_data_from_text_file(const char *filename, unsigned char *data_out, size_t data_size, size_t *actual_read) +{ + size_t read_index = 0; + FILE* file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(errno)); + return false; + } + + bool result = true; + unsigned int val; + char buf[16]; + while (fscanf(file, "%15s", buf) == 1) { + if (sscanf(buf, "0x%X", &val) != 1) { + fprintf(stderr, "Invalid HEX text ('%s') file, got %s\n", filename, buf); + result = false; + goto end; + } + + if (read_index >= data_size) { + fprintf(stderr, "Buffer for file read is too small. Got only %zu bytes to read '%s'\n", data_size, filename); + result = false; + goto end; + } + + if (val > (unsigned char)-1) { + fprintf(stderr, "Invalid HEX text ('%s') file, got a value of: %u\n", filename, val); + result = false; + goto end; + } + + data_out[read_index] = (unsigned char) val; + + read_index++; + } + + if (!feof(file)) { + fprintf(stderr, "Invalid HEX text ('%s') file - failed to read all values\n", filename); + result = false; + goto end; + } + + *actual_read = read_index; + +end: + fclose(file); + return result; +} + + +int main(int argc, char* argv[]) +{ + if (argc != 3) { + fprintf(stderr, "Expected 2 arguments for the test ('<>.pp_data' and '<>_expected.rpt_desc'), got: %d\n", argc - 1); + return EXIT_FAILURE; + } + + printf("Checking: '%s' / '%s'\n", argv[1], argv[2]); + + unsigned char report_descriptor[HID_API_MAX_REPORT_DESCRIPTOR_SIZE]; + size_t report_descriptor_size = 0; + if (!read_hex_data_from_text_file(argv[2], report_descriptor, sizeof(report_descriptor), &report_descriptor_size)) { + return EXIT_FAILURE; + } + + ssize_t expected = parse_max_input_report_size(argv[1]); + if (expected < 0) { + fprintf(stderr, "Unable to expected max input report size from %s\n", argv[1]); + return EXIT_FAILURE; + } + + ssize_t res = (ssize_t)get_max_input_report_size(report_descriptor, report_descriptor_size); + + if (res != expected) { + fprintf(stderr, "Failed to properly compute size. Got %zd, expected %zd\n", res, expected); + return EXIT_FAILURE; + } else { + printf("Properly computed size: %zd\n", res); + return EXIT_SUCCESS; + } +} From 3710895f8e7c9f1e5a4c9336941612411f8a4d7d Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 27 Mar 2025 12:32:55 -0700 Subject: [PATCH 3/4] Allow computation of max report size for other types --- libusb/hid.c | 31 ++++++++----- libusb/test/max_input_report_size_test.c | 57 +++++++++++++++++------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/libusb/hid.c b/libusb/hid.c index 68ad17ee1..281efef7e 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -69,6 +69,12 @@ extern "C" { #define DETACH_KERNEL_DRIVER #endif +enum report_descr_type { + REPORT_DESCR_INPUT = 0x80, + REPORT_DESCR_OUTPUT = 0x90, + REPORT_DESCR_FEATURE = 0xB0, +}; + /* Uncomment to enable the retrieval of Usage and Usage Page in hid_enumerate(). Warning, on platforms different from FreeBSD this is very invasive as it requires the detach @@ -279,17 +285,17 @@ static int get_usage(uint8_t *report_descriptor, size_t size, return -1; /* failure */ } -/* Retrieves the largest input report size (in bytes) from the passed in report descriptor. +/* Retrieves the largest report size (in bytes) from the passed in report descriptor. The return value is the size on success and -1 on failure. */ -static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_size) +static size_t get_max_report_size(uint8_t * report_descriptor, int desc_size, enum report_descr_type report_type) { int i = 0; int size_code; int data_len, key_size; int64_t report_size = -1, report_count = -1; - ssize_t cur_size = 0; - ssize_t max_size = -1; + size_t cur_size = 0; + size_t max_size = 0; while (i < desc_size) { int key = report_descriptor[i]; @@ -322,7 +328,7 @@ static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_si if (key_cmd == 0x74) { /* Report Size */ report_size = get_bytes(report_descriptor, desc_size, data_len, i); } - if (key_cmd == 0x80) { /* Input */ + if (key_cmd == report_type) { /* Input / Output / Feature */ if (report_count < 0 || report_size < 0) { /* We are missing size or count. That isn't good. */ return 0; @@ -344,13 +350,14 @@ static size_t get_max_input_report_size(uint8_t * report_descriptor, int desc_si max_size = cur_size; } - if (max_size < 0) { - return -1; + if (max_size == 0) { + // No matching reports found + return 0; + } else { + /* report_size is in bits. Determine the total size convert to bytes + (rounded up), and add one byte for the report number. */ + return ((max_size + 7) / 8) + 1; } - - /* report_size is in bits. Determine the total size convert to bytes - (rounded up), and add one byte for the report number. */ - return ((max_size + 7) / 8) + 1; } #if defined(__FreeBSD__) && __FreeBSD__ < 10 @@ -1305,7 +1312,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa int desc_size = hid_get_report_descriptor_libusb(dev->device_handle, dev->interface, dev->report_descriptor_size, report_descriptor, sizeof(report_descriptor)); if (desc_size > 0) { - dev->max_input_report_size = get_max_input_report_size(report_descriptor, desc_size); + dev->max_input_report_size = get_max_report_size(report_descriptor, desc_size, REPORT_DESCR_INPUT); } else { dev->max_input_report_size = -1; } diff --git a/libusb/test/max_input_report_size_test.c b/libusb/test/max_input_report_size_test.c index 340f8e92f..462bf2b92 100644 --- a/libusb/test/max_input_report_size_test.c +++ b/libusb/test/max_input_report_size_test.c @@ -7,7 +7,13 @@ #include "../hid.c" -static ssize_t parse_max_input_report_size(const char * filename) +struct max_report_sizes { + size_t input; + size_t output; + size_t feature; +}; + +static int parse_max_input_report_size(const char * filename, struct max_report_sizes * sizes) { FILE* file = fopen(filename, "r"); if (file == NULL) { @@ -20,16 +26,20 @@ static ssize_t parse_max_input_report_size(const char * filename) while (fgets(line, sizeof(line), file) != NULL) { unsigned short temp_ushort; if (sscanf(line, "pp_data->caps_info[0]->ReportByteLength = %hu\n", &temp_ushort) == 1) { - fclose(file); - return (ssize_t)temp_ushort; + sizes->input = (size_t)temp_ushort; + } + if (sscanf(line, "pp_data->caps_info[1]->ReportByteLength = %hu\n", &temp_ushort) == 1) { + sizes->output = (size_t)temp_ushort; + } + if (sscanf(line, "pp_data->caps_info[2]->ReportByteLength = %hu\n", &temp_ushort) == 1) { + sizes->feature = (size_t)temp_ushort; } } } - fprintf(stderr, "Unable to find pp_data->caps_info[0]->ReportByteLength in %s\n", filename); fclose(file); - return -1; + return 0; } 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[]) return EXIT_FAILURE; } - ssize_t expected = parse_max_input_report_size(argv[1]); - if (expected < 0) { - fprintf(stderr, "Unable to expected max input report size from %s\n", argv[1]); + struct max_report_sizes expected; + if (parse_max_input_report_size(argv[1], &expected) < 0) { + fprintf(stderr, "Unable to get expected max report sizes from %s\n", argv[1]); return EXIT_FAILURE; } - ssize_t res = (ssize_t)get_max_input_report_size(report_descriptor, report_descriptor_size); + struct max_report_sizes computed = { + .input = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_INPUT), + .output = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_OUTPUT), + .feature = (size_t)get_max_report_size(report_descriptor, report_descriptor_size, REPORT_DESCR_FEATURE) + }; - if (res != expected) { - fprintf(stderr, "Failed to properly compute size. Got %zd, expected %zd\n", res, expected); - return EXIT_FAILURE; - } else { - printf("Properly computed size: %zd\n", res); - return EXIT_SUCCESS; + int ret = EXIT_SUCCESS; + + if (expected.input != computed.input) { + fprintf(stderr, "Failed to properly compute input size. Got %zu, expected %zu\n", computed.input, expected.input); + ret = EXIT_FAILURE; } + if (expected.output != computed.output) { + fprintf(stderr, "Failed to properly compute output size. Got %zu, expected %zu\n", computed.output, expected.output); + ret = EXIT_FAILURE; + } + if (expected.feature != computed.feature) { + fprintf(stderr, "Failed to properly compute feature size. Got %zu, expected %zu\n", computed.feature, expected.feature); + ret = EXIT_FAILURE; + } + + if (ret == EXIT_SUCCESS) { + printf("Properly computed sizes: %zu, %zu, %zu\n", computed.input, computed.output, computed.feature); + } + + return ret; } From 470c9e98de63caa98edb153852b198ed32ab73ec Mon Sep 17 00:00:00 2001 From: Stephen Date: Thu, 27 Mar 2025 12:47:57 -0700 Subject: [PATCH 4/4] Don't assign -1 to size_t. That's silly --- libusb/hid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libusb/hid.c b/libusb/hid.c index 281efef7e..aee5782d9 100644 --- a/libusb/hid.c +++ b/libusb/hid.c @@ -286,7 +286,7 @@ static int get_usage(uint8_t *report_descriptor, size_t size, } /* Retrieves the largest report size (in bytes) from the passed in report descriptor. - The return value is the size on success and -1 on failure. */ + The return value is the size on success and 0 on failure. */ static size_t get_max_report_size(uint8_t * report_descriptor, int desc_size, enum report_descr_type report_type) { int i = 0; @@ -1314,7 +1314,7 @@ static int hidapi_initialize_device(hid_device *dev, const struct libusb_interfa if (desc_size > 0) { dev->max_input_report_size = get_max_report_size(report_descriptor, desc_size, REPORT_DESCR_INPUT); } else { - dev->max_input_report_size = -1; + dev->max_input_report_size = 0; } dev->input_endpoint = 0;