SDL: hidapi: syncing with mainstream:

From aaba01aee468d9f06fb4b0f8ce9812b85272eca7 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Thu, 23 Nov 2023 11:35:02 +0300
Subject: [PATCH] hidapi: syncing with mainstream:

- macos, pthread_barrier_wait: properly check the wait condition
- windows: Assert that struct has the correct size
- windows: Fix printf/string-related issues
- other miscellaneous stuff irrelevant in SDL. (for symmetry...)
---
 src/hidapi/BUILD.cmake.md                     |   2 +-
 src/hidapi/hidtest/test.c                     |   2 +-
 src/hidapi/libusb/hid.c                       |   2 +-
 src/hidapi/mac/hid.c                          |  20 +--
 src/hidapi/src/CMakeLists.txt                 |   5 +-
 .../windows/hidapi_descriptor_reconstruct.h   |  11 +-
 .../windows/pp_data_dump/pp_data_dump.c       | 130 ++++++++--------
 .../test/hid_report_reconstructor_test.c      | 144 +++++++++---------
 8 files changed, 165 insertions(+), 151 deletions(-)

diff --git a/src/hidapi/BUILD.cmake.md b/src/hidapi/BUILD.cmake.md
index aa5ba740d07d..5555fd2ea6a6 100644
--- a/src/hidapi/BUILD.cmake.md
+++ b/src/hidapi/BUILD.cmake.md
@@ -214,7 +214,7 @@ This is done to let the host project's developer decide what is important (what
     In a _subdirectory build_, even if not set, those variables remain unchanged, so a host project's developer has a full control over the HIDAPI build configuration.
 
 Available CMake targets after `add_subdirectory(hidapi)` _are the same as in case of [standalone build](#standalone-package-build)_, and a few additional ones:
-- `hidapi_include` - the interface library; `hidapi::hidapi` is an alias of it;
+- `hidapi_include` - the interface library; `hidapi::include` is an alias of it;
 - `hidapi_winapi` - library target on Windows; `hidapi::winapi` is an alias of it;
 - `hidapi_darwin` - library target on macOS; `hidapi::darwin` is an alias of it;
 - `hidapi_libusb` - library target for libusb backend; `hidapi::libusb` is an alias of it;
diff --git a/src/hidapi/hidtest/test.c b/src/hidapi/hidtest/test.c
index 94bbf37a33a5..1eb658229a00 100644
--- a/src/hidapi/hidtest/test.c
+++ b/src/hidapi/hidtest/test.c
@@ -77,7 +77,7 @@ void print_device(struct hid_device_info *cur_dev) {
 	printf("  Release:      %hx\n", cur_dev->release_number);
 	printf("  Interface:    %d\n",  cur_dev->interface_number);
 	printf("  Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
-	printf("  Bus type: %d (%s)\n", cur_dev->bus_type, hid_bus_name(cur_dev->bus_type));
+	printf("  Bus type: %u (%s)\n", (unsigned)cur_dev->bus_type, hid_bus_name(cur_dev->bus_type));
 	printf("\n");
 }
 
diff --git a/src/hidapi/libusb/hid.c b/src/hidapi/libusb/hid.c
index b063dafe39f4..f0ec00ca7ff8 100644
--- a/src/hidapi/libusb/hid.c
+++ b/src/hidapi/libusb/hid.c
@@ -2088,7 +2088,7 @@ uint16_t get_usb_code_for_current_locale(void)
 		return 0x0;
 
 	/* Make a copy of the current locale string. */
-	strncpy(search_string, locale, sizeof(search_string));
+	strncpy(search_string, locale, sizeof(search_string)-1);
 	search_string[sizeof(search_string)-1] = '\0';
 
 	/* Chop off the encoding part, and make it lower case. */
diff --git a/src/hidapi/mac/hid.c b/src/hidapi/mac/hid.c
index 1eb49b5d3120..ee6666b6963a 100644
--- a/src/hidapi/mac/hid.c
+++ b/src/hidapi/mac/hid.c
@@ -54,15 +54,15 @@ static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrie
 {
 	(void) attr;
 
-	if(count == 0) {
+	if (count == 0) {
 		errno = EINVAL;
 		return -1;
 	}
 
-	if(pthread_mutex_init(&barrier->mutex, 0) < 0) {
+	if (pthread_mutex_init(&barrier->mutex, 0) < 0) {
 		return -1;
 	}
-	if(pthread_cond_init(&barrier->cond, 0) < 0) {
+	if (pthread_cond_init(&barrier->cond, 0) < 0) {
 		pthread_mutex_destroy(&barrier->mutex);
 		return -1;
 	}
@@ -83,16 +83,18 @@ static int pthread_barrier_wait(pthread_barrier_t *barrier)
 {
 	pthread_mutex_lock(&barrier->mutex);
 	++(barrier->count);
-	if(barrier->count >= barrier->trip_count)
-	{
+	if (barrier->count >= barrier->trip_count) {
 		barrier->count = 0;
-		pthread_cond_broadcast(&barrier->cond);
 		pthread_mutex_unlock(&barrier->mutex);
+		pthread_cond_broadcast(&barrier->cond);
 		return 1;
 	}
-	else
-	{
-		pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+	else {
+		do {
+			pthread_cond_wait(&barrier->cond, &(barrier->mutex));
+		}
+		while (barrier->count != 0);
+
 		pthread_mutex_unlock(&barrier->mutex);
 		return 0;
 	}
diff --git a/src/hidapi/src/CMakeLists.txt b/src/hidapi/src/CMakeLists.txt
index d08224be8ed4..507b2d13e231 100644
--- a/src/hidapi/src/CMakeLists.txt
+++ b/src/hidapi/src/CMakeLists.txt
@@ -68,8 +68,9 @@ function(hidapi_configure_pc PC_IN_FILE)
     get_filename_component(PC_IN_FILENAME "${PC_IN_FILE}" NAME_WE)
     set(PC_FILE "${CMAKE_CURRENT_BINARY_DIR}/pc/${PC_IN_FILENAME}.pc")
     configure_file("${PC_IN_FILE}" "${PC_FILE}" @ONLY)
-
-    install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
+    if(HIDAPI_INSTALL_TARGETS)
+        install(FILES "${PC_FILE}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
+    endif()
 endfunction()
 
 # The library
diff --git a/src/hidapi/windows/hidapi_descriptor_reconstruct.h b/src/hidapi/windows/hidapi_descriptor_reconstruct.h
index 6f3e37f744c4..a6223b6a4027 100644
--- a/src/hidapi/windows/hidapi_descriptor_reconstruct.h
+++ b/src/hidapi/windows/hidapi_descriptor_reconstruct.h
@@ -37,6 +37,7 @@
 #include <windows.h>
 
 #include "hidapi_hidsdi.h"
+/*#include <assert.h>*/
 
 #define NUM_OF_HIDP_REPORT_TYPES 3
 
@@ -125,6 +126,14 @@ typedef struct hid_pp_link_collection_node_ {
 	// Same as the public API structure HIDP_LINK_COLLECTION_NODE, but without PVOID UserContext at the end
 } hid_pp_link_collection_node, *phid_pp_link_collection_node;
 
+// Note: This is risk-reduction-measure for this specific struct, as it has ULONG bit-field.
+//       Although very unlikely, it might still be possible that the compiler creates a memory layout that is
+//       not binary compatile.
+//       Other structs are not checked at the time of writing.
+//static_assert(sizeof(struct hid_pp_link_collection_node_) == 16,
+//    "Size of struct hid_pp_link_collection_node_ not as expected. This might break binary compatibility");
+SDL_COMPILE_TIME_ASSERT(hid_pp_link_collection_node_, sizeof(struct hid_pp_link_collection_node_) == 16);
+
 typedef struct hidp_unknown_token_ {
 	UCHAR Token; /* Specifies the one-byte prefix of a global item. */
 	UCHAR Reserved[3];
@@ -213,7 +222,7 @@ typedef struct hidp_preparsed_data_ {
 	USHORT FirstByteOfLinkCollectionArray;
 	USHORT NumberLinkCollectionNodes;
 
-#if defined(__MINGW32__) || defined(__CYGWIN__)
+#ifndef _MSC_VER
 	// MINGW fails with: Flexible array member in union not supported
 	// Solution: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
 	union {
diff --git a/src/hidapi/windows/pp_data_dump/pp_data_dump.c b/src/hidapi/windows/pp_data_dump/pp_data_dump.c
index 561dc96af65a..d5df68b50f52 100644
--- a/src/hidapi/windows/pp_data_dump/pp_data_dump.c
+++ b/src/hidapi/windows/pp_data_dump/pp_data_dump.c
@@ -1,95 +1,95 @@
-
+#if defined(__MINGW32__)
+	// Needed for %hh
+	#define __USE_MINGW_ANSI_STDIO 1
+#endif
 
 #include <hid.c>
 #include <../windows/hidapi_descriptor_reconstruct.h>
 
 #include <hidapi.h>
 
-#if defined(__MINGW32__)
-#pragma GCC diagnostic ignored "-Wformat"
-#pragma GCC diagnostic ignored "-Wformat-extra-args"
-#endif
-
 void dump_hid_pp_cap(FILE* file, phid_pp_cap pp_cap, unsigned int cap_idx) {
-	fprintf(file, "pp_data->cap[%d]->UsagePage                    = 0x%04hX\n", cap_idx, pp_cap->UsagePage);
-	fprintf(file, "pp_data->cap[%d]->ReportID                     = 0x%02hhX\n", cap_idx, pp_cap->ReportID);
-	fprintf(file, "pp_data->cap[%d]->BitPosition                  = %hhu\n", cap_idx, pp_cap->BitPosition);
-	fprintf(file, "pp_data->cap[%d]->BitSize                      = %hu\n", cap_idx, pp_cap->ReportSize);
-	fprintf(file, "pp_data->cap[%d]->ReportCount                  = %hu\n", cap_idx, pp_cap->ReportCount);
-	fprintf(file, "pp_data->cap[%d]->BytePosition                 = 0x%04hX\n", cap_idx, pp_cap->BytePosition);
-	fprintf(file, "pp_data->cap[%d]->BitCount                     = %hu\n", cap_idx, pp_cap->BitCount);
-	fprintf(file, "pp_data->cap[%d]->BitField                     = 0x%02lX\n", cap_idx, pp_cap->BitField);
-	fprintf(file, "pp_data->cap[%d]->NextBytePosition             = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition);
-	fprintf(file, "pp_data->cap[%d]->LinkCollection               = 0x%04hX\n", cap_idx, pp_cap->LinkCollection);
-	fprintf(file, "pp_data->cap[%d]->LinkUsagePage                = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage);
-	fprintf(file, "pp_data->cap[%d]->LinkUsage                    = 0x%04hX\n", cap_idx, pp_cap->LinkUsage);
+	fprintf(file, "pp_data->cap[%u]->UsagePage                    = 0x%04hX\n", cap_idx, pp_cap->UsagePage);
+	fprintf(file, "pp_data->cap[%u]->ReportID                     = 0x%02hhX\n", cap_idx, pp_cap->ReportID);
+	fprintf(file, "pp_data->cap[%u]->BitPosition                  = %hhu\n", cap_idx, pp_cap->BitPosition);
+	fprintf(file, "pp_data->cap[%u]->BitSize                      = %hu\n", cap_idx, pp_cap->ReportSize);
+	fprintf(file, "pp_data->cap[%u]->ReportCount                  = %hu\n", cap_idx, pp_cap->ReportCount);
+	fprintf(file, "pp_data->cap[%u]->BytePosition                 = 0x%04hX\n", cap_idx, pp_cap->BytePosition);
+	fprintf(file, "pp_data->cap[%u]->BitCount                     = %hu\n", cap_idx, pp_cap->BitCount);
+	fprintf(file, "pp_data->cap[%u]->BitField                     = 0x%02lX\n", cap_idx, pp_cap->BitField);
+	fprintf(file, "pp_data->cap[%u]->NextBytePosition             = 0x%04hX\n", cap_idx, pp_cap->NextBytePosition);
+	fprintf(file, "pp_data->cap[%u]->LinkCollection               = 0x%04hX\n", cap_idx, pp_cap->LinkCollection);
+	fprintf(file, "pp_data->cap[%u]->LinkUsagePage                = 0x%04hX\n", cap_idx, pp_cap->LinkUsagePage);
+	fprintf(file, "pp_data->cap[%u]->LinkUsage                    = 0x%04hX\n", cap_idx, pp_cap->LinkUsage);
 
 	// 8 Flags in one byte
-	fprintf(file, "pp_data->cap[%d]->IsMultipleItemsForArray      = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray);
-	fprintf(file, "pp_data->cap[%d]->IsButtonCap                  = %hhu\n", cap_idx, pp_cap->IsButtonCap);
-	fprintf(file, "pp_data->cap[%d]->IsPadding                    = %hhu\n", cap_idx, pp_cap->IsPadding);
-	fprintf(file, "pp_data->cap[%d]->IsAbsolute                   = %hhu\n", cap_idx, pp_cap->IsAbsolute);
-	fprintf(file, "pp_data->cap[%d]->IsRange                      = %hhu\n", cap_idx, pp_cap->IsRange);
-	fprintf(file, "pp_data->cap[%d]->IsAlias                      = %hhu\n", cap_idx, pp_cap->IsAlias);
-	fprintf(file, "pp_data->cap[%d]->IsStringRange                = %hhu\n", cap_idx, pp_cap->IsStringRange);
-	fprintf(file, "pp_data->cap[%d]->IsDesignatorRange            = %hhu\n", cap_idx, pp_cap->IsDesignatorRange);
+	fprintf(file, "pp_data->cap[%u]->IsMultipleItemsForArray      = %hhu\n", cap_idx, pp_cap->IsMultipleItemsForArray);
+	fprintf(file, "pp_data->cap[%u]->IsButtonCap                  = %hhu\n", cap_idx, pp_cap->IsButtonCap);
+	fprintf(file, "pp_data->cap[%u]->IsPadding                    = %hhu\n", cap_idx, pp_cap->IsPadding);
+	fprintf(file, "pp_data->cap[%u]->IsAbsolute                   = %hhu\n", cap_idx, pp_cap->IsAbsolute);
+	fprintf(file, "pp_data->cap[%u]->IsRange                      = %hhu\n", cap_idx, pp_cap->IsRange);
+	fprintf(file, "pp_data->cap[%u]->IsAlias                      = %hhu\n", cap_idx, pp_cap->IsAlias);
+	fprintf(file, "pp_data->cap[%u]->IsStringRange                = %hhu\n", cap_idx, pp_cap->IsStringRange);
+	fprintf(file, "pp_data->cap[%u]->IsDesignatorRange            = %hhu\n", cap_idx, pp_cap->IsDesignatorRange);
 
-	fprintf(file, "pp_data->cap[%d]->Reserved1                    = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]);
+	fprintf(file, "pp_data->cap[%u]->Reserved1                    = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->Reserved1[0], pp_cap->Reserved1[1], pp_cap->Reserved1[2]);
 
 	for (int token_idx = 0; token_idx < 4; token_idx++) {
-		fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Token    = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token);
-		fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]);
-		fprintf(file, "pp_data->cap[%d]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField);
+		fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Token    = 0x%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Token);
+		fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].Reserved = 0x%02hhX%02hhX%02hhX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].Reserved[0], pp_cap->UnknownTokens[token_idx].Reserved[1], pp_cap->UnknownTokens[token_idx].Reserved[2]);
+		fprintf(file, "pp_data->cap[%u]->pp_cap->UnknownTokens[%d].BitField = 0x%08lX\n", cap_idx, token_idx, pp_cap->UnknownTokens[token_idx].BitField);
 	}
 
 	if (pp_cap->IsRange) {
-		fprintf(file, "pp_data->cap[%d]->Range.UsageMin                     = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin);
-		fprintf(file, "pp_data->cap[%d]->Range.UsageMax                     = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax);
-		fprintf(file, "pp_data->cap[%d]->Range.StringMin                    = %hu\n", cap_idx, pp_cap->Range.StringMin);
-		fprintf(file, "pp_data->cap[%d]->Range.StringMax                    = %hu\n", cap_idx, pp_cap->Range.StringMax);
-		fprintf(file, "pp_data->cap[%d]->Range.DesignatorMin                = %hu\n", cap_idx, pp_cap->Range.DesignatorMin);
-		fprintf(file, "pp_data->cap[%d]->Range.DesignatorMax                = %hu\n", cap_idx, pp_cap->Range.DesignatorMax);
-		fprintf(file, "pp_data->cap[%d]->Range.DataIndexMin                 = %hu\n", cap_idx, pp_cap->Range.DataIndexMin);
-		fprintf(file, "pp_data->cap[%d]->Range.DataIndexMax                 = %hu\n", cap_idx, pp_cap->Range.DataIndexMax);
+		fprintf(file, "pp_data->cap[%u]->Range.UsageMin                     = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMin);
+		fprintf(file, "pp_data->cap[%u]->Range.UsageMax                     = 0x%04hX\n", cap_idx, pp_cap->Range.UsageMax);
+		fprintf(file, "pp_data->cap[%u]->Range.StringMin                    = %hu\n", cap_idx, pp_cap->Range.StringMin);
+		fprintf(file, "pp_data->cap[%u]->Range.StringMax                    = %hu\n", cap_idx, pp_cap->Range.StringMax);
+		fprintf(file, "pp_data->cap[%u]->Range.DesignatorMin                = %hu\n", cap_idx, pp_cap->Range.DesignatorMin);
+		fprintf(file, "pp_data->cap[%u]->Range.DesignatorMax                = %hu\n", cap_idx, pp_cap->Range.DesignatorMax);
+		fprintf(file, "pp_data->cap[%u]->Range.DataIndexMin                 = %hu\n", cap_idx, pp_cap->Range.DataIndexMin);
+		fprintf(file, "pp_data->cap[%u]->Range.DataIndexMax                 = %hu\n", cap_idx, pp_cap->Range.DataIndexMax);
 	}
 	else {
-		fprintf(file, "pp_data->cap[%d]->NotRange.Usage                        = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage);
-		fprintf(file, "pp_data->cap[%d]->NotRange.Reserved1                    = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1);
-		fprintf(file, "pp_data->cap[%d]->NotRange.StringIndex                  = %hu\n", cap_idx, pp_cap->NotRange.StringIndex);
-		fprintf(file, "pp_data->cap[%d]->NotRange.Reserved2                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved2);
-		fprintf(file, "pp_data->cap[%d]->NotRange.DesignatorIndex              = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex);
-		fprintf(file, "pp_data->cap[%d]->NotRange.Reserved3                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved3);
-		fprintf(file, "pp_data->cap[%d]->NotRange.DataIndex                    = %hu\n", cap_idx, pp_cap->NotRange.DataIndex);
-		fprintf(file, "pp_data->cap[%d]->NotRange.Reserved4                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved4);
+		fprintf(file, "pp_data->cap[%u]->NotRange.Usage                        = 0x%04hX\n", cap_idx, pp_cap->NotRange.Usage);
+		fprintf(file, "pp_data->cap[%u]->NotRange.Reserved1                    = 0x%04hX\n", cap_idx, pp_cap->NotRange.Reserved1);
+		fprintf(file, "pp_data->cap[%u]->NotRange.StringIndex                  = %hu\n", cap_idx, pp_cap->NotRange.StringIndex);
+		fprintf(file, "pp_data->cap[%u]->NotRange.Reserved2                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved2);
+		fprintf(file, "pp_data->cap[%u]->NotRange.DesignatorIndex              = %hu\n", cap_idx, pp_cap->NotRange.DesignatorIndex);
+		fprintf(file, "pp_data->cap[%u]->NotRange.Reserved3                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved3);
+		fprintf(file, "pp_data->cap[%u]->NotRange.DataIndex                    = %hu\n", cap_idx, pp_cap->NotRange.DataIndex);
+		fprintf(file, "pp_data->cap[%u]->NotRange.Reserved4                    = %hu\n", cap_idx, pp_cap->NotRange.Reserved4);
 	}
 
 	if (pp_cap->IsButtonCap) {
-		fprintf(file, "pp_data->cap[%d]->Button.LogicalMin                   = %ld\n", cap_idx, pp_cap->Button.LogicalMin);
-		fprintf(file, "pp_data->cap[%d]->Button.LogicalMax                   = %ld\n", cap_idx, pp_cap->Button.LogicalMax);
+		fprintf(file, "pp_data->cap[%u]->Button.LogicalMin                   = %ld\n", cap_idx, pp_cap->Button.LogicalMin);
+		fprintf(file, "pp_data->cap[%u]->Button.LogicalMax                   = %ld\n", cap_idx, pp_cap->Button.LogicalMax);
 	}
 	else
 	{
-		fprintf(file, "pp_data->cap[%d]->NotButton.HasNull                   = %hhu\n", cap_idx, pp_cap->NotButton.HasNull);
-		fprintf(file, "pp_data->cap[%d]->NotButton.Reserved4                 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]);
-		fprintf(file, "pp_data->cap[%d]->NotButton.LogicalMin                = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin);
-		fprintf(file, "pp_data->cap[%d]->NotButton.LogicalMax                = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax);
-		fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMin               = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin);
-		fprintf(file, "pp_data->cap[%d]->NotButton.PhysicalMax               = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax);
+		fprintf(file, "pp_data->cap[%u]->NotButton.HasNull                   = %hhu\n", cap_idx, pp_cap->NotButton.HasNull);
+		fprintf(file, "pp_data->cap[%u]->NotButton.Reserved4                 = 0x%02hhX%02hhX%02hhX\n", cap_idx, pp_cap->NotButton.Reserved4[0], pp_cap->NotButton.Reserved4[1], pp_cap->NotButton.Reserved4[2]);
+		fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMin                = %ld\n", cap_idx, pp_cap->NotButton.LogicalMin);
+		fprintf(file, "pp_data->cap[%u]->NotButton.LogicalMax                = %ld\n", cap_idx, pp_cap->NotButton.LogicalMax);
+		fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMin               = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMin);
+		fprintf(file, "pp_data->cap[%u]->NotButton.PhysicalMax               = %ld\n", cap_idx, pp_cap->NotButton.PhysicalMax);
 	};
-	fprintf(file, "pp_data->cap[%d]->Units                    = %lu\n", cap_idx, pp_cap->Units);
-	fprintf(file, "pp_data->cap[%d]->UnitsExp                 = %lu\n", cap_idx, pp_cap->UnitsExp);
+	fprintf(file, "pp_data->cap[%u]->Units                    = %lu\n", cap_idx, pp_cap->Units);
+	fprintf(file, "pp_data->cap[%u]->UnitsExp                 = %lu\n", cap_idx, pp_cap->UnitsExp);
 }
 
 void dump_hidp_link_collection_node(FILE* file, phid_pp_link_collection_node pcoll, unsigned int coll_idx) {
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->LinkUsage          = 0x%04hX\n", coll_idx, pcoll->LinkUsage);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->LinkUsagePage      = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->Parent             = %hu\n", coll_idx, pcoll->Parent);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->NumberOfChildren   = %hu\n", coll_idx, pcoll->NumberOfChildren);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->NextSibling        = %hu\n", coll_idx, pcoll->NextSibling);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->FirstChild         = %hu\n", coll_idx, pcoll->FirstChild);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->CollectionType     = %d\n", coll_idx, pcoll->CollectionType);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->IsAlias            = %d\n", coll_idx, pcoll->IsAlias);
-	fprintf(file, "pp_data->LinkCollectionArray[%d]->Reserved           = 0x%08X\n", coll_idx, pcoll->Reserved);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsage          = 0x%04hX\n", coll_idx, pcoll->LinkUsage);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->LinkUsagePage      = 0x%04hX\n", coll_idx, pcoll->LinkUsagePage);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->Parent             = %hu\n", coll_idx, pcoll->Parent);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->NumberOfChildren   = %hu\n", coll_idx, pcoll->NumberOfChildren);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->NextSibling        = %hu\n", coll_idx, pcoll->NextSibling);
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->FirstChild         = %hu\n", coll_idx, pcoll->FirstChild);
+	// The compilers are not consistent on ULONG-bit-fields: They lose the unsinged or define them as int.
+	// Thus just always cast them to unsinged int, which should be fine, as the biggest bit-field is 28 bit
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->CollectionType     = %u\n", coll_idx, (unsigned int)(pcoll->CollectionType));
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->IsAlias            = %u\n", coll_idx, (unsigned int)(pcoll->IsAlias));
+	fprintf(file, "pp_data->LinkCollectionArray[%u]->Reserved           = 0x%08X\n", coll_idx, (unsigned int)(pcoll->Reserved));
 }
 
 int dump_pp_data(FILE* file, hid_device* dev)
diff --git a/src/hidapi/windows/test/hid_report_reconstructor_test.c b/src/hidapi/windows/test/hid_report_reconstructor_test.c
index 4c94fd9766db..a7adeb54d042 100644
--- a/src/hidapi/windows/test/hid_report_reconstructor_test.c
+++ b/src/hidapi/windows/test/hid_report_reconstructor_test.c
@@ -1,12 +1,14 @@
+#if defined(__MINGW32__)
+	// Needed for %zu
+	#define __USE_MINGW_ANSI_STDIO 1
+#endif
+
 #include "../hidapi_descriptor_reconstruct.h"
 
 #include <stddef.h>
 #include <stdio.h>
 #include <string.h>
 
-#if defined(__MINGW32__)
-#pragma GCC diagnostic ignored "-Wformat"
-#endif
 static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename)
 {
 	FILE* file;
@@ -107,25 +109,25 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename)
 		if (sscanf(line, "pp_data->UsagePage                            = 0x%04hX\n", &pp_data->UsagePage)) continue;
 		if (sscanf(line, "pp_data->Reserved                             = 0x%04hX%04hX\n", &pp_data->Reserved[0], &pp_data->Reserved[1])) continue;
 
-		if (sscanf(line, "pp_data->caps_info[%d]", &rt_idx) == 1) {
+		if (sscanf(line, "pp_data->caps_info[%u]", &rt_idx) == 1) {
 			const size_t caps_info_count = sizeof(pp_data->caps_info) / sizeof(pp_data->caps_info[0]);
 			if (rt_idx >= caps_info_count) {
 				fprintf(stderr, "Broken pp_data file, pp_data->caps_info[<idx>] can have at most %zu elements, accessing %ud, (%s)", caps_info_count, rt_idx, line);
 				continue;
 			}
-			if (sscanf(line, "pp_data->caps_info[%d]->FirstCap           = %hu\n", &rt_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->caps_info[%u]->FirstCap           = %hu\n", &rt_idx, &temp_ushort) == 2) {
 				pp_data->caps_info[rt_idx].FirstCap = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->caps_info[%d]->LastCap            = %hu\n", &rt_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->caps_info[%u]->LastCap            = %hu\n", &rt_idx, &temp_ushort) == 2) {
 				pp_data->caps_info[rt_idx].LastCap = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->caps_info[%d]->NumberOfCaps       = %hu\n", &rt_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->caps_info[%u]->NumberOfCaps       = %hu\n", &rt_idx, &temp_ushort) == 2) {
 				pp_data->caps_info[rt_idx].NumberOfCaps = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->caps_info[%d]->ReportByteLength   = %hu\n", &rt_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->caps_info[%u]->ReportByteLength   = %hu\n", &rt_idx, &temp_ushort) == 2) {
 				pp_data->caps_info[rt_idx].ReportByteLength = temp_ushort;
 				continue;
 			}
@@ -140,7 +142,7 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename)
 			continue;
 		}
 
-		if (sscanf(line, "pp_data->cap[%d]", &caps_idx) == 1) {
+		if (sscanf(line, "pp_data->cap[%u]", &caps_idx) == 1) {
 			if (pp_data->FirstByteOfLinkCollectionArray == 0) {
 				fprintf(stderr, "Error reading pp_data file (%s): FirstByteOfLinkCollectionArray is 0 or not reported yet\n", line);
 				continue;
@@ -149,113 +151,113 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename)
 				fprintf(stderr, "Error reading pp_data file (%s): the caps index (%u) is out of pp_data bytes boundary (%hu vs %hu)\n", line, caps_idx, (unsigned short) ((caps_idx + 1) * sizeof(hid_pp_cap)), pp_data->FirstByteOfLinkCollectionArray);
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->UsagePage                    = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->UsagePage                    = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
 				pp_data->caps[caps_idx].UsagePage = temp_usage;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->ReportID                     = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->ReportID                     = 0x%02hhX\n", &caps_idx, &temp_uchar[0]) == 2) {
 				pp_data->caps[caps_idx].ReportID = temp_uchar[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->BitPosition                  = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->BitPosition                  = %hhu\n", &caps_idx, &temp_uchar[0]) == 2) {
 				pp_data->caps[caps_idx].BitPosition = temp_uchar[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->BitSize                      = %hu\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->BitSize                      = %hu\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].ReportSize = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->ReportCount                  = %hu\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->ReportCount                  = %hu\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].ReportCount = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->BytePosition                 = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->BytePosition                 = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].BytePosition = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->BitCount                     = %hu\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->BitCount                     = %hu\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].BitCount = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->BitField                     = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->BitField                     = 0x%02lX\n", &caps_idx, &temp_ulong) == 2) {
 				pp_data->caps[caps_idx].BitField = temp_ulong;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->NextBytePosition             = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->NextBytePosition             = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].NextBytePosition = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->LinkCollection               = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->LinkCollection               = 0x%04hX\n", &caps_idx, &temp_ushort) == 2) {
 				pp_data->caps[caps_idx].LinkCollection = temp_ushort;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->LinkUsagePage                = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->LinkUsagePage                = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
 				pp_data->caps[caps_idx].LinkUsagePage = temp_usage;
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->LinkUsage                    = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->LinkUsage                    = 0x%04hX\n", &caps_idx, &temp_usage) == 2) {
 				pp_data->caps[caps_idx].LinkUsage = temp_usage;
 				continue;
 			}
 
 			// 8 Flags in one byte
-			if (sscanf(line, "pp_data->cap[%d]->IsMultipleItemsForArray      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsMultipleItemsForArray      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsMultipleItemsForArray = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsButtonCap                  = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsButtonCap                  = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsButtonCap = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsPadding                    = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsPadding                    = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsPadding = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsAbsolute                   = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsAbsolute                   = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsAbsolute = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsRange                      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsRange                      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsRange = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsAlias                      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsAlias                      = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsAlias = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsStringRange                = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsStringRange                = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
 				pp_data->caps[caps_idx].IsStringRange = temp_boolean[0];
 				continue;
 			}
-			if (sscanf(line, "pp_data->cap[%d]->IsDesignatorRange            = %hhu\n", &caps_idx, &temp_boolean[0]) == 2) {
+			if (sscanf(line, "pp_data->cap[%u]->IsDesignatorR

(Patch may be truncated, please check the link at the top of this post.)