summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-07-23 20:57:17 -0400
committerGitHub <noreply@github.com>2025-07-23 20:57:17 -0400
commit45ba6ed6b185564099bbb7257c0bdfdb8f2d779f (patch)
tree81b7faa25ea36b94e3194a5eab0b5926766eedc1 /Source/Core
parent10cedc90af0068d2a78a454914c4d7ca4c1cdbdf (diff)
parent4ae195ee60b1167757b4c1e8ef6771e0aa23a96e (diff)
Merge pull request #13770 from JoshuaVandaele/usbutils
USBUtils: Refactor USB device handling
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/CMakeLists.txt2
-rw-r--r--Source/Core/Core/Config/MainSettings.cpp24
-rw-r--r--Source/Core/Core/Config/MainSettings.h5
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp42
-rw-r--r--Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h9
-rw-r--r--Source/Core/Core/IOS/USB/Host.cpp116
-rw-r--r--Source/Core/Core/IOS/USB/Host.h1
-rw-r--r--Source/Core/Core/IOS/USB/USBScanner.cpp6
-rw-r--r--Source/Core/Core/USBUtils.cpp300
-rw-r--r--Source/Core/Core/USBUtils.h40
-rw-r--r--Source/Core/DolphinLib.props4
-rw-r--r--Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp24
-rw-r--r--Source/Core/DolphinQt/Config/WiimoteControllersWidget.h5
-rw-r--r--Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.cpp41
-rw-r--r--Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h6
-rw-r--r--Source/Core/DolphinQt/Settings/WiiPane.cpp27
-rw-r--r--Source/Core/UICommon/CMakeLists.txt2
-rw-r--r--Source/Core/UICommon/UICommon.cpp2
-rw-r--r--Source/Core/UICommon/USBUtils.cpp83
-rw-r--r--Source/Core/UICommon/USBUtils.h16
20 files changed, 423 insertions, 332 deletions
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 79aab432cd..64be002800 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -551,6 +551,8 @@ add_library(core
TimePlayed.h
TitleDatabase.cpp
TitleDatabase.h
+ USBUtils.cpp
+ USBUtils.h
WC24PatchEngine.cpp
WC24PatchEngine.h
WiiRoot.cpp
diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp
index dc6a48aa7f..31560f97bf 100644
--- a/Source/Core/Core/Config/MainSettings.cpp
+++ b/Source/Core/Core/Config/MainSettings.cpp
@@ -27,6 +27,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SI/SI_Device.h"
#include "Core/PowerPC/PowerPC.h"
+#include "Core/USBUtils.h"
#include "DiscIO/Enums.h"
#include "VideoCommon/VideoBackendBase.h"
@@ -551,40 +552,35 @@ const Info<bool> MAIN_USB_PASSTHROUGH_DISGUISE_PLAYSTATION_AS_WII{
const Info<std::string> MAIN_USB_PASSTHROUGH_DEVICES{{System::Main, "USBPassthrough", "Devices"},
""};
-static std::set<std::pair<u16, u16>> LoadUSBWhitelistFromString(const std::string& devices_string)
+static std::set<USBUtils::DeviceInfo> LoadUSBWhitelistFromString(const std::string& devices_string)
{
- std::set<std::pair<u16, u16>> devices;
+ std::set<USBUtils::DeviceInfo> devices;
for (const auto& pair : SplitString(devices_string, ','))
{
- const auto index = pair.find(':');
- if (index == std::string::npos)
- continue;
-
- const u16 vid = static_cast<u16>(strtol(pair.substr(0, index).c_str(), nullptr, 16));
- const u16 pid = static_cast<u16>(strtol(pair.substr(index + 1).c_str(), nullptr, 16));
- if (vid && pid)
- devices.emplace(vid, pid);
+ auto device = USBUtils::DeviceInfo::FromString(pair);
+ if (device)
+ devices.emplace(*device);
}
return devices;
}
-static std::string SaveUSBWhitelistToString(const std::set<std::pair<u16, u16>>& devices)
+static std::string SaveUSBWhitelistToString(const std::set<USBUtils::DeviceInfo>& devices)
{
std::ostringstream oss;
for (const auto& device : devices)
- oss << fmt::format("{:04x}:{:04x}", device.first, device.second) << ',';
+ oss << device.ToString() << ',';
std::string devices_string = oss.str();
if (!devices_string.empty())
devices_string.pop_back();
return devices_string;
}
-std::set<std::pair<u16, u16>> GetUSBDeviceWhitelist()
+std::set<USBUtils::DeviceInfo> GetUSBDeviceWhitelist()
{
return LoadUSBWhitelistFromString(Config::Get(Config::MAIN_USB_PASSTHROUGH_DEVICES));
}
-void SetUSBDeviceWhitelist(const std::set<std::pair<u16, u16>>& devices)
+void SetUSBDeviceWhitelist(const std::set<USBUtils::DeviceInfo>& devices)
{
Config::SetBase(Config::MAIN_USB_PASSTHROUGH_DEVICES, SaveUSBWhitelistToString(devices));
}
diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h
index f732d68645..580ccfdabf 100644
--- a/Source/Core/Core/Config/MainSettings.h
+++ b/Source/Core/Core/Config/MainSettings.h
@@ -11,6 +11,7 @@
#include "Common/Common.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
+#include "Core/USBUtils.h"
#include "DiscIO/Enums.h"
// DSP Backend Types
@@ -358,8 +359,8 @@ extern const Info<std::string> MAIN_BLUETOOTH_PASSTHROUGH_LINK_KEYS;
extern const Info<bool> MAIN_USB_PASSTHROUGH_DISGUISE_PLAYSTATION_AS_WII;
extern const Info<std::string> MAIN_USB_PASSTHROUGH_DEVICES;
-std::set<std::pair<u16, u16>> GetUSBDeviceWhitelist();
-void SetUSBDeviceWhitelist(const std::set<std::pair<u16, u16>>& devices);
+std::set<USBUtils::DeviceInfo> GetUSBDeviceWhitelist();
+void SetUSBDeviceWhitelist(const std::set<USBUtils::DeviceInfo>& devices);
// Main.EmulatedUSBDevices
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp
index 5fdf8fab06..ab331b7bad 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp
+++ b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.cpp
@@ -19,7 +19,6 @@
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
#include "Core/IOS/USB/Bluetooth/hci.h"
-#include "Core/IOS/USB/Host.h"
namespace
{
@@ -41,7 +40,9 @@ constexpr libusb_transfer_cb_fn LibUSBMemFunCallback()
};
}
-bool IsBluetoothDevice(const libusb_device_descriptor& descriptor)
+} // namespace
+
+bool LibUSBBluetoothAdapter::IsBluetoothDevice(const libusb_device_descriptor& descriptor)
{
constexpr u8 SUBCLASS = 0x01;
constexpr u8 PROTOCOL_BLUETOOTH = 0x01;
@@ -56,8 +57,6 @@ bool IsBluetoothDevice(const libusb_device_descriptor& descriptor)
descriptor.idVendor, descriptor.idProduct);
}
-} // namespace
-
bool LibUSBBluetoothAdapter::IsWiiBTModule() const
{
return m_is_wii_bt_module;
@@ -454,41 +453,6 @@ bool LibUSBBluetoothAdapter::OpenDevice(const libusb_device_descriptor& device_d
return true;
}
-std::vector<LibUSBBluetoothAdapter::BluetoothDeviceInfo> LibUSBBluetoothAdapter::ListDevices()
-{
- std::vector<BluetoothDeviceInfo> device_list;
- LibusbUtils::Context context;
-
- if (!context.IsValid())
- return {};
-
- int result = context.GetDeviceList([&device_list](libusb_device* device) {
- auto [config_ret, config] = LibusbUtils::MakeConfigDescriptor(device, 0);
- if (config_ret != LIBUSB_SUCCESS)
- return true;
-
- libusb_device_descriptor desc;
- if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS)
- return true;
-
- if (IsBluetoothDevice(desc))
- {
- const std::string device_name =
- IOS::HLE::USBHost::GetDeviceNameFromVIDPID(desc.idVendor, desc.idProduct);
- device_list.push_back({desc.idVendor, desc.idProduct, device_name});
- }
- return true;
- });
-
- if (result < 0)
- {
- ERROR_LOG_FMT(IOS_USB, "Failed to get device list: {}", LibusbUtils::ErrorWrap(result));
- return device_list;
- }
-
- return device_list;
-}
-
void LibUSBBluetoothAdapter::HandleOutputTransfer(libusb_transfer* tr)
{
HandleTransferError(tr);
diff --git a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h
index 6e0f8bc1de..7add7c073e 100644
--- a/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h
+++ b/Source/Core/Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h
@@ -23,15 +23,8 @@ class LibUSBBluetoothAdapter
public:
using BufferType = Common::UniqueBuffer<u8>;
- struct BluetoothDeviceInfo
- {
- u16 vid;
- u16 pid;
- std::string name;
- };
-
- static std::vector<BluetoothDeviceInfo> ListDevices();
static bool IsConfiguredBluetoothDevice(u16 vid, u16 pid);
+ static bool IsBluetoothDevice(const libusb_device_descriptor& descriptor);
static bool HasConfiguredBluetoothDevice();
// Public interface is intended to be used by a single thread.
diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp
index f8263d7afd..11adfb9f38 100644
--- a/Source/Core/Core/IOS/USB/Host.cpp
+++ b/Source/Core/Core/IOS/USB/Host.cpp
@@ -11,21 +11,6 @@
#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>
-#endif
-
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
@@ -64,107 +49,6 @@ std::optional<IPCReply> USBHost::Open(const OpenRequest& request)
return IPCReply(IPC_SUCCESS);
}
-std::string USBHost::GetDeviceNameFromVIDPID(u16 vid, u16 pid)
-{
- std::string device_name;
-#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())
- return device_name;
-
- context.GetDeviceList([&device_name, vid, pid](libusb_device* device) {
- libusb_device_descriptor desc{};
- if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS)
- return true;
-
- if (desc.idVendor != vid || desc.idProduct != pid)
- return true;
-
- if (desc.iProduct == 0)
- return false;
-
- libusb_device_handle* handle{};
- if (libusb_open(device, &handle) != LIBUSB_SUCCESS)
- return false;
-
- device_name = LibusbUtils::GetStringDescriptor(handle, desc.iProduct).value_or("");
- libusb_close(handle);
- return false;
- });
-
- if (!device_name.empty())
- return device_name;
-#endif
-#ifdef HAVE_LIBUDEV
- udev* udev = udev_new();
- if (!udev)
- return device_name;
-
- udev_hwdb* hwdb = udev_hwdb_new(udev);
- if (hwdb)
- {
- const std::string modalias = fmt::format("usb:v{:04X}p{:04X}*", vid, pid);
- udev_list_entry* entries = udev_hwdb_get_properties_list_entry(hwdb, modalias.c_str(), 0);
-
- if (entries)
- {
- udev_list_entry* device_name_entry =
- udev_list_entry_get_by_name(entries, "ID_MODEL_FROM_DATABASE");
- if (device_name_entry)
- {
- device_name = udev_list_entry_get_value(device_name_entry);
- }
- }
- udev_hwdb_unref(hwdb);
- }
-#endif
- return device_name;
-}
-
void USBHost::DoState(PointerWrap& p)
{
Device::DoState(p);
diff --git a/Source/Core/Core/IOS/USB/Host.h b/Source/Core/Core/IOS/USB/Host.h
index 9d0f537f33..ba858dc503 100644
--- a/Source/Core/Core/IOS/USB/Host.h
+++ b/Source/Core/Core/IOS/USB/Host.h
@@ -32,7 +32,6 @@ public:
void DoState(PointerWrap& p) override;
void OnDevicesChanged(const USBScanner::DeviceMap& new_devices);
- static std::string GetDeviceNameFromVIDPID(u16 vid, u16 pid);
protected:
enum class ChangeEvent
diff --git a/Source/Core/Core/IOS/USB/USBScanner.cpp b/Source/Core/Core/IOS/USB/USBScanner.cpp
index b0a170ee35..aa213ce412 100644
--- a/Source/Core/Core/IOS/USB/USBScanner.cpp
+++ b/Source/Core/Core/IOS/USB/USBScanner.cpp
@@ -28,6 +28,7 @@
#include "Core/IOS/USB/LibusbDevice.h"
#include "Core/NetPlayProto.h"
#include "Core/System.h"
+#include "Core/USBUtils.h"
namespace IOS::HLE
{
@@ -142,7 +143,7 @@ bool USBScanner::AddNewDevices(DeviceMap* new_devices) const
#ifdef __LIBUSB__
if (!Core::WantsDeterminism())
{
- auto whitelist = Config::GetUSBDeviceWhitelist();
+ const auto whitelist = Config::GetUSBDeviceWhitelist();
if (whitelist.empty())
return true;
@@ -155,7 +156,8 @@ bool USBScanner::AddNewDevices(DeviceMap* new_devices) const
{
WakeupSantrollerDevice(device);
}
- if (!whitelist.contains({descriptor.idVendor, descriptor.idProduct}))
+ const USBUtils::DeviceInfo device_info{descriptor.idVendor, descriptor.idProduct};
+ if (!whitelist.contains(device_info))
return true;
auto usb_device = std::make_unique<USB::LibusbDevice>(device, descriptor);
diff --git a/Source/Core/Core/USBUtils.cpp b/Source/Core/Core/USBUtils.cpp
new file mode 100644
index 0000000000..b2edfd0b22
--- /dev/null
+++ b/Source/Core/Core/USBUtils.cpp
@@ -0,0 +1,300 @@
+// Copyright 2025 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "Core/USBUtils.h"
+
+#include <charconv>
+#include <cwchar>
+#include <functional>
+#include <map>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#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>
+
+#include "Common/StringUtil.h"
+#include "Common/WindowsDevice.h"
+#endif
+
+#include "Common/CommonTypes.h"
+#include "Common/Logging/Log.h"
+#include "Common/MsgHandler.h"
+#include "Common/ScopeGuard.h"
+#include "Core/LibusbUtils.h"
+
+// Device names for known Wii peripherals.
+static const std::map<USBUtils::DeviceInfo, std::string> s_known_devices{{
+ {{0x046d, 0x0a03}, "Logitech Microphone"},
+ {{0x057e, 0x0308}, "Wii Speak"},
+ {{0x057e, 0x0309}, "Nintendo USB Microphone"},
+ {{0x057e, 0x030a}, "Ubisoft Motion Tracking Camera"},
+ {{0x0e6f, 0x0129}, "Disney Infinity Reader (Portal Device)"},
+ {{0x12ba, 0x0200}, "Harmonix Guitar for PlayStation 3"},
+ {{0x12ba, 0x0210}, "Harmonix Drum Kit for PlayStation 3"},
+ {{0x12ba, 0x0218}, "Harmonix Drum Kit for PlayStation 3"},
+ {{0x12ba, 0x2330}, "Harmonix RB3 Keyboard for PlayStation 3"},
+ {{0x12ba, 0x2338}, "Harmonix RB3 MIDI Keyboard Interface for PlayStation 3"},
+ {{0x12ba, 0x2430}, "Harmonix RB3 Mustang Guitar for PlayStation 3"},
+ {{0x12ba, 0x2438}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
+ {{0x12ba, 0x2530}, "Harmonix RB3 Squier Guitar for PlayStation 3"},
+ {{0x12ba, 0x2538}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
+ {{0x1430, 0x0100}, "Tony Hawk Ride Skateboard"},
+ {{0x1430, 0x0150}, "Skylanders Portal"},
+ {{0x1bad, 0x0004}, "Harmonix Guitar Controller for Nintendo Wii"},
+ {{0x1bad, 0x0005}, "Harmonix Drum Controller for Nintendo Wii"},
+ {{0x1bad, 0x3010}, "Harmonix Guitar Controller for Nintendo Wii"},
+ {{0x1bad, 0x3110}, "Harmonix Drum Controller for Nintendo Wii"},
+ {{0x1bad, 0x3138}, "Harmonix Drum Controller for Nintendo Wii"},
+ {{0x1bad, 0x3330}, "Harmonix RB3 Keyboard for Nintendo Wii"},
+ {{0x1bad, 0x3338}, "Harmonix RB3 MIDI Keyboard Interface for Nintendo Wii"},
+ {{0x1bad, 0x3430}, "Harmonix RB3 Mustang Guitar for Nintendo Wii"},
+ {{0x1bad, 0x3438}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
+ {{0x1bad, 0x3530}, "Harmonix RB3 Squier Guitar for Nintendo Wii"},
+ {{0x1bad, 0x3538}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
+ {{0x21a4, 0xac40}, "EA Active NFL"},
+}};
+
+namespace USBUtils
+{
+std::optional<DeviceInfo> DeviceInfo::FromString(const std::string& str)
+{
+ const size_t colon_index = str.find(':');
+ if (colon_index == std::string::npos)
+ return std::nullopt;
+
+ auto parse_hex = [](std::string_view sv, u16& out) -> bool {
+ auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), out, 16);
+ return ec == std::errc();
+ };
+
+ DeviceInfo info;
+ std::string_view vid_sv(str.data(), colon_index);
+ std::string_view pid_sv(str.data() + colon_index + 1);
+
+ if (!parse_hex(vid_sv, info.vid))
+ return std::nullopt;
+ if (!parse_hex(pid_sv, info.pid))
+ return std::nullopt;
+
+ return info;
+}
+
+std::string DeviceInfo::ToString() const
+{
+ return fmt::format("{:04x}:{:04x}", vid, pid);
+}
+
+std::string DeviceInfo::ToDisplayString() const
+{
+ const std::string name =
+ // i18n: This replaces the name of a device if it cannot be found.
+ GetDeviceNameFromVIDPID(vid, pid).value_or(Common::GetStringT("Unknown Device"));
+ return ToDisplayString(name);
+}
+
+std::string DeviceInfo::ToDisplayString(const std::string& name) const
+{
+ return fmt::format("{} ({:04x}:{:04x})", name, vid, pid);
+}
+
+static std::optional<std::string> GetDeviceNameUsingKnownDevices(u16 vid, u16 pid)
+{
+ const auto iter = s_known_devices.find(DeviceInfo{vid, pid});
+ if (iter != s_known_devices.end())
+ return iter->second;
+ return std::nullopt;
+}
+
+#ifdef _WIN32
+static std::optional<std::string> GetDeviceNameUsingSetupAPI(u16 vid, u16 pid)
+{
+ std::optional<std::string> device_name;
+ 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 std::nullopt;
+ 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);
+ }
+
+ if (!property_value.empty())
+ device_name = WStringToUTF8(property_value);
+ break;
+ }
+
+ SetupDiDestroyDeviceInfoList(dev_info);
+ return device_name;
+}
+#endif
+
+#ifdef HAVE_LIBUDEV
+static std::optional<std::string> GetDeviceNameUsingHWDB(u16 vid, u16 pid)
+{
+ std::optional<std::string> device_name;
+ udev* udev = udev_new();
+ if (!udev)
+ return std::nullopt;
+
+ Common::ScopeGuard udev_guard{[&] { udev_unref(udev); }};
+
+ udev_hwdb* hwdb = udev_hwdb_new(udev);
+ if (!hwdb)
+ return std::nullopt;
+
+ Common::ScopeGuard hwdb_guard{[&] { udev_hwdb_unref(hwdb); }};
+
+ const std::string modalias = fmt::format("usb:v{:04X}p{:04X}*", vid, pid);
+ udev_list_entry* entries = udev_hwdb_get_properties_list_entry(hwdb, modalias.c_str(), 0);
+ if (!entries)
+ return std::nullopt;
+
+ udev_list_entry* device_name_entry =
+ udev_list_entry_get_by_name(entries, "ID_MODEL_FROM_DATABASE");
+ if (!device_name_entry)
+ return std::nullopt;
+
+ device_name = udev_list_entry_get_value(device_name_entry);
+
+ 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)
+static std::optional<std::string> GetDeviceNameUsingLibUSB(u16 vid, u16 pid)
+{
+ std::optional<std::string> device_name;
+ LibusbUtils::Context context;
+
+ if (!context.IsValid())
+ return std::nullopt;
+
+ context.GetDeviceList([&device_name, vid, pid](libusb_device* device) {
+ libusb_device_descriptor desc{};
+
+ if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS)
+ return true;
+
+ if (desc.idVendor != vid || desc.idProduct != pid)
+ return true;
+
+ if (!desc.iProduct)
+ return false;
+
+ libusb_device_handle* handle;
+ if (libusb_open(device, &handle) != LIBUSB_SUCCESS)
+ return false;
+
+ device_name = LibusbUtils::GetStringDescriptor(handle, desc.iProduct);
+ libusb_close(handle);
+ return false;
+ });
+ return device_name;
+}
+#endif
+
+std::optional<std::string> GetDeviceNameFromVIDPID(u16 vid, u16 pid)
+{
+ using LookupFn = std::optional<std::string> (*)(u16, u16);
+
+ // Try name lookup backends in priority order:
+ // 1. Known Devices - Known, hard‑coded devices (fast, most reliable)
+ // 2. HWDB - libudev’s hardware database (fast, OS‑specific)
+ // 3. Setup API - Vendor/Product registry on Windows (moderately fast, OS‑specific)
+ // 4. libusb - Fallback to querying the USB device (slowest)
+ static constexpr auto backends = std::to_array<LookupFn>({
+ &GetDeviceNameUsingKnownDevices,
+#ifdef HAVE_LIBUDEV
+ &GetDeviceNameUsingHWDB,
+#endif
+#ifdef _WIN32
+ &GetDeviceNameUsingSetupAPI,
+#endif
+#if defined(__LIBUSB__) && !defined(_WIN32)
+ &GetDeviceNameUsingLibUSB,
+#endif
+ });
+
+ for (const auto& backend : backends)
+ {
+ if (auto name = backend(vid, pid))
+ return name;
+ }
+ return std::nullopt;
+}
+
+#ifdef __LIBUSB__
+std::vector<DeviceInfo>
+ListDevices(const std::function<bool(const libusb_device_descriptor&)>& filter)
+{
+ std::vector<DeviceInfo> device_list;
+ LibusbUtils::Context context;
+ if (!context.IsValid())
+ return {};
+
+ const int ret = context.GetDeviceList([&device_list, &filter](libusb_device* device) {
+ libusb_device_descriptor desc;
+
+ if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS)
+ return true;
+
+ if (filter(desc))
+ {
+ device_list.push_back({desc.idVendor, desc.idProduct});
+ }
+
+ return true;
+ });
+
+ if (ret != LIBUSB_SUCCESS)
+ WARN_LOG_FMT(CORE, "Failed to get device list: {}", LibusbUtils::ErrorWrap(ret));
+
+ return device_list;
+}
+
+std::vector<DeviceInfo> ListDevices(const std::function<bool(const DeviceInfo&)>& filter)
+{
+ return ListDevices([&filter](const libusb_device_descriptor& desc) {
+ const DeviceInfo info{desc.idVendor, desc.idProduct};
+ return filter(info);
+ });
+}
+#endif
+} // namespace USBUtils
diff --git a/Source/Core/Core/USBUtils.h b/Source/Core/Core/USBUtils.h
new file mode 100644
index 0000000000..1147cced31
--- /dev/null
+++ b/Source/Core/Core/USBUtils.h
@@ -0,0 +1,40 @@
+// Copyright 2025 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <functional>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include "Common/CommonTypes.h"
+
+struct libusb_device_descriptor;
+
+namespace USBUtils
+{
+
+struct DeviceInfo
+{
+ u16 vid;
+ u16 pid;
+
+ constexpr auto operator<=>(const DeviceInfo& other) const = default;
+
+ // Extracts DeviceInfo from a string in the format "VID:PID"
+ static std::optional<DeviceInfo> FromString(const std::string& str);
+ std::string ToString() const;
+ std::string ToDisplayString() const;
+ std::string ToDisplayString(const std::string& name) const;
+};
+
+std::optional<std::string> GetDeviceNameFromVIDPID(u16 vid, u16 pid);
+
+std::vector<DeviceInfo>
+ListDevices(const std::function<bool(const struct libusb_device_descriptor&)>& filter =
+ [](const struct libusb_device_descriptor&) { return true; });
+std::vector<DeviceInfo> ListDevices(const std::function<bool(const DeviceInfo&)>& filter =
+ [](const DeviceInfo&) { return true; });
+
+} // namespace USBUtils
diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props
index 5803fb0437..bc865343e0 100644
--- a/Source/Core/DolphinLib.props
+++ b/Source/Core/DolphinLib.props
@@ -473,6 +473,7 @@
<ClInclude Include="Core\System.h" />
<ClInclude Include="Core\TimePlayed.h" />
<ClInclude Include="Core\TitleDatabase.h" />
+ <ClInclude Include="Core\USBUtils.h" />
<ClInclude Include="Core\WC24PatchEngine.h" />
<ClInclude Include="Core\WiiRoot.h" />
<ClInclude Include="Core\WiiUtils.h" />
@@ -573,7 +574,6 @@
<ClInclude Include="UICommon\ResourcePack\Manifest.h" />
<ClInclude Include="UICommon\ResourcePack\ResourcePack.h" />
<ClInclude Include="UICommon\UICommon.h" />
- <ClInclude Include="UICommon\USBUtils.h" />
<ClInclude Include="UpdaterCommon\UI.h" />
<ClInclude Include="UpdaterCommon\UpdaterCommon.h" />
<ClInclude Include="VideoBackends\D3D\D3DBase.h" />
@@ -1152,6 +1152,7 @@
<ClCompile Include="Core\System.cpp" />
<ClCompile Include="Core\TimePlayed.cpp" />
<ClCompile Include="Core\TitleDatabase.cpp" />
+ <ClCompile Include="Core\USBUtils.cpp" />
<ClCompile Include="Core\WiiRoot.cpp" />
<ClCompile Include="Core\WiiUtils.cpp" />
<ClCompile Include="Core\WC24PatchEngine.cpp" />
@@ -1244,7 +1245,6 @@
<ClCompile Include="UICommon\ResourcePack\Manifest.cpp" />
<ClCompile Include="UICommon\ResourcePack\ResourcePack.cpp" />
<ClCompile Include="UICommon\UICommon.cpp" />
- <ClCompile Include="UICommon\USBUtils.cpp" />
<ClCompile Include="UpdaterCommon\UpdaterCommon.cpp" />
<ClCompile Include="VideoBackends\D3D\D3DBase.cpp" />
<ClCompile Include="VideoBackends\D3D\D3DBoundingBox.cpp" />
diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp
index 11c98ee883..8517e4328e 100644
--- a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp
+++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp
@@ -28,6 +28,7 @@
#include "Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h"
#include "Core/NetPlayProto.h"
#include "Core/System.h"
+#include "Core/USBUtils.h"
#include "Core/WiiUtils.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
@@ -64,6 +65,7 @@ void WiimoteControllersWidget::UpdateBluetoothAvailableStatus()
void WiimoteControllersWidget::StartBluetoothAdapterRefresh()
{
+#ifdef __LIBUSB__
if (m_bluetooth_adapter_scan_in_progress)
return;
@@ -75,7 +77,7 @@ void WiimoteControllersWidget::StartBluetoothAdapterRefresh()
const auto scan_func = [this]() {
INFO_LOG_FMT(COMMON, "Refreshing Bluetooth adapter list...");
- auto device_list = LibUSBBluetoothAdapter::ListDevices();
+ auto device_list = USBUtils::ListDevices(LibUSBBluetoothAdapter::IsBluetoothDevice);
INFO_LOG_FMT(COMMON, "{} Bluetooth adapters available.", device_list.size());
const auto refresh_complete_func = [this, devices = std::move(device_list)]() {
OnBluetoothAdapterRefreshComplete(devices);
@@ -84,10 +86,11 @@ void WiimoteControllersWidget::StartBluetoothAdapterRefresh()
};
m_bluetooth_adapter_refresh_thread.Push(scan_func);
+#endif
}
void WiimoteControllersWidget::OnBluetoothAdapterRefreshComplete(
- const std::vector<LibUSBBluetoothAdapter::BluetoothDeviceInfo>& devices)
+ const std::vector<USBUtils::DeviceInfo>& devices)
{
const int configured_vid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID);
const int configured_pid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_PID);
@@ -103,10 +106,8 @@ void WiimoteControllersWidget::OnBluetoothAdapterRefreshComplete(
for (auto& device : devices)
{
- std::string name = device.name.empty() ? tr("Unknown Device").toStdString() : device.name;
- QString device_info =
- QString::fromStdString(fmt::format("{} ({:04x}:{:04x})", name, device.vid, device.pid));
- m_bluetooth_adapters->addItem(device_info, QVariant::fromValue(device));
+ m_bluetooth_adapters->addItem(QString::fromStdString(device.ToDisplayString()),
+ QVariant::fromValue(device));
if (!found_configured_device &&
LibUSBBluetoothAdapter::IsConfiguredBluetoothDevice(device.vid, device.pid))
@@ -121,13 +122,12 @@ void WiimoteControllersWidget::OnBluetoothAdapterRefreshComplete(
const QString name = QLatin1Char{'['} + tr("disconnected") + QLatin1Char(']');
const std::string name_str = name.toStdString();
- LibUSBBluetoothAdapter::BluetoothDeviceInfo disconnected_device;
+ USBUtils::DeviceInfo disconnected_device;
disconnected_device.vid = configured_vid;
disconnected_device.pid = configured_pid;
- disconnected_device.name = name_str;
- QString device_info = QString::fromStdString(
- fmt::format("{} ({:04x}:{:04x})", name_str, configured_vid, configured_pid));
+ const QString device_info =
+ QString::fromStdString(disconnected_device.ToDisplayString(name_str));
m_bluetooth_adapters->insertSeparator(m_bluetooth_adapters->count());
m_bluetooth_adapters->addItem(device_info, QVariant::fromValue(disconnected_device));
@@ -311,13 +311,13 @@ void WiimoteControllersWidget::OnBluetoothPassthroughDeviceChanged(int index)
const QVariant item_data = m_bluetooth_adapters->itemData(index);
- if (!item_data.isValid() || !item_data.canConvert<LibUSBBluetoothAdapter::BluetoothDeviceInfo>())
+ if (!item_data.isValid() || !item_data.canConvert<USBUtils::DeviceInfo>())
{
ERROR_LOG_FMT(COMMON, "Invalid Bluetooth device info selected in WiimoteControllersWidget");
return;
}
- const auto& device_info = item_data.value<LibUSBBluetoothAdapter::BluetoothDeviceInfo>();
+ const auto& device_info = item_data.value<USBUtils::DeviceInfo>();
Config::SetBaseOrCurrent(Config::MAIN_BLUETOOTH_PASSTHROUGH_PID, device_info.pid);
Config::SetBaseOrCurrent(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID, device_info.vid);
diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h
index e8507d9866..ef75fbbcbb 100644
--- a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h
+++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h
@@ -8,7 +8,7 @@
#include <QWidget>
#include "Common/WorkQueueThread.h"
-#include "Core/IOS/USB/Bluetooth/LibUSBBluetoothAdapter.h"
+#include "Core/USBUtils.h"
class QCheckBox;
class QComboBox;
@@ -38,8 +38,7 @@ private:
void OnBluetoothPassthroughDeviceChanged(int index);
void OnBluetoothPassthroughSyncPressed();
void OnBluetoothPassthroughResetPressed();
- void OnBluetoothAdapterRefreshComplete(
- const std::vector<LibUSBBluetoothAdapter::BluetoothDeviceInfo>& devices);
+ void OnBluetoothAdapterRefreshComplete(const std::vector<USBUtils::DeviceInfo>& devices);
void OnWiimoteRefreshPressed();
void OnWiimoteConfigure(size_t index);
void StartBluetoothAdapterRefresh();
diff --git a/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.cpp b/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.cpp
index b1133e16d6..05f940505c 100644
--- a/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.cpp
+++ b/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.cpp
@@ -16,16 +16,17 @@
#include <QVBoxLayout>
#include <QWidget>
+#include <fmt/format.h>
+
#include "Common/StringUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
+#include "Core/USBUtils.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/Settings/WiiPane.h"
-#include "UICommon/USBUtils.h"
-
static bool IsValidUSBIDString(const std::string& string)
{
if (string.empty() || string.length() > 4)
@@ -105,20 +106,23 @@ void USBDeviceAddToWhitelistDialog::InitControls()
device_vid_textbox->setMaxLength(4);
device_pid_textbox->setMaxLength(4);
}
-
void USBDeviceAddToWhitelistDialog::RefreshDeviceList()
{
- const auto& current_devices = USBUtils::GetInsertedDevices();
+ const auto whitelist = Config::GetUSBDeviceWhitelist();
+
+ const auto& current_devices = USBUtils::ListDevices(
+ [&whitelist](const USBUtils::DeviceInfo& device) { return !whitelist.contains(device); });
+
if (current_devices == m_shown_devices)
return;
const auto selection_string = usb_inserted_devices_list->currentItem();
usb_inserted_devices_list->clear();
- auto whitelist = Config::GetUSBDeviceWhitelist();
for (const auto& device : current_devices)
{
- if (whitelist.contains({device.first.first, device.first.second}))
- continue;
- usb_inserted_devices_list->addItem(QString::fromStdString(device.second));
+ auto* item = new QListWidgetItem(QString::fromStdString(device.ToDisplayString()),
+ usb_inserted_devices_list);
+ QVariant device_data = QVariant::fromValue(device);
+ item->setData(Qt::UserRole, device_data);
}
usb_inserted_devices_list->setCurrentItem(selection_string);
@@ -147,15 +151,16 @@ void USBDeviceAddToWhitelistDialog::AddUSBDeviceToWhitelist()
const u16 vid = static_cast<u16>(std::stoul(vid_string, nullptr, 16));
const u16 pid = static_cast<u16>(std::stoul(pid_string, nullptr, 16));
+ const USBUtils::DeviceInfo new_device{vid, pid};
auto whitelist = Config::GetUSBDeviceWhitelist();
- auto it = whitelist.emplace(vid, pid);
- if (!it.second)
+ if (whitelist.contains(new_device))
{
ModalMessageBox::critical(this, tr("USB Whitelist Error"),
tr("This USB device is already whitelisted."));
return;
}
+ whitelist.emplace(new_device);
Config::SetUSBDeviceWhitelist(whitelist);
Config::Save();
accept();
@@ -163,11 +168,13 @@ void USBDeviceAddToWhitelistDialog::AddUSBDeviceToWhitelist()
void USBDeviceAddToWhitelistDialog::OnDeviceSelection()
{
- // Not the nicest way of doing this but...
- QString device = usb_inserted_devices_list->currentItem()->text().left(9);
- QStringList split = device.split(QString::fromStdString(":"));
- QString* vid = new QString(split[0]);
- QString* pid = new QString(split[1]);
- device_vid_textbox->setText(*vid);
- device_pid_textbox->setText(*pid);
+ auto* current_item = usb_inserted_devices_list->currentItem();
+ if (!current_item)
+ return;
+
+ QVariant item_data = current_item->data(Qt::UserRole);
+ USBUtils::DeviceInfo device = item_data.value<USBUtils::DeviceInfo>();
+
+ device_vid_textbox->setText(QString::fromStdString(fmt::format("{:04x}", device.vid)));
+ device_pid_textbox->setText(QString::fromStdString(fmt::format("{:04x}", device.pid)));
}
diff --git a/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h b/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h
index 5ae1199f2e..deb513698a 100644
--- a/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h
+++ b/Source/Core/DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h
@@ -3,8 +3,12 @@
#pragma once
+#include <vector>
+
#include <QDialog>
+#include "Core/USBUtils.h"
+
class QTimer;
class QDialog;
class QHeaderView;
@@ -44,5 +48,5 @@ private:
void OnDeviceSelection();
- std::map<std::pair<quint16, quint16>, std::string> m_shown_devices;
+ std::vector<USBUtils::DeviceInfo> m_shown_devices;
};
diff --git a/Source/Core/DolphinQt/Settings/WiiPane.cpp b/Source/Core/DolphinQt/Settings/WiiPane.cpp
index 0ec003c827..5aa1caea13 100644
--- a/Source/Core/DolphinQt/Settings/WiiPane.cpp
+++ b/Source/Core/DolphinQt/Settings/WiiPane.cpp
@@ -30,6 +30,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/System.h"
+#include "Core/USBUtils.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
@@ -40,8 +41,6 @@
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h"
-#include "UICommon/USBUtils.h"
-
// SYSCONF uses 0 for bottom and 1 for top, but we place them in
// the other order in the GUI so that Top will be above Bottom,
// matching the respective physical placements of the sensor bar.
@@ -469,14 +468,15 @@ void WiiPane::OnUSBWhitelistAddButton()
void WiiPane::OnUSBWhitelistRemoveButton()
{
- QString device = m_whitelist_usb_list->currentItem()->text().left(9);
- QStringList split = device.split(QString::fromStdString(":"));
- QString vid = QString(split[0]);
- QString pid = QString(split[1]);
- const u16 vid_u16 = static_cast<u16>(std::stoul(vid.toStdString(), nullptr, 16));
- const u16 pid_u16 = static_cast<u16>(std::stoul(pid.toStdString(), nullptr, 16));
+ auto* current_item = m_whitelist_usb_list->currentItem();
+ if (!current_item)
+ return;
+
+ QVariant item_data = current_item->data(Qt::UserRole);
+ USBUtils::DeviceInfo device = item_data.value<USBUtils::DeviceInfo>();
+
auto whitelist = Config::GetUSBDeviceWhitelist();
- whitelist.erase({vid_u16, pid_u16});
+ whitelist.erase(device);
Config::SetUSBDeviceWhitelist(whitelist);
PopulateUSBPassthroughListWidget();
}
@@ -485,11 +485,12 @@ void WiiPane::PopulateUSBPassthroughListWidget()
{
m_whitelist_usb_list->clear();
auto whitelist = Config::GetUSBDeviceWhitelist();
- for (const auto& device : whitelist)
+ for (auto& device : whitelist)
{
- QListWidgetItem* usb_lwi =
- new QListWidgetItem(QString::fromStdString(USBUtils::GetDeviceName(device)));
- m_whitelist_usb_list->addItem(usb_lwi);
+ auto* item =
+ new QListWidgetItem(QString::fromStdString(device.ToDisplayString()), m_whitelist_usb_list);
+ QVariant device_data = QVariant::fromValue(device);
+ item->setData(Qt::UserRole, device_data);
}
ValidateSelectionState();
}
diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt
index d57fdb811a..2f248e1066 100644
--- a/Source/Core/UICommon/CMakeLists.txt
+++ b/Source/Core/UICommon/CMakeLists.txt
@@ -19,8 +19,6 @@ add_library(uicommon
ResourcePack/ResourcePack.h
UICommon.cpp
UICommon.h
- USBUtils.cpp
- USBUtils.h
)
target_link_libraries(uicommon
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index 89912c802c..4f55660bcc 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -42,13 +42,13 @@
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/System.h"
+#include "Core/USBUtils.h"
#include "Core/WiiRoot.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
#include "UICommon/DiscordPresence.h"
-#include "UICommon/USBUtils.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
diff --git a/Source/Core/UICommon/USBUtils.cpp b/Source/Core/UICommon/USBUtils.cpp
deleted file mode 100644
index 42c4bd93fd..0000000000
--- a/Source/Core/UICommon/USBUtils.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include "UICommon/USBUtils.h"
-
-#include <string_view>
-
-#include <fmt/format.h>
-#ifdef __LIBUSB__
-#include <libusb.h>
-#endif
-
-#include "Common/CommonTypes.h"
-#include "Common/Logging/Log.h"
-#include "Core/LibusbUtils.h"
-
-// Because opening and getting the device name from devices is slow, especially on Windows
-// with usbdk, we cannot do that for every single device. We should however still show
-// device names for known Wii peripherals.
-static const std::map<std::pair<u16, u16>, std::string_view> s_known_peripherals{{
- {{0x046d, 0x0a03}, "Logitech Microphone"},
- {{0x057e, 0x0308}, "Wii Speak"},
- {{0x057e, 0x0309}, "Nintendo USB Microphone"},
- {{0x057e, 0x030a}, "Ubisoft Motion Tracking Camera"},
- {{0x0e6f, 0x0129}, "Disney Infinity Reader (Portal Device)"},
- {{0x12ba, 0x0200}, "Harmonix Guitar for PlayStation 3"},
- {{0x12ba, 0x0210}, "Harmonix Drum Kit for PlayStation 3"},
- {{0x12ba, 0x0218}, "Harmonix Drum Kit for PlayStation 3"},
- {{0x12ba, 0x2330}, "Harmonix RB3 Keyboard for PlayStation 3"},
- {{0x12ba, 0x2338}, "Harmonix RB3 MIDI Keyboard Interface for PlayStation 3"},
- {{0x12ba, 0x2430}, "Harmonix RB3 Mustang Guitar for PlayStation 3"},
- {{0x12ba, 0x2438}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
- {{0x12ba, 0x2530}, "Harmonix RB3 Squier Guitar for PlayStation 3"},
- {{0x12ba, 0x2538}, "Harmonix RB3 MIDI Guitar Interface for PlayStation 3"},
- {{0x1430, 0x0100}, "Tony Hawk Ride Skateboard"},
- {{0x1430, 0x0150}, "Skylanders Portal"},
- {{0x1bad, 0x0004}, "Harmonix Guitar Controller for Nintendo Wii"},
- {{0x1bad, 0x0005}, "Harmonix Drum Controller for Nintendo Wii"},
- {{0x1bad, 0x3010}, "Harmonix Guitar Controller for Nintendo Wii"},
- {{0x1bad, 0x3110}, "Harmonix Drum Controller for Nintendo Wii"},
- {{0x1bad, 0x3138}, "Harmonix Drum Controller for Nintendo Wii"},
- {{0x1bad, 0x3330}, "Harmonix RB3 Keyboard for Nintendo Wii"},
- {{0x1bad, 0x3338}, "Harmonix RB3 MIDI Keyboard Interface for Nintendo Wii"},
- {{0x1bad, 0x3430}, "Harmonix RB3 Mustang Guitar for Nintendo Wii"},
- {{0x1bad, 0x3438}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
- {{0x1bad, 0x3530}, "Harmonix RB3 Squier Guitar for Nintendo Wii"},
- {{0x1bad, 0x3538}, "Harmonix RB3 MIDI Guitar Interface for Nintendo Wii"},
- {{0x21a4, 0xac40}, "EA Active NFL"},
-}};
-
-namespace USBUtils
-{
-std::map<std::pair<u16, u16>, std::string> GetInsertedDevices()
-{
- std::map<std::pair<u16, u16>, std::string> devices;
-
-#ifdef __LIBUSB__
- LibusbUtils::Context context;
- if (!context.IsValid())
- return devices;
-
- const int ret = context.GetDeviceList([&](libusb_device* device) {
- libusb_device_descriptor descr;
- libusb_get_device_descriptor(device, &descr);
- const std::pair<u16, u16> vid_pid{descr.idVendor, descr.idProduct};
- devices[vid_pid] = GetDeviceName(vid_pid);
- return true;
- });
- if (ret != LIBUSB_SUCCESS)
- WARN_LOG_FMT(COMMON, "GetDeviceList failed: {}", LibusbUtils::ErrorWrap(ret));
-#endif
-
- return devices;
-}
-
-std::string GetDeviceName(const std::pair<u16, u16> vid_pid)
-{
- const auto iter = s_known_peripherals.find(vid_pid);
- const std::string_view device_name =
- iter == s_known_peripherals.cend() ? "Unknown" : iter->second;
- return fmt::format("{:04x}:{:04x} - {}", vid_pid.first, vid_pid.second, device_name);
-}
-} // namespace USBUtils
diff --git a/Source/Core/UICommon/USBUtils.h b/Source/Core/UICommon/USBUtils.h
deleted file mode 100644
index 1eb54d81d9..0000000000
--- a/Source/Core/UICommon/USBUtils.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 Dolphin Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include "Common/CommonTypes.h"
-
-namespace USBUtils
-{
-std::map<std::pair<u16, u16>, std::string> GetInsertedDevices();
-std::string GetDeviceName(std::pair<u16, u16> vid_pid);
-} // namespace USBUtils