USBUtils: Refactor USB device handling

This commit is contained in:
Joshua Vandaële
2025-07-12 14:03:30 +02:00
parent c39c8277b7
commit 4ae195ee60
20 changed files with 423 additions and 332 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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)));
}

View File

@ -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;
};

View File

@ -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();
}