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\locale\SDL_locale.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\windows\SDL_sysurl.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\locale\SDL_locale.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\windows\SDL_sysurl.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\locale\SDL_locale.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\windows\SDL_sysurl.c" />
<ClCompile Include="..\..\src\power\SDL_power.c" />

View File

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

View File

@@ -522,6 +522,8 @@
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 */; };
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 */; };
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 */; };
@@ -1101,6 +1103,8 @@
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>"; };
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>"; };
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>"; };
@@ -1414,6 +1418,8 @@
children = (
F3ADAB8C2576F08500A6B1D9 /* ios */,
5616CA48252BB285005D5928 /* macos */,
F3DC38C72E5FC60300CD73DE /* SDL_libusb.h */,
F3DC38C82E5FC60300CD73DE /* SDL_libusb.c */,
5616CA4A252BB2A6005D5928 /* SDL_sysurl.h */,
5616CA49252BB2A5005D5928 /* SDL_url.c */,
);
@@ -2750,6 +2756,7 @@
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */,
F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */,
F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */,
F3DC38C92E5FC60300CD73DE /* SDL_libusb.h in Headers */,
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */,
F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */,
F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */,
@@ -3101,6 +3108,7 @@
0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */,
0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */,
000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */,
F3DC38CA2E5FC60300CD73DE /* SDL_libusb.c in Sources */,
0000140640E77F73F1DF0000 /* SDL_dialog_utils.c in Sources */,
0000D5B526B85DE7AB1C0000 /* SDL_cocoapen.m 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
// libusb HIDAPI Implementation
// Include this now, for our dynamically-loaded libusb context
#include <libusb.h>
#include "../misc/SDL_libusb.h"
static struct
{
SDL_SharedObject *libhandle;
static SDL_LibUSBContext *libusb_ctx;
/* *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
} 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
#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_;
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)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"libusb disabled with SDL_HINT_HIDAPI_LIBUSB");
libusb_ctx.libhandle = NULL;
} else {
++attempts;
#ifdef SDL_LIBUSB_DYNAMIC
libusb_ctx.libhandle = SDL_LoadObject(SDL_LIBUSB_DYNAMIC);
#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");
if (!SDL_InitLibUSB(&libusb_ctx)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Couldn't load libusb");
} else if (LIBUSB_hid_init() < 0) {
#ifdef SDL_LIBUSB_DYNAMIC
SDL_UnloadObject(libusb_ctx.libhandle);
#endif
libusb_ctx.libhandle = NULL;
SDL_QuitLibUSB();
libusb_ctx = NULL;
} else {
++success;
}
}
}
#endif // HAVE_LIBUSB
#ifdef HAVE_PLATFORM_BACKEND
@@ -1306,12 +1185,10 @@ int SDL_hid_exit(void)
#endif // HAVE_PLATFORM_BACKEND
#ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle) {
if (libusb_ctx) {
result |= LIBUSB_hid_exit();
#ifdef SDL_LIBUSB_DYNAMIC
SDL_UnloadObject(libusb_ctx.libhandle);
#endif
libusb_ctx.libhandle = NULL;
SDL_QuitLibUSB();
libusb_ctx = NULL;
}
#endif // HAVE_LIBUSB
@@ -1452,7 +1329,7 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
#endif
#ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle) {
if (libusb_ctx) {
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
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
#ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle != NULL) {
if (libusb_ctx) {
pDevice = LIBUSB_hid_open(vendor_id, product_id, serial_number);
if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
@@ -1592,7 +1469,7 @@ SDL_hid_device *SDL_hid_open_path(const char *path)
#endif // HAVE_DRIVER_BACKEND
#ifdef HAVE_LIBUSB
if (libusb_ctx.libhandle != NULL) {
if (libusb_ctx) {
pDevice = LIBUSB_hid_open_path(path);
if (pDevice != NULL) {
return CreateHIDDeviceWrapper(pDevice, &LIBUSB_Backend);
@@ -1733,14 +1610,14 @@ void SDL_EnableGameCubeAdaptors(void)
ssize_t i, num_devs;
int kernel_detached = 0;
if (libusb_ctx.libhandle == NULL) {
if (!libusb_ctx) {
return;
}
if (libusb_ctx.init(&context) == 0) {
num_devs = libusb_ctx.get_device_list(context, &devs);
if (libusb_ctx->init(&context) == 0) {
num_devs = libusb_ctx->get_device_list(context, &devs);
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;
}
@@ -1748,31 +1625,31 @@ void SDL_EnableGameCubeAdaptors(void)
continue;
}
if (libusb_ctx.open(devs[i], &handle) != 0) {
if (libusb_ctx->open(devs[i], &handle) != 0) {
continue;
}
if (libusb_ctx.kernel_driver_active(handle, 0)) {
if (libusb_ctx.detach_kernel_driver(handle, 0) == 0) {
if (libusb_ctx->kernel_driver_active(handle, 0)) {
if (libusb_ctx->detach_kernel_driver(handle, 0) == 0) {
kernel_detached = 1;
}
}
if (libusb_ctx.claim_interface(handle, 0) == 0) {
libusb_ctx.control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000);
libusb_ctx.release_interface(handle, 0);
if (libusb_ctx->claim_interface(handle, 0) == 0) {
libusb_ctx->control_transfer(handle, 0x21, 11, 0x0001, 0, NULL, 0, 1000);
libusb_ctx->release_interface(handle, 0);
}
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
}

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