Move libusb support into a shared location

This commit is contained in:
Sam Lantinga
2025-08-27 14:35:17 -07:00
parent cdae0d10d1
commit 09ca7e8f64
8 changed files with 275 additions and 182 deletions

View File

@@ -766,6 +766,7 @@
<ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" /> <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
<ClCompile Include="..\..\src\locale\SDL_locale.c" /> <ClCompile Include="..\..\src\locale\SDL_locale.c" />
<ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" /> <ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" />
<ClCompile Include="..\..\src\misc\SDL_libusb.c" />
<ClCompile Include="..\..\src\misc\SDL_url.c" /> <ClCompile Include="..\..\src\misc\SDL_url.c" />
<ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" /> <ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" />
<ClCompile Include="..\..\src\power\SDL_power.c" /> <ClCompile Include="..\..\src\power\SDL_power.c" />

View File

@@ -99,6 +99,7 @@
<ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" /> <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
<ClCompile Include="..\..\src\locale\SDL_locale.c" /> <ClCompile Include="..\..\src\locale\SDL_locale.c" />
<ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" /> <ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" />
<ClCompile Include="..\..\src\misc\SDL_libusb.c" />
<ClCompile Include="..\..\src\misc\SDL_url.c" /> <ClCompile Include="..\..\src\misc\SDL_url.c" />
<ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" /> <ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" />
<ClCompile Include="..\..\src\power\SDL_power.c" /> <ClCompile Include="..\..\src\power\SDL_power.c" />

View File

@@ -638,6 +638,7 @@
<ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" /> <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c" />
<ClCompile Include="..\..\src\locale\SDL_locale.c" /> <ClCompile Include="..\..\src\locale\SDL_locale.c" />
<ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" /> <ClCompile Include="..\..\src\locale\windows\SDL_syslocale.c" />
<ClCompile Include="..\..\src\misc\SDL_libusb.c" />
<ClCompile Include="..\..\src\misc\SDL_url.c" /> <ClCompile Include="..\..\src\misc\SDL_url.c" />
<ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" /> <ClCompile Include="..\..\src\misc\windows\SDL_sysurl.c" />
<ClCompile Include="..\..\src\power\SDL_power.c" /> <ClCompile Include="..\..\src\power\SDL_power.c" />

View File

@@ -1137,6 +1137,9 @@
<ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c"> <ClCompile Include="..\..\src\loadso\windows\SDL_sysloadso.c">
<Filter>loadso\windows</Filter> <Filter>loadso\windows</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\misc\SDL_libusb.c">
<Filter>misc</Filter>
</ClCompile>
<ClCompile Include="..\..\src\misc\SDL_url.c"> <ClCompile Include="..\..\src\misc\SDL_url.c">
<Filter>misc</Filter> <Filter>misc</Filter>
</ClCompile> </ClCompile>

View File

@@ -522,6 +522,8 @@
F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; }; F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; };
F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */; }; F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */; };
F3D8BDFD2D6D2C7000B22FA1 /* SDL_eventwatch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */; }; F3D8BDFD2D6D2C7000B22FA1 /* SDL_eventwatch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */; };
F3DC38C92E5FC60300CD73DE /* SDL_libusb.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */; };
F3DC38CA2E5FC60300CD73DE /* SDL_libusb.c in Sources */ = {isa = PBXBuildFile; fileRef = F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */; };
F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; }; F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; };
F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; }; F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; };
F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; }; F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; };
@@ -1101,6 +1103,8 @@
F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = "<group>"; }; F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = "<group>"; };
F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_eventwatch.c; sourceTree = "<group>"; }; F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_eventwatch.c; sourceTree = "<group>"; };
F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_eventwatch_c.h; sourceTree = "<group>"; }; F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_eventwatch_c.h; sourceTree = "<group>"; };
F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_libusb.h; sourceTree = "<group>"; };
F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_libusb.c; sourceTree = "<group>"; };
F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = "<group>"; }; F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = "<group>"; };
F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = "<group>"; }; F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = "<group>"; };
F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = "<group>"; }; F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = "<group>"; };
@@ -1414,6 +1418,8 @@
children = ( children = (
F3ADAB8C2576F08500A6B1D9 /* ios */, F3ADAB8C2576F08500A6B1D9 /* ios */,
5616CA48252BB285005D5928 /* macos */, 5616CA48252BB285005D5928 /* macos */,
F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */,
F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */,
5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */, 5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */,
5616CA49252BB2A5005D5928 /* SDL_url.c */, 5616CA49252BB2A5005D5928 /* SDL_url.c */,
); );
@@ -2750,6 +2756,7 @@
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */, F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */,
F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */, F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */,
F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */, F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */,
F3DC38C92E5FC60300CD73DE /* SDL_libusb.h in Headers */,
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */, F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */,
F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */, F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */,
F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */, F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */,
@@ -3101,6 +3108,7 @@
0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */, 0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */,
0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */, 0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */,
000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */, 000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */,
F3DC38CA2E5FC60300CD73DE /* SDL_libusb.c in Sources */,
0000140640E77F73F1DF0000 /* SDL_dialog_utils.c in Sources */, 0000140640E77F73F1DF0000 /* SDL_dialog_utils.c in Sources */,
0000D5B526B85DE7AB1C0000 /* SDL_cocoapen.m in Sources */, 0000D5B526B85DE7AB1C0000 /* SDL_cocoapen.m in Sources */,
6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */, 6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */,

View File

@@ -698,105 +698,40 @@ typedef struct DRIVER_hid_device_ DRIVER_hid_device;
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
// libusb HIDAPI Implementation // libusb HIDAPI Implementation
// Include this now, for our dynamically-loaded libusb context #include "../misc/SDL_libusb.h"
#include <libusb.h>
static struct static SDL_LibUSBContext *libusb_ctx;
{
SDL_SharedObject *libhandle;
/* *INDENT-OFF* */ // clang-format off #define libusb_init libusb_ctx->init
int (LIBUSB_CALL *init)(libusb_context **ctx); #define libusb_exit libusb_ctx->exit
void (LIBUSB_CALL *exit)(libusb_context *ctx); #define libusb_get_device_list libusb_ctx->get_device_list
ssize_t (LIBUSB_CALL *get_device_list)(libusb_context *ctx, libusb_device ***list); #define libusb_free_device_list libusb_ctx->free_device_list
void (LIBUSB_CALL *free_device_list)(libusb_device **list, int unref_devices); #define libusb_get_device_descriptor libusb_ctx->get_device_descriptor
int (LIBUSB_CALL *get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc); #define libusb_get_active_config_descriptor libusb_ctx->get_active_config_descriptor
int (LIBUSB_CALL *get_active_config_descriptor)(libusb_device *dev, struct libusb_config_descriptor **config); #define libusb_get_config_descriptor libusb_ctx->get_config_descriptor
int (LIBUSB_CALL *get_config_descriptor)( #define libusb_free_config_descriptor libusb_ctx->free_config_descriptor
libusb_device *dev, #define libusb_get_bus_number libusb_ctx->get_bus_number
uint8_t config_index, #define libusb_get_port_numbers libusb_ctx->get_port_numbers
struct libusb_config_descriptor **config #define libusb_get_device_address libusb_ctx->get_device_address
); #define libusb_open libusb_ctx->open
void (LIBUSB_CALL *free_config_descriptor)(struct libusb_config_descriptor *config); #define libusb_close libusb_ctx->close
uint8_t (LIBUSB_CALL *get_bus_number)(libusb_device *dev); #define libusb_get_device libusb_ctx->get_device
int (LIBUSB_CALL *get_port_numbers)(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len); #define libusb_claim_interface libusb_ctx->claim_interface
uint8_t (LIBUSB_CALL *get_device_address)(libusb_device *dev); #define libusb_release_interface libusb_ctx->release_interface
int (LIBUSB_CALL *open)(libusb_device *dev, libusb_device_handle **dev_handle); #define libusb_kernel_driver_active libusb_ctx->kernel_driver_active
void (LIBUSB_CALL *close)(libusb_device_handle *dev_handle); #define libusb_detach_kernel_driver libusb_ctx->detach_kernel_driver
libusb_device *(LIBUSB_CALL *get_device)(libusb_device_handle *dev_handle); #define libusb_attach_kernel_driver libusb_ctx->attach_kernel_driver
int (LIBUSB_CALL *claim_interface)(libusb_device_handle *dev_handle, int interface_number); #define libusb_set_interface_alt_setting libusb_ctx->set_interface_alt_setting
int (LIBUSB_CALL *release_interface)(libusb_device_handle *dev_handle, int interface_number); #define libusb_alloc_transfer libusb_ctx->alloc_transfer
int (LIBUSB_CALL *kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number); #define libusb_submit_transfer libusb_ctx->submit_transfer
int (LIBUSB_CALL *detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number); #define libusb_cancel_transfer libusb_ctx->cancel_transfer
int (LIBUSB_CALL *attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number); #define libusb_free_transfer libusb_ctx->free_transfer
int (LIBUSB_CALL *set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting); #define libusb_control_transfer libusb_ctx->control_transfer
struct libusb_transfer * (LIBUSB_CALL *alloc_transfer)(int iso_packets); #define libusb_interrupt_transfer libusb_ctx->interrupt_transfer
int (LIBUSB_CALL *submit_transfer)(struct libusb_transfer *transfer); #define libusb_bulk_transfer libusb_ctx->bulk_transfer
int (LIBUSB_CALL *cancel_transfer)(struct libusb_transfer *transfer); #define libusb_handle_events libusb_ctx->handle_events
void (LIBUSB_CALL *free_transfer)(struct libusb_transfer *transfer); #define libusb_handle_events_completed libusb_ctx->handle_events_completed
int (LIBUSB_CALL *control_transfer)( #define libusb_error_name libusb_ctx->error_name
libusb_device_handle *dev_handle,
uint8_t request_type,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char *data,
uint16_t wLength,
unsigned int timeout
);
int (LIBUSB_CALL *interrupt_transfer)(
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *actual_length,
unsigned int timeout
);
int (LIBUSB_CALL *bulk_transfer)(
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *transferred,
unsigned int timeout
);
int (LIBUSB_CALL *handle_events)(libusb_context *ctx);
int (LIBUSB_CALL *handle_events_completed)(libusb_context *ctx, int *completed);
const char * (LIBUSB_CALL *error_name)(int errcode);
/* *INDENT-ON* */ // clang-format on
} libusb_ctx;
#define libusb_init libusb_ctx.init
#define libusb_exit libusb_ctx.exit
#define libusb_get_device_list libusb_ctx.get_device_list
#define libusb_free_device_list libusb_ctx.free_device_list
#define libusb_get_device_descriptor libusb_ctx.get_device_descriptor
#define libusb_get_active_config_descriptor libusb_ctx.get_active_config_descriptor
#define libusb_get_config_descriptor libusb_ctx.get_config_descriptor
#define libusb_free_config_descriptor libusb_ctx.free_config_descriptor
#define libusb_get_bus_number libusb_ctx.get_bus_number
#define libusb_get_port_numbers libusb_ctx.get_port_numbers
#define libusb_get_device_address libusb_ctx.get_device_address
#define libusb_open libusb_ctx.open
#define libusb_close libusb_ctx.close
#define libusb_get_device libusb_ctx.get_device
#define libusb_claim_interface libusb_ctx.claim_interface
#define libusb_release_interface libusb_ctx.release_interface
#define libusb_kernel_driver_active libusb_ctx.kernel_driver_active
#define libusb_detach_kernel_driver libusb_ctx.detach_kernel_driver
#define libusb_attach_kernel_driver libusb_ctx.attach_kernel_driver
#define libusb_set_interface_alt_setting libusb_ctx.set_interface_alt_setting
#define libusb_alloc_transfer libusb_ctx.alloc_transfer
#define libusb_submit_transfer libusb_ctx.submit_transfer
#define libusb_cancel_transfer libusb_ctx.cancel_transfer
#define libusb_free_transfer libusb_ctx.free_transfer
#define libusb_control_transfer libusb_ctx.control_transfer
#define libusb_interrupt_transfer libusb_ctx.interrupt_transfer
#define libusb_bulk_transfer libusb_ctx.bulk_transfer
#define libusb_handle_events libusb_ctx.handle_events
#define libusb_handle_events_completed libusb_ctx.handle_events_completed
#define libusb_error_name libusb_ctx.error_name
struct LIBUSB_hid_device_; struct LIBUSB_hid_device_;
typedef struct LIBUSB_hid_device_ LIBUSB_hid_device; typedef struct LIBUSB_hid_device_ LIBUSB_hid_device;
@@ -1188,73 +1123,17 @@ int SDL_hid_init(void)
if (!SDL_GetHintBoolean(SDL_HINT_HIDAPI_LIBUSB, true)) { if (!SDL_GetHintBoolean(SDL_HINT_HIDAPI_LIBUSB, true)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"libusb disabled with SDL_HINT_HIDAPI_LIBUSB"); "libusb disabled with SDL_HINT_HIDAPI_LIBUSB");
libusb_ctx.libhandle = NULL;
} else { } else {
++attempts; ++attempts;
#ifdef SDL_LIBUSB_DYNAMIC if (!SDL_InitLibUSB(&libusb_ctx)) {
libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC); SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Couldn't load libusb");
#else
libusb_ctx.libhandle = (void *)1;
#endif
if (libusb_ctx.libhandle != NULL) {
bool loaded = true;
#ifdef SDL_LIBUSB_DYNAMIC
#define LOAD_LIBUSB_SYMBOL(type, func) \
if ((libusb_ctx.func = (type)SDL_LoadFunction(libusb_ctx.libhandle, "libusb_" #func)) == NULL) { \
loaded = false; \
}
#else
#define LOAD_LIBUSB_SYMBOL(type, func) \
libusb_ctx.func = libusb_##func;
#endif
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context **), init)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_context *), exit)
LOAD_LIBUSB_SYMBOL(ssize_t (LIBUSB_CALL *)(libusb_context *, libusb_device ***), get_device_list)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_device **, int), free_device_list)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, struct libusb_device_descriptor *), get_device_descriptor)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, struct libusb_config_descriptor **), get_active_config_descriptor)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, uint8_t, struct libusb_config_descriptor **), get_config_descriptor)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(struct libusb_config_descriptor *), free_config_descriptor)
LOAD_LIBUSB_SYMBOL(uint8_t (LIBUSB_CALL *)(libusb_device *), get_bus_number)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len), get_port_numbers)
LOAD_LIBUSB_SYMBOL(uint8_t (LIBUSB_CALL *)(libusb_device *), get_device_address)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, libusb_device_handle **), open)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_device_handle *), close)
LOAD_LIBUSB_SYMBOL(libusb_device * (LIBUSB_CALL *)(libusb_device_handle *dev_handle), get_device)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), claim_interface)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), release_interface)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), kernel_driver_active)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), detach_kernel_driver)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), attach_kernel_driver)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int, int), set_interface_alt_setting)
LOAD_LIBUSB_SYMBOL(struct libusb_transfer * (LIBUSB_CALL *)(int), alloc_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(struct libusb_transfer *), submit_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(struct libusb_transfer *), cancel_transfer)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(struct libusb_transfer *), free_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, uint8_t, uint8_t, uint16_t, uint16_t, unsigned char *, uint16_t, unsigned int), control_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, unsigned char, unsigned char *, int, int *, unsigned int), interrupt_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, unsigned char, unsigned char *, int, int *, unsigned int), bulk_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context *), handle_events)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context *, int *), handle_events_completed)
LOAD_LIBUSB_SYMBOL(const char * (LIBUSB_CALL *)(int), error_name)
#undef LOAD_LIBUSB_SYMBOL
if (!loaded) {
#ifdef SDL_LIBUSB_DYNAMIC
SDL_UnloadObject(libusb_ctx.libhandle);
#endif
libusb_ctx.libhandle = NULL;
// SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, SDL_LIBUSB_DYNAMIC " found but could not load function");
} else if (LIBUSB_hid_init() < 0) { } else if (LIBUSB_hid_init() < 0) {
#ifdef SDL_LIBUSB_DYNAMIC SDL_QuitLibUSB();
SDL_UnloadObject(libusb_ctx.libhandle); libusb_ctx = NULL;
#endif
libusb_ctx.libhandle = NULL;
} else { } else {
++success; ++success;
} }
} }
}
#endif // HAVE_LIBUSB #endif // HAVE_LIBUSB
#ifdef HAVE_PLATFORM_BACKEND #ifdef HAVE_PLATFORM_BACKEND
@@ -1306,12 +1185,10 @@ int SDL_hid_exit(void)
#endif // HAVE_PLATFORM_BACKEND #endif // HAVE_PLATFORM_BACKEND
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle) { if (libusb_ctx) {
result |= LIBUSB_hid_exit(); result |= LIBUSB_hid_exit();
#ifdef SDL_LIBUSB_DYNAMIC SDL_QuitLibUSB();
SDL_UnloadObject(libusb_ctx.libhandle); libusb_ctx = NULL;
#endif
libusb_ctx.libhandle = NULL;
} }
#endif // HAVE_LIBUSB #endif // HAVE_LIBUSB
@@ -1452,7 +1329,7 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
#endif #endif
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle) { if (libusb_ctx) {
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id); usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
if (use_libusb_whitelist) { if (use_libusb_whitelist) {
@@ -1553,7 +1430,7 @@ SDL_hid_device *SDL_hid_open(unsigned short vendor_id, unsigned short product_id
#endif // HAVE_DRIVER_BACKEND #endif // HAVE_DRIVER_BACKEND
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle != NULL) { if (libusb_ctx) {
pDevice = LIBUSB_hid_open(vendor_id, product_id, serial_number); pDevice = LIBUSB_hid_open(vendor_id, product_id, serial_number);
if (pDevice != NULL) { if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
@@ -1592,7 +1469,7 @@ SDL_hid_device *SDL_hid_open_path(const char *path)
#endif // HAVE_DRIVER_BACKEND #endif // HAVE_DRIVER_BACKEND
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle != NULL) { if (libusb_ctx) {
pDevice = LIBUSB_hid_open_path(path); pDevice = LIBUSB_hid_open_path(path);
if (pDevice != NULL) { if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend); return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
@@ -1733,14 +1610,14 @@ void SDL_EnableGameCubeAdaptors(void)
ssize_t i, num_devs; ssize_t i, num_devs;
int kernel_detached = 0; int kernel_detached = 0;
if (libusb_ctx.libhandle == NULL) { if (!libusb_ctx) {
return; return;
} }
if (libusb_ctx.init(&context) == 0) { if (libusb_ctx->init(&context) == 0) {
num_devs = libusb_ctx.get_device_list(context, &devs); num_devs = libusb_ctx->get_device_list(context, &devs);
for (i = 0; i < num_devs; ++i) { for (i = 0; i < num_devs; ++i) {
if (libusb_ctx.get_device_descriptor(devs[i], &desc) != 0) { if (libusb_ctx->get_device_descriptor(devs[i], &desc) != 0) {
continue; continue;
} }
@@ -1748,31 +1625,31 @@ void SDL_EnableGameCubeAdaptors(void)
continue; continue;
} }
if (libusb_ctx.open(devs[i], &handle) != 0) { if (libusb_ctx->open(devs[i], &handle) != 0) {
continue; continue;
} }
if (libusb_ctx.kernel_driver_active(handle, 0)) { if (libusb_ctx->kernel_driver_active(handle, 0)) {
if (libusb_ctx.detach_kernel_driver(handle, 0) == 0) { if (libusb_ctx->detach_kernel_driver(handle, 0) == 0) {
kernel_detached = 1; kernel_detached = 1;
} }
} }
if (libusb_ctx.claim_interface(handle, 0) == 0) { if (libusb_ctx->claim_interface(handle, 0) == 0) {
libusb_ctx.control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000); libusb_ctx->control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000);
libusb_ctx.release_interface(handle, 0); libusb_ctx->release_interface(handle, 0);
} }
if (kernel_detached) { if (kernel_detached) {
libusb_ctx.attach_kernel_driver(handle, 0); libusb_ctx->attach_kernel_driver(handle, 0);
} }
libusb_ctx.close(handle); libusb_ctx->close(handle);
} }
libusb_ctx.free_device_list(devs, 1); libusb_ctx->free_device_list(devs, 1);
libusb_ctx.exit(context); libusb_ctx->exit(context);
} }
#endif // HAVE_LIBUSB #endif // HAVE_LIBUSB
} }

105
src/misc/SDL_libusb.c Normal file
View File

@@ -0,0 +1,105 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_libusb.h"
#ifdef HAVE_LIBUSB
static SDL_AtomicInt SDL_libusb_refcount;
static bool SDL_libusb_loaded;
static SDL_SharedObject *SDL_libusb_handle;
static SDL_LibUSBContext SDL_libusb_context;
bool SDL_InitLibUSB(SDL_LibUSBContext **ctx)
{
if (SDL_AtomicIncRef(&SDL_libusb_refcount) == 0) {
#ifdef SDL_LIBUSB_DYNAMIC
SDL_libusb_handle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
if (SDL_libusb_handle)
#endif
{
SDL_libusb_loaded = true;
#ifdef SDL_LIBUSB_DYNAMIC
#define LOAD_LIBUSB_SYMBOL(type, func) \
if ((SDL_libusb_context.func = (type)SDL_LoadFunction(SDL_libusb_handle, "libusb_" #func)) == NULL) { \
SDL_libusb_loaded = false; \
}
#else
#define LOAD_LIBUSB_SYMBOL(type, func) \
SDL_libusb_context.func = libusb_##func;
#endif
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context **), init)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_context *), exit)
LOAD_LIBUSB_SYMBOL(ssize_t (LIBUSB_CALL *)(libusb_context *, libusb_device ***), get_device_list)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_device **, int), free_device_list)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, struct libusb_device_descriptor *), get_device_descriptor)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, struct libusb_config_descriptor **), get_active_config_descriptor)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, uint8_t, struct libusb_config_descriptor **), get_config_descriptor)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(struct libusb_config_descriptor *), free_config_descriptor)
LOAD_LIBUSB_SYMBOL(uint8_t (LIBUSB_CALL *)(libusb_device *), get_bus_number)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len), get_port_numbers)
LOAD_LIBUSB_SYMBOL(uint8_t (LIBUSB_CALL *)(libusb_device *), get_device_address)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device *, libusb_device_handle **), open)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(libusb_device_handle *), close)
LOAD_LIBUSB_SYMBOL(libusb_device * (LIBUSB_CALL *)(libusb_device_handle *dev_handle), get_device)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), claim_interface)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), release_interface)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), kernel_driver_active)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), detach_kernel_driver)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int), attach_kernel_driver)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, int, int), set_interface_alt_setting)
LOAD_LIBUSB_SYMBOL(struct libusb_transfer * (LIBUSB_CALL *)(int), alloc_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(struct libusb_transfer *), submit_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(struct libusb_transfer *), cancel_transfer)
LOAD_LIBUSB_SYMBOL(void (LIBUSB_CALL *)(struct libusb_transfer *), free_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, uint8_t, uint8_t, uint16_t, uint16_t, unsigned char *, uint16_t, unsigned int), control_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, unsigned char, unsigned char *, int, int *, unsigned int), interrupt_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_device_handle *, unsigned char, unsigned char *, int, int *, unsigned int), bulk_transfer)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context *), handle_events)
LOAD_LIBUSB_SYMBOL(int (LIBUSB_CALL *)(libusb_context *, int *), handle_events_completed)
LOAD_LIBUSB_SYMBOL(const char * (LIBUSB_CALL *)(int), error_name)
#undef LOAD_LIBUSB_SYMBOL
}
}
if (SDL_libusb_loaded) {
*ctx = &SDL_libusb_context;
return true;
} else {
SDL_QuitLibUSB();
*ctx = NULL;
return false;
}
}
void SDL_QuitLibUSB(void)
{
if (SDL_AtomicDecRef(&SDL_libusb_refcount)) {
if (SDL_libusb_handle) {
SDL_UnloadObject(SDL_libusb_handle);
SDL_libusb_handle = NULL;
}
SDL_libusb_loaded = false;
}
}
#endif // HAVE_LIBUSB

97
src/misc/SDL_libusb.h Normal file
View File

@@ -0,0 +1,97 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef HAVE_LIBUSB
// libusb HIDAPI Implementation
// Include this now, for our dynamically-loaded libusb context
#include <libusb.h>
typedef struct SDL_LibUSBContext
{
/* *INDENT-OFF* */ // clang-format off
int (LIBUSB_CALL *init)(libusb_context **ctx);
void (LIBUSB_CALL *exit)(libusb_context *ctx);
ssize_t (LIBUSB_CALL *get_device_list)(libusb_context *ctx, libusb_device ***list);
void (LIBUSB_CALL *free_device_list)(libusb_device **list, int unref_devices);
int (LIBUSB_CALL *get_device_descriptor)(libusb_device *dev, struct libusb_device_descriptor *desc);
int (LIBUSB_CALL *get_active_config_descriptor)(libusb_device *dev, struct libusb_config_descriptor **config);
int (LIBUSB_CALL *get_config_descriptor)(
libusb_device *dev,
uint8_t config_index,
struct libusb_config_descriptor **config
);
void (LIBUSB_CALL *free_config_descriptor)(struct libusb_config_descriptor *config);
uint8_t (LIBUSB_CALL *get_bus_number)(libusb_device *dev);
int (LIBUSB_CALL *get_port_numbers)(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len);
uint8_t (LIBUSB_CALL *get_device_address)(libusb_device *dev);
int (LIBUSB_CALL *open)(libusb_device *dev, libusb_device_handle **dev_handle);
void (LIBUSB_CALL *close)(libusb_device_handle *dev_handle);
libusb_device *(LIBUSB_CALL *get_device)(libusb_device_handle *dev_handle);
int (LIBUSB_CALL *claim_interface)(libusb_device_handle *dev_handle, int interface_number);
int (LIBUSB_CALL *release_interface)(libusb_device_handle *dev_handle, int interface_number);
int (LIBUSB_CALL *kernel_driver_active)(libusb_device_handle *dev_handle, int interface_number);
int (LIBUSB_CALL *detach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
int (LIBUSB_CALL *attach_kernel_driver)(libusb_device_handle *dev_handle, int interface_number);
int (LIBUSB_CALL *set_interface_alt_setting)(libusb_device_handle *dev, int interface_number, int alternate_setting);
struct libusb_transfer * (LIBUSB_CALL *alloc_transfer)(int iso_packets);
int (LIBUSB_CALL *submit_transfer)(struct libusb_transfer *transfer);
int (LIBUSB_CALL *cancel_transfer)(struct libusb_transfer *transfer);
void (LIBUSB_CALL *free_transfer)(struct libusb_transfer *transfer);
int (LIBUSB_CALL *control_transfer)(
libusb_device_handle *dev_handle,
uint8_t request_type,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char *data,
uint16_t wLength,
unsigned int timeout
);
int (LIBUSB_CALL *interrupt_transfer)(
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *actual_length,
unsigned int timeout
);
int (LIBUSB_CALL *bulk_transfer)(
libusb_device_handle *dev_handle,
unsigned char endpoint,
unsigned char *data,
int length,
int *transferred,
unsigned int timeout
);
int (LIBUSB_CALL *handle_events)(libusb_context *ctx);
int (LIBUSB_CALL *handle_events_completed)(libusb_context *ctx, int *completed);
const char * (LIBUSB_CALL *error_name)(int errcode);
/* *INDENT-ON* */ // clang-format on
} SDL_LibUSBContext;
extern bool SDL_InitLibUSB(SDL_LibUSBContext **ctx);
extern void SDL_QuitLibUSB(void);
#endif // HAVE_LIBUSB