From 7e0285b482c080d00e8a39f3364f39b849106943 Mon Sep 17 00:00:00 2001
From: "arnau.nau" <[EMAIL REDACTED]>
Date: Sat, 13 Jun 2026 12:25:45 +0200
Subject: [PATCH] hidapi: fix function pointer type mismatch in backend table
The HIDAPI backend table used function pointers that didn't match the
macro-renamed backend function types, which trips Clang's function sanitizer.
Adding small wrappers so the backend table has the correct function types and
the cast to the backend-specific device type happens inside a direct call.
fixes #15821.
(cherry picked from commit 46d0ecead0f98c0987e86bb01a028f11bc7e5e77)
---
src/hidapi/SDL_hidapi.c | 190 +++++++++++++++++++++++++++-------------
1 file changed, 130 insertions(+), 60 deletions(-)
diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c
index b7ea2cf1595b0..abb85676004f7 100644
--- a/src/hidapi/SDL_hidapi.c
+++ b/src/hidapi/SDL_hidapi.c
@@ -900,83 +900,153 @@ static bool use_libusb_gamecube = true;
struct hidapi_backend
{
- int (*hid_write)(void *device, const unsigned char *data, size_t length);
- int (*hid_read_timeout)(void *device, unsigned char *data, size_t length, int milliseconds);
- int (*hid_read)(void *device, unsigned char *data, size_t length);
- int (*hid_set_nonblocking)(void *device, int nonblock);
- int (*hid_send_feature_report)(void *device, const unsigned char *data, size_t length);
- int (*hid_get_feature_report)(void *device, unsigned char *data, size_t length);
- int (*hid_get_input_report)(void *device, unsigned char *data, size_t length);
- void (*hid_close)(void *device);
- int (*hid_get_manufacturer_string)(void *device, wchar_t *string, size_t maxlen);
- int (*hid_get_product_string)(void *device, wchar_t *string, size_t maxlen);
- int (*hid_get_serial_number_string)(void *device, wchar_t *string, size_t maxlen);
- int (*hid_get_indexed_string)(void *device, int string_index, wchar_t *string, size_t maxlen);
- struct hid_device_info *(*hid_get_device_info)(void *device);
- int (*hid_get_report_descriptor)(void *device, unsigned char *buf, size_t buf_size);
- const wchar_t *(*hid_error)(void *device);
+ int (*hid_write)(hid_device *device, const unsigned char *data, size_t length);
+ int (*hid_read_timeout)(hid_device *device, unsigned char *data, size_t length, int milliseconds);
+ int (*hid_read)(hid_device *device, unsigned char *data, size_t length);
+ int (*hid_set_nonblocking)(hid_device *device, int nonblock);
+ int (*hid_send_feature_report)(hid_device *device, const unsigned char *data, size_t length);
+ int (*hid_get_feature_report)(hid_device *device, unsigned char *data, size_t length);
+ int (*hid_get_input_report)(hid_device *device, unsigned char *data, size_t length);
+ void (*hid_close)(hid_device *device);
+ int (*hid_get_manufacturer_string)(hid_device *device, wchar_t *string, size_t maxlen);
+ int (*hid_get_product_string)(hid_device *device, wchar_t *string, size_t maxlen);
+ int (*hid_get_serial_number_string)(hid_device *device, wchar_t *string, size_t maxlen);
+ int (*hid_get_indexed_string)(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
+ struct hid_device_info *(*hid_get_device_info)(hid_device *device);
+ int (*hid_get_report_descriptor)(hid_device *device, unsigned char *buf, size_t buf_size);
+ const wchar_t *(*hid_error)(hid_device *device);
};
+#define HIDAPI_BACKEND_WRAPPERS(PREFIX, DEVICE_TYPE) \
+ static int PREFIX##_hid_write_backend(hid_device *device, const unsigned char *data, size_t length) \
+ { \
+ return PREFIX##_hid_write((DEVICE_TYPE *)device, data, length); \
+ } \
+ static int PREFIX##_hid_read_timeout_backend(hid_device *device, unsigned char *data, size_t length, int milliseconds) \
+ { \
+ return PREFIX##_hid_read_timeout((DEVICE_TYPE *)device, data, length, milliseconds); \
+ } \
+ static int PREFIX##_hid_read_backend(hid_device *device, unsigned char *data, size_t length) \
+ { \
+ return PREFIX##_hid_read((DEVICE_TYPE *)device, data, length); \
+ } \
+ static int PREFIX##_hid_set_nonblocking_backend(hid_device *device, int nonblock) \
+ { \
+ return PREFIX##_hid_set_nonblocking((DEVICE_TYPE *)device, nonblock); \
+ } \
+ static int PREFIX##_hid_send_feature_report_backend(hid_device *device, const unsigned char *data, size_t length) \
+ { \
+ return PREFIX##_hid_send_feature_report((DEVICE_TYPE *)device, data, length); \
+ } \
+ static int PREFIX##_hid_get_feature_report_backend(hid_device *device, unsigned char *data, size_t length) \
+ { \
+ return PREFIX##_hid_get_feature_report((DEVICE_TYPE *)device, data, length); \
+ } \
+ static int PREFIX##_hid_get_input_report_backend(hid_device *device, unsigned char *data, size_t length) \
+ { \
+ return PREFIX##_hid_get_input_report((DEVICE_TYPE *)device, data, length); \
+ } \
+ static void PREFIX##_hid_close_backend(hid_device *device) \
+ { \
+ PREFIX##_hid_close((DEVICE_TYPE *)device); \
+ } \
+ static int PREFIX##_hid_get_manufacturer_string_backend(hid_device *device, wchar_t *string, size_t maxlen) \
+ { \
+ return PREFIX##_hid_get_manufacturer_string((DEVICE_TYPE *)device, string, maxlen); \
+ } \
+ static int PREFIX##_hid_get_product_string_backend(hid_device *device, wchar_t *string, size_t maxlen) \
+ { \
+ return PREFIX##_hid_get_product_string((DEVICE_TYPE *)device, string, maxlen); \
+ } \
+ static int PREFIX##_hid_get_serial_number_string_backend(hid_device *device, wchar_t *string, size_t maxlen) \
+ { \
+ return PREFIX##_hid_get_serial_number_string((DEVICE_TYPE *)device, string, maxlen); \
+ } \
+ static int PREFIX##_hid_get_indexed_string_backend(hid_device *device, int string_index, wchar_t *string, size_t maxlen) \
+ { \
+ return PREFIX##_hid_get_indexed_string((DEVICE_TYPE *)device, string_index, string, maxlen); \
+ } \
+ static struct hid_device_info *PREFIX##_hid_get_device_info_backend(hid_device *device) \
+ { \
+ return PREFIX##_hid_get_device_info((DEVICE_TYPE *)device); \
+ } \
+ static int PREFIX##_hid_get_report_descriptor_backend(hid_device *device, unsigned char *buf, size_t buf_size) \
+ { \
+ return PREFIX##_hid_get_report_descriptor((DEVICE_TYPE *)device, buf, buf_size); \
+ } \
+ static const wchar_t *PREFIX##_hid_error_backend(hid_device *device) \
+ { \
+ return PREFIX##_hid_error((DEVICE_TYPE *)device); \
+ }
+
#ifdef HAVE_PLATFORM_BACKEND
+HIDAPI_BACKEND_WRAPPERS(PLATFORM, PLATFORM_hid_device)
+
static const struct hidapi_backend PLATFORM_Backend = {
- (void *)PLATFORM_hid_write,
- (void *)PLATFORM_hid_read_timeout,
- (void *)PLATFORM_hid_read,
- (void *)PLATFORM_hid_set_nonblocking,
- (void *)PLATFORM_hid_send_feature_report,
- (void *)PLATFORM_hid_get_feature_report,
- (void *)PLATFORM_hid_get_input_report,
- (void *)PLATFORM_hid_close,
- (void *)PLATFORM_hid_get_manufacturer_string,
- (void *)PLATFORM_hid_get_product_string,
- (void *)PLATFORM_hid_get_serial_number_string,
- (void *)PLATFORM_hid_get_indexed_string,
- (void *)PLATFORM_hid_get_device_info,
- (void *)PLATFORM_hid_get_report_descriptor,
- (void *)PLATFORM_hid_error
+ PLATFORM_hid_write_backend,
+ PLATFORM_hid_read_timeout_backend,
+ PLATFORM_hid_read_backend,
+ PLATFORM_hid_set_nonblocking_backend,
+ PLATFORM_hid_send_feature_report_backend,
+ PLATFORM_hid_get_feature_report_backend,
+ PLATFORM_hid_get_input_report_backend,
+ PLATFORM_hid_close_backend,
+ PLATFORM_hid_get_manufacturer_string_backend,
+ PLATFORM_hid_get_product_string_backend,
+ PLATFORM_hid_get_serial_number_string_backend,
+ PLATFORM_hid_get_indexed_string_backend,
+ PLATFORM_hid_get_device_info_backend,
+ PLATFORM_hid_get_report_descriptor_backend,
+ PLATFORM_hid_error_backend
};
#endif // HAVE_PLATFORM_BACKEND
#ifdef HAVE_DRIVER_BACKEND
+HIDAPI_BACKEND_WRAPPERS(DRIVER, DRIVER_hid_device)
+
static const struct hidapi_backend DRIVER_Backend = {
- (void *)DRIVER_hid_write,
- (void *)DRIVER_hid_read_timeout,
- (void *)DRIVER_hid_read,
- (void *)DRIVER_hid_set_nonblocking,
- (void *)DRIVER_hid_send_feature_report,
- (void *)DRIVER_hid_get_feature_report,
- (void *)DRIVER_hid_get_input_report,
- (void *)DRIVER_hid_close,
- (void *)DRIVER_hid_get_manufacturer_string,
- (void *)DRIVER_hid_get_product_string,
- (void *)DRIVER_hid_get_serial_number_string,
- (void *)DRIVER_hid_get_indexed_string,
- (void *)DRIVER_hid_get_device_info,
- (void *)DRIVER_hid_get_report_descriptor,
- (void *)DRIVER_hid_error
+ DRIVER_hid_write_backend,
+ DRIVER_hid_read_timeout_backend,
+ DRIVER_hid_read_backend,
+ DRIVER_hid_set_nonblocking_backend,
+ DRIVER_hid_send_feature_report_backend,
+ DRIVER_hid_get_feature_report_backend,
+ DRIVER_hid_get_input_report_backend,
+ DRIVER_hid_close_backend,
+ DRIVER_hid_get_manufacturer_string_backend,
+ DRIVER_hid_get_product_string_backend,
+ DRIVER_hid_get_serial_number_string_backend,
+ DRIVER_hid_get_indexed_string_backend,
+ DRIVER_hid_get_device_info_backend,
+ DRIVER_hid_get_report_descriptor_backend,
+ DRIVER_hid_error_backend
};
#endif // HAVE_DRIVER_BACKEND
#ifdef HAVE_LIBUSB
+HIDAPI_BACKEND_WRAPPERS(LIBUSB, LIBUSB_hid_device)
+
static const struct hidapi_backend LIBUSB_Backend = {
- (void *)LIBUSB_hid_write,
- (void *)LIBUSB_hid_read_timeout,
- (void *)LIBUSB_hid_read,
- (void *)LIBUSB_hid_set_nonblocking,
- (void *)LIBUSB_hid_send_feature_report,
- (void *)LIBUSB_hid_get_feature_report,
- (void *)LIBUSB_hid_get_input_report,
- (void *)LIBUSB_hid_close,
- (void *)LIBUSB_hid_get_manufacturer_string,
- (void *)LIBUSB_hid_get_product_string,
- (void *)LIBUSB_hid_get_serial_number_string,
- (void *)LIBUSB_hid_get_indexed_string,
- (void *)LIBUSB_hid_get_device_info,
- (void *)LIBUSB_hid_get_report_descriptor,
- (void *)LIBUSB_hid_error
+ LIBUSB_hid_write_backend,
+ LIBUSB_hid_read_timeout_backend,
+ LIBUSB_hid_read_backend,
+ LIBUSB_hid_set_nonblocking_backend,
+ LIBUSB_hid_send_feature_report_backend,
+ LIBUSB_hid_get_feature_report_backend,
+ LIBUSB_hid_get_input_report_backend,
+ LIBUSB_hid_close_backend,
+ LIBUSB_hid_get_manufacturer_string_backend,
+ LIBUSB_hid_get_product_string_backend,
+ LIBUSB_hid_get_serial_number_string_backend,
+ LIBUSB_hid_get_indexed_string_backend,
+ LIBUSB_hid_get_device_info_backend,
+ LIBUSB_hid_get_report_descriptor_backend,
+ LIBUSB_hid_error_backend
};
#endif // HAVE_LIBUSB
+#undef HIDAPI_BACKEND_WRAPPERS
+
struct SDL_hid_device
{
void *device;