From d93245cc7a2aaa232a57161cdde426a540f0d810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Fri, 13 Jun 2025 14:21:39 +0200 Subject: [PATCH] Host: Implement a Windows-only implementation of `GetDeviceNameFromVIDPID` --- Source/Core/Common/CommonFuncs.cpp | 24 ++++++++++ Source/Core/Common/CommonFuncs.h | 10 ++++ Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 26 +---------- Source/Core/Core/IOS/USB/Host.cpp | 57 +++++++++++++++++++++-- 4 files changed, 90 insertions(+), 27 deletions(-) diff --git a/Source/Core/Common/CommonFuncs.cpp b/Source/Core/Common/CommonFuncs.cpp index aff87a9258..f59939bf6b 100644 --- a/Source/Core/Common/CommonFuncs.cpp +++ b/Source/Core/Common/CommonFuncs.cpp @@ -10,6 +10,7 @@ #ifdef _WIN32 #include +#include #define strerror_r(err, buf, len) strerror_s(buf, len, err) @@ -91,5 +92,28 @@ std::optional GetModuleName(void* hInstance) name.resize(size); return name; } + +std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DATA device_data, + const DEVPROPKEY* requested_property) +{ + DWORD required_size = 0; + DEVPROPTYPE device_property_type; + BOOL result; + + result = SetupDiGetDeviceProperty(device_info, device_data, requested_property, + &device_property_type, nullptr, 0, &required_size, 0); + if (!result && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return std::wstring(); + + std::vector unicode_buffer(required_size / sizeof(TCHAR)); + + result = SetupDiGetDeviceProperty( + device_info, device_data, requested_property, &device_property_type, + reinterpret_cast(unicode_buffer.data()), required_size, nullptr, 0); + if (!result) + return std::wstring(); + + return std::wstring(unicode_buffer.data()); +} #endif } // namespace Common diff --git a/Source/Core/Common/CommonFuncs.h b/Source/Core/Common/CommonFuncs.h index c774cc64aa..8e09d0747b 100644 --- a/Source/Core/Common/CommonFuncs.h +++ b/Source/Core/Common/CommonFuncs.h @@ -5,6 +5,12 @@ #include #include +#ifdef _WIN32 +#include +#include +#include +#endif + #include "Common/CommonTypes.h" #ifndef _WIN32 @@ -58,5 +64,9 @@ std::string GetWin32ErrorString(unsigned long error_code); // Obtains a full path to the specified module. std::optional GetModuleName(void* hInstance); + +// Obtains a device property and returns it as a wide string. +std::wstring GetDeviceProperty(const HANDLE& device_info, const PSP_DEVINFO_DATA device_data, + const DEVPROPKEY* requested_property); #endif } // namespace Common diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index bf7a87acac..da4926524f 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -210,28 +210,6 @@ bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); namespace { -std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DATA device_data, - const DEVPROPKEY* requested_property) -{ - DWORD required_size = 0; - DEVPROPTYPE device_property_type; - - SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type, - nullptr, 0, &required_size, 0); - - std::vector unicode_buffer(required_size, 0); - - BOOL result = - SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type, - unicode_buffer.data(), required_size, nullptr, 0); - if (!result) - { - return std::wstring(); - } - - return std::wstring((PWCHAR)unicode_buffer.data()); -} - int IOWritePerSetOutputReport(HANDLE& dev_handle, const u8* buf, size_t len, DWORD* written) { const BOOLEAN result = @@ -403,8 +381,8 @@ bool CheckForToshibaStack(const DEVINST& hid_interface_device_instance) if (GetParentDevice(hid_interface_device_instance, &parent_device_info, &parent_device_data)) { - std::wstring class_driver_provider = - GetDeviceProperty(parent_device_info, &parent_device_data, &DEVPKEY_Device_DriverProvider); + std::wstring class_driver_provider = Common::GetDeviceProperty( + parent_device_info, &parent_device_data, &DEVPKEY_Device_DriverProvider); SetupDiDestroyDeviceInfoList(parent_device_info); diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index c46e356209..5182b1642c 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -11,12 +11,20 @@ #include #include +#include +#include +#ifdef HAVE_LIBUDEV +#include +#endif #ifdef __LIBUSB__ #include #endif +#ifdef _WIN32 +#include +#include +#include -#ifdef HAVE_LIBUDEV -#include +#include "Common/CommonFuncs.h" #endif #include "Common/ChunkFile.h" @@ -56,7 +64,50 @@ std::optional USBHost::Open(const OpenRequest& request) std::string USBHost::GetDeviceNameFromVIDPID(u16 vid, u16 pid) { std::string device_name; -#ifdef __LIBUSB__ +#ifdef _WIN32 + const std::wstring filter = fmt::format(L"VID_{:04X}&PID_{:04X}", vid, pid); + + HDEVINFO dev_info = + SetupDiGetClassDevs(nullptr, nullptr, nullptr, DIGCF_PRESENT | DIGCF_ALLCLASSES); + if (dev_info == INVALID_HANDLE_VALUE) + return device_name; + + SP_DEVINFO_DATA dev_info_data; + dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + + for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); ++i) + { + TCHAR instance_id[MAX_DEVICE_ID_LEN]; + if (CM_Get_Device_ID(dev_info_data.DevInst, instance_id, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS) + continue; + + const std::wstring_view id_wstr(instance_id); + if (id_wstr.find(filter) == std::wstring::npos) + continue; + + std::wstring property_value = + Common::GetDeviceProperty(dev_info, &dev_info_data, &DEVPKEY_Device_FriendlyName); + if (property_value.empty()) + { + property_value = + Common::GetDeviceProperty(dev_info, &dev_info_data, &DEVPKEY_Device_DeviceDesc); + } + + device_name = WStringToUTF8(property_value); + break; + } + + SetupDiDestroyDeviceInfoList(dev_info); + if (!device_name.empty()) + return device_name; +#endif + // libusb can cause BSODs with certain bad OEM drivers on Windows when opening a device. + // All offending drivers are known to depend on the BthUsb.sys driver, which is a Miniport Driver + // for Bluetooth. + // Known offenders: + // - btfilter.sys from Qualcomm Atheros Communications + // - ibtusb.sys from Intel Corporation +#if defined(__LIBUSB__) && !defined(_WIN32) LibusbUtils::Context context; if (!context.IsValid())