sys_usbd: enable windows hotplug

This commit is contained in:
Megamouse 2026-05-18 18:50:26 +02:00
parent 84b61e3850
commit 6a2ad0a0aa
5 changed files with 28 additions and 23 deletions

View File

@ -3,6 +3,9 @@
<!-- Common default props for defining properties without macros. Import right before Microsoft.Cpp.Default.props --> <!-- Common default props for defining properties without macros. Import right before Microsoft.Cpp.Default.props -->
<ImportGroup Label="PropertySheets" /> <ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup>
<EnableLibUsbWindowsHotplug>true</EnableLibUsbWindowsHotplug>
</PropertyGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>

View File

@ -2,7 +2,6 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" /> <ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<Optimization>Full</Optimization> <Optimization>Full</Optimization>

View File

@ -46,6 +46,14 @@
#include <libusb.h> #include <libusb.h>
#ifdef _WIN32
#if LIBUSB_WINDOWS_HOTPLUG && LIBUSB_API_VERSION >= 0x0100010C
#define SYS_USBD_HOTPLUG_SUPPORTED 1
#endif
#elif LIBUSB_API_VERSION >= 0x01000102
#define SYS_USBD_HOTPLUG_SUPPORTED 1
#endif
LOG_CHANNEL(sys_usbd); LOG_CHANNEL(sys_usbd);
cfg_buzz g_cfg_buzz; cfg_buzz g_cfg_buzz;
@ -154,6 +162,7 @@ public:
ppu_thread* sq{}; ppu_thread* sq{};
atomic_t<u64> usb_hotplug_timeout = umax; atomic_t<u64> usb_hotplug_timeout = umax;
atomic_t<bool> hotplug_supported = false;
static constexpr auto thread_name = "Usb Manager Thread"sv; static constexpr auto thread_name = "Usb Manager Thread"sv;
@ -217,7 +226,6 @@ private:
{0x12BA, 0x04A1, 0x04A1, "Top Shot Fearmaster", nullptr, nullptr}, {0x12BA, 0x04A1, 0x04A1, "Top Shot Fearmaster", nullptr, nullptr},
{0x12BA, 0x04B0, 0x04B0, "Rapala Fishing Rod", nullptr, nullptr}, {0x12BA, 0x04B0, 0x04B0, "Rapala Fishing Rod", nullptr, nullptr},
// Wheels // Wheels
#ifdef HAVE_SDL3 #ifdef HAVE_SDL3
{0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", &usb_device_logitech_g27::get_num_emu_devices, &usb_device_logitech_g27::make_instance}, {0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", &usb_device_logitech_g27::get_num_emu_devices, &usb_device_logitech_g27::make_instance},
@ -294,13 +302,9 @@ private:
libusb_context* ctx = nullptr; libusb_context* ctx = nullptr;
#ifndef _WIN32 #if SYS_USBD_HOTPLUG_SUPPORTED
#if LIBUSB_API_VERSION >= 0x01000102
libusb_hotplug_callback_handle callback_handle {}; libusb_hotplug_callback_handle callback_handle {};
#endif #endif
#endif
bool hotplug_supported = false;
}; };
void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer) void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer)
@ -313,15 +317,13 @@ void LIBUSB_CALL callback_transfer(struct libusb_transfer* transfer)
usbh.transfer_complete(transfer); usbh.transfer_complete(transfer);
} }
#ifndef _WIN32 #if SYS_USBD_HOTPLUG_SUPPORTED
#if LIBUSB_API_VERSION >= 0x01000102 static int LIBUSB_CALL hotplug_callback(libusb_context* /*ctx*/, libusb_device* /*dev*/, libusb_hotplug_event event, void* /*user_data*/)
static int LIBUSB_CALL hotplug_callback(libusb_context* /*ctx*/, libusb_device * /*dev*/, libusb_hotplug_event event, void * /*user_data*/)
{ {
handle_hotplug_event(event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED); handle_hotplug_event(event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, true);
return 0; return 0;
} }
#endif #endif
#endif
#if LIBUSB_API_VERSION >= 0x0100010A #if LIBUSB_API_VERSION >= 0x0100010A
static void LIBUSB_CALL log_cb(libusb_context* /*ctx*/, enum libusb_log_level level, const char* str) static void LIBUSB_CALL log_cb(libusb_context* /*ctx*/, enum libusb_log_level level, const char* str)
@ -463,9 +465,7 @@ usb_handler_thread::usb_handler_thread()
return; return;
} }
#ifdef _WIN32 #if SYS_USBD_HOTPLUG_SUPPORTED
hotplug_supported = true;
#elif LIBUSB_API_VERSION >= 0x01000102
if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG))
{ {
if (int res = libusb_hotplug_register_callback(ctx, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | if (int res = libusb_hotplug_register_callback(ctx, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
@ -480,6 +480,8 @@ usb_handler_thread::usb_handler_thread()
hotplug_supported = true; hotplug_supported = true;
} }
} }
#elif defined(_WIN32)
hotplug_supported = true;
#endif #endif
for (u32 index = 0; index < MAX_SYS_USBD_TRANSFERS; index++) for (u32 index = 0; index < MAX_SYS_USBD_TRANSFERS; index++)
@ -627,11 +629,9 @@ usb_handler_thread::~usb_handler_thread()
libusb_free_transfer(transfers[index].transfer); libusb_free_transfer(transfers[index].transfer);
} }
#ifndef _WIN32 #if SYS_USBD_HOTPLUG_SUPPORTED
#if LIBUSB_API_VERSION >= 0x01000102
if (ctx && hotplug_supported) if (ctx && hotplug_supported)
libusb_hotplug_deregister_callback(ctx, callback_handle); libusb_hotplug_deregister_callback(ctx, callback_handle);
#endif
#endif #endif
if (ctx) if (ctx)
@ -654,7 +654,7 @@ void usb_handler_thread::operator()()
// every 4 seconds. // every 4 seconds.
// On systems where hotplug is native, we wait a little bit for devices to settle before we start the scan // On systems where hotplug is native, we wait a little bit for devices to settle before we start the scan
perform_scan(); perform_scan();
usb_hotplug_timeout = hotplug_supported ? umax : get_system_time() + 4'000'000ull; usb_hotplug_timeout = hotplug_supported ? umax : (get_system_time() + 4'000'000ull);
} }
// Process asynchronous requests that are pending // Process asynchronous requests that are pending
@ -1106,15 +1106,18 @@ void reconnect_usb(u32 assigned_number)
usbh->reconnect_usb_device(assigned_number); usbh->reconnect_usb_device(assigned_number);
} }
void handle_hotplug_event(bool connected) void handle_hotplug_event(bool connected, bool source_is_libusb)
{ {
if (auto usbh = g_fxo->try_get<named_thread<usb_handler_thread>>()) if (auto usbh = g_fxo->try_get<named_thread<usb_handler_thread>>())
{ {
if (usbh->hotplug_supported && !source_is_libusb) return;
sys_usbd.notice("handle_hotplug_event: connected=%d", connected);
usbh->usb_hotplug_timeout = get_system_time() + (connected ? 1'000'000ull : 0); usbh->usb_hotplug_timeout = get_system_time() + (connected ? 1'000'000ull : 0);
} }
} }
error_code sys_usbd_initialize(ppu_thread& ppu, vm::ptr<u32> handle) error_code sys_usbd_initialize(ppu_thread& ppu, vm::ptr<u32> handle)
{ {
ppu.state += cpu_flag::wait; ppu.state += cpu_flag::wait;

View File

@ -90,4 +90,4 @@ error_code sys_usbd_unregister_extra_ldd(ppu_thread& ppu, u32 handle, vm::cptr<c
void connect_usb_controller(u8 index, input::product_type); void connect_usb_controller(u8 index, input::product_type);
void reconnect_usb(u32 assigned_number); void reconnect_usb(u32 assigned_number);
void handle_hotplug_event(bool connected); void handle_hotplug_event(bool connected, bool source_is_libusb);

View File

@ -1361,7 +1361,7 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co
{ {
if (Emu.IsRunning() || Emu.IsStarting()) if (Emu.IsRunning() || Emu.IsStarting())
{ {
handle_hotplug_event(msg->wParam == DBT_DEVICEARRIVAL); handle_hotplug_event(msg->wParam == DBT_DEVICEARRIVAL, false);
} }
return false; return false;
} }