diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index edb2386bd4..0a8294acea 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -75,6 +75,7 @@ void SConfig::SaveSettings() SaveAnalyticsSettings(ini); SaveNetworkSettings(ini); SaveBluetoothPassthroughSettings(ini); + SaveUSBPassthroughSettings(ini); SaveSysconfSettings(ini); ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX)); @@ -341,6 +342,20 @@ void SConfig::SaveBluetoothPassthroughSettings(IniFile& ini) section->Set("LinkKeys", m_bt_passthrough_link_keys); } +void SConfig::SaveUSBPassthroughSettings(IniFile& ini) +{ + IniFile::Section* section = ini.GetOrCreateSection("USBPassthrough"); + + std::ostringstream oss; + for (const auto& device : m_usb_passthrough_devices) + oss << StringFromFormat("%04x:%04x", device.first, device.second) << ','; + std::string devices_string = oss.str(); + if (!devices_string.empty()) + devices_string.pop_back(); + + section->Set("Devices", devices_string); +} + void SConfig::SaveSysconfSettings(IniFile& ini) { IniFile::Section* section = ini.GetOrCreateSection("Sysconf"); @@ -398,6 +413,7 @@ void SConfig::LoadSettings() LoadNetworkSettings(ini); LoadAnalyticsSettings(ini); LoadBluetoothPassthroughSettings(ini); + LoadUSBPassthroughSettings(ini); LoadSysconfSettings(ini); } @@ -674,6 +690,27 @@ void SConfig::LoadBluetoothPassthroughSettings(IniFile& ini) section->Get("LinkKeys", &m_bt_passthrough_link_keys, ""); } +void SConfig::LoadUSBPassthroughSettings(IniFile& ini) +{ + IniFile::Section* section = ini.GetOrCreateSection("USBPassthrough"); + m_usb_passthrough_devices.clear(); + std::string devices_string; + std::vector pairs; + section->Get("Devices", &devices_string, ""); + SplitString(devices_string, ',', pairs); + for (const auto& pair : pairs) + { + const auto index = pair.find(':'); + if (index == std::string::npos) + continue; + + const u16 vid = static_cast(strtol(pair.substr(0, index).c_str(), nullptr, 16)); + const u16 pid = static_cast(strtol(pair.substr(index + 1).c_str(), nullptr, 16)); + if (vid && pid) + m_usb_passthrough_devices.emplace(vid, pid); + } +} + void SConfig::LoadSysconfSettings(IniFile& ini) { IniFile::Section* section = ini.GetOrCreateSection("Sysconf"); @@ -764,6 +801,11 @@ void SConfig::LoadDefaults() m_revision = 0; } +bool SConfig::IsUSBDeviceWhitelisted(const std::pair vid_pid) const +{ + return m_usb_passthrough_devices.find(vid_pid) != m_usb_passthrough_devices.end(); +} + const char* SConfig::GetDirectoryForRegion(DiscIO::Region region) { switch (region) diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index e91bb9b1ff..8ac1bc2ee4 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -5,7 +5,9 @@ #pragma once #include +#include #include +#include #include #include "Common/IniFile.h" @@ -151,6 +153,10 @@ struct SConfig : NonCopyable int m_bt_passthrough_vid = -1; std::string m_bt_passthrough_link_keys; + // USB passthrough settings + std::set> m_usb_passthrough_devices; + bool IsUSBDeviceWhitelisted(std::pair vid_pid) const; + // SYSCONF settings int m_sensor_bar_position = 0x01; int m_sensor_bar_sensitivity = 0x03; @@ -350,6 +356,7 @@ private: void SaveNetworkSettings(IniFile& ini); void SaveAnalyticsSettings(IniFile& ini); void SaveBluetoothPassthroughSettings(IniFile& ini); + void SaveUSBPassthroughSettings(IniFile& ini); void SaveSysconfSettings(IniFile& ini); void LoadGeneralSettings(IniFile& ini); @@ -364,6 +371,7 @@ private: void LoadNetworkSettings(IniFile& ini); void LoadAnalyticsSettings(IniFile& ini); void LoadBluetoothPassthroughSettings(IniFile& ini); + void LoadUSBPassthroughSettings(IniFile& ini); void LoadSysconfSettings(IniFile& ini); bool SetRegion(DiscIO::Region region, std::string* directory_name); diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index 65630b6b8e..6bfc4be9bd 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -1,6 +1,10 @@ set(SRCS Disassembler.cpp - UICommon.cpp) + UICommon.cpp + USBUtils.cpp) set(LIBS common) +if(LIBUSB_FOUND) + set(LIBS ${LIBS} ${LIBUSB_LIBRARIES}) +endif() add_dolphin_library(uicommon "${SRCS}" "${LIBS}") diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index ece3d2d2ee..8de73bd151 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -17,6 +17,7 @@ #include "InputCommon/GCAdapter.h" #include "UICommon/UICommon.h" +#include "UICommon/USBUtils.h" #include "VideoCommon/VideoBackendBase.h" @@ -29,6 +30,7 @@ void Init() VideoBackendBase::PopulateList(); WiimoteReal::LoadSettings(); GCAdapter::Init(); + USBUtils::Init(); VideoBackendBase::ActivateBackend(SConfig::GetInstance().m_strVideoBackend); SetEnableAlert(SConfig::GetInstance().bUsePanicHandlers); @@ -40,6 +42,7 @@ void Shutdown() WiimoteReal::Shutdown(); VideoBackendBase::ClearList(); SConfig::Shutdown(); + USBUtils::Shutdown(); LogManager::Shutdown(); } diff --git a/Source/Core/UICommon/UICommon.vcxproj b/Source/Core/UICommon/UICommon.vcxproj index 24f4a1cfc5..567ba5f6ff 100644 --- a/Source/Core/UICommon/UICommon.vcxproj +++ b/Source/Core/UICommon/UICommon.vcxproj @@ -45,10 +45,14 @@ + + 4200;%(DisableSpecificWarnings) + + diff --git a/Source/Core/UICommon/USBUtils.cpp b/Source/Core/UICommon/USBUtils.cpp new file mode 100644 index 0000000000..8f0ba21d52 --- /dev/null +++ b/Source/Core/UICommon/USBUtils.cpp @@ -0,0 +1,79 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#ifdef __LIBUSB__ +#include +#endif + +#include "Common/CommonTypes.h" +#include "Common/StringUtil.h" +#include "UICommon/USBUtils.h" + +#ifdef __LIBUSB__ +static libusb_context* s_libusb_context; +#endif + +// 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::string> s_wii_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)"}, + {{0x1430, 0x0100}, "Tony Hawk Ride Skateboard"}, + {{0x1430, 0x0150}, "Skylanders Portal"}, + {{0x1bad, 0x0004}, "Harmonix Guitar Controller"}, + {{0x1bad, 0x3110}, "Rock Band 3 Mustang Guitar Dongle"}, + {{0x1bad, 0x3430}, "Rock Band Drum Set"}, + {{0x21a4, 0xac40}, "EA Active NFL"}, +}}; + +namespace USBUtils +{ +void Init() +{ +#ifdef __LIBUSB__ + libusb_init(&s_libusb_context); +#endif +} + +void Shutdown() +{ +#ifdef __LIBUSB__ + libusb_exit(s_libusb_context); +#endif +} + +std::map, std::string> GetInsertedDevices() +{ + std::map, std::string> devices; + +#ifdef __LIBUSB__ + if (!s_libusb_context) + return devices; + + libusb_device** list; + const ssize_t cnt = libusb_get_device_list(s_libusb_context, &list); + for (ssize_t i = 0; i < cnt; ++i) + { + libusb_device_descriptor descr; + libusb_get_device_descriptor(list[i], &descr); + const std::pair vid_pid{descr.idVendor, descr.idProduct}; + devices[vid_pid] = GetDeviceName(vid_pid); + } + libusb_free_device_list(list, 1); +#endif + + return devices; +} + +std::string GetDeviceName(const std::pair vid_pid) +{ + const auto iter = s_wii_peripherals.find(vid_pid); + const std::string device_name = iter == s_wii_peripherals.cend() ? "Unknown" : iter->second; + return StringFromFormat("%04x:%04x - %s", vid_pid.first, vid_pid.second, device_name.c_str()); +} +} // namespace USBUtils diff --git a/Source/Core/UICommon/USBUtils.h b/Source/Core/UICommon/USBUtils.h new file mode 100644 index 0000000000..6ae778e8a4 --- /dev/null +++ b/Source/Core/UICommon/USBUtils.h @@ -0,0 +1,20 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "Common/CommonTypes.h" + +namespace USBUtils +{ +void Init(); +void Shutdown(); + +std::map, std::string> GetInsertedDevices(); +std::string GetDeviceName(std::pair vid_pid); +} // namespace USBUtils