summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2025-06-15 15:44:31 -0500
committerGitHub <noreply@github.com>2025-06-15 15:44:31 -0500
commit3a94289ad6e27011fe0ca3ab0fb0fee771fb9fa8 (patch)
tree3a9803a91ed2408bdd041bc989561dc61bcdf57f /Source/Core
parent2fb66e97087119715ada71c015f63c2decc97b2d (diff)
parentd93245cc7a2aaa232a57161cdde426a540f0d810 (diff)
Merge pull request #13744 from JoshuaVandaele/windows-specific-getdevicename
Host: Implement a Windows-only implementation of `GetDeviceNameFromVIDPID`
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/CommonFuncs.cpp24
-rw-r--r--Source/Core/Common/CommonFuncs.h10
-rw-r--r--Source/Core/Core/HW/WiimoteReal/IOWin.cpp26
-rw-r--r--Source/Core/Core/IOS/USB/Host.cpp57
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 <windows.h>
+#include <SetupAPI.h>
#define strerror_r(err, buf, len) strerror_s(buf, len, err)
@@ -91,5 +92,28 @@ std::optional<std::wstring> 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<TCHAR> unicode_buffer(required_size / sizeof(TCHAR));
+
+ result = SetupDiGetDeviceProperty(
+ device_info, device_data, requested_property, &device_property_type,
+ reinterpret_cast<PBYTE>(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 <optional>
#include <string>
+#ifdef _WIN32
+#include <SetupAPI.h>
+#include <cfgmgr32.h>
+#include <devpropdef.h>
+#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<std::wstring> 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<BYTE> 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 <string>
#include <utility>
+#include <fmt/format.h>
+#include <fmt/xchar.h>
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
#ifdef __LIBUSB__
#include <libusb.h>
#endif
+#ifdef _WIN32
+#include <SetupAPI.h>
+#include <cfgmgr32.h>
+#include <devpkey.h>
-#ifdef HAVE_LIBUDEV
-#include <libudev.h>
+#include "Common/CommonFuncs.h"
#endif
#include "Common/ChunkFile.h"
@@ -56,7 +64,50 @@ std::optional<IPCReply> 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())