From f5a3aac8e1ef77c3f1c1e30f47e15222752a538b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 6 Feb 2017 22:09:43 +0100 Subject: [PATCH 1/4] IOS: Check if libusb can be used instead of asserting This prevents panic alerts from showing up three times when starting Wii emulation whenever libusb could not be initialized. The user has already seen a warning at startup -- no need to warn them 3 more times. --- Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp | 5 +- Source/Core/Core/IOS/USB/Host.cpp | 50 ++++++++++--------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index 0e7267b614..72d536fd3a 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -61,8 +61,6 @@ BluetoothReal::BluetoothReal(u32 device_id, const std::string& device_name) : BluetoothBase(device_id, device_name) { m_libusb_context = LibusbContext::Get(); - _assert_msg_(IOS_WIIMOTE, m_libusb_context, "Failed to init libusb."); - LoadLinkKeys(); } @@ -84,6 +82,9 @@ BluetoothReal::~BluetoothReal() ReturnCode BluetoothReal::Open(const OpenRequest& request) { + if (!m_libusb_context) + return IPC_EACCES; + libusb_device** list; const ssize_t cnt = libusb_get_device_list(m_libusb_context.get(), &list); _dbg_assert_msg_(IOS, cnt > 0, "Couldn't get device list"); diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index 875dc451f1..80c19e34fa 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -32,7 +32,6 @@ USBHost::USBHost(u32 device_id, const std::string& device_name) : Device(device_ { #ifdef __LIBUSB__ m_libusb_context = LibusbContext::Get(); - _assert_msg_(IOS_USB, m_libusb_context, "Failed to init libusb."); #endif } @@ -117,31 +116,36 @@ bool USBHost::AddNewDevices(std::set& new_devices, DeviceChangeHooks& hooks const bool always_add_hooks) { #ifdef __LIBUSB__ - libusb_device** list; - const ssize_t count = libusb_get_device_list(m_libusb_context.get(), &list); - if (count < 0) + if (m_libusb_context) { - WARN_LOG(IOS_USB, "Failed to get device list: %s", libusb_error_name(static_cast(count))); - return false; - } + libusb_device** list; + const ssize_t count = libusb_get_device_list(m_libusb_context.get(), &list); + if (count < 0) + { + WARN_LOG(IOS_USB, "Failed to get device list: %s", + libusb_error_name(static_cast(count))); + return false; + } - for (ssize_t i = 0; i < count; ++i) - { - libusb_device* device = list[i]; - libusb_device_descriptor descriptor; - libusb_get_device_descriptor(device, &descriptor); - if (!SConfig::GetInstance().IsUSBDeviceWhitelisted({descriptor.idVendor, descriptor.idProduct})) - continue; + for (ssize_t i = 0; i < count; ++i) + { + libusb_device* device = list[i]; + libusb_device_descriptor descriptor; + libusb_get_device_descriptor(device, &descriptor); + if (!SConfig::GetInstance().IsUSBDeviceWhitelisted( + {descriptor.idVendor, descriptor.idProduct})) + continue; - auto usb_device = std::make_unique(device, descriptor); - if (!ShouldAddDevice(*usb_device)) - continue; - const u64 id = usb_device->GetId(); - new_devices.insert(id); - if (AddDevice(std::move(usb_device)) || always_add_hooks) - hooks.emplace(GetDeviceById(id), ChangeEvent::Inserted); + auto usb_device = std::make_unique(device, descriptor); + if (!ShouldAddDevice(*usb_device)) + continue; + const u64 id = usb_device->GetId(); + new_devices.insert(id); + if (AddDevice(std::move(usb_device)) || always_add_hooks) + hooks.emplace(GetDeviceById(id), ChangeEvent::Inserted); + } + libusb_free_device_list(list, 1); } - libusb_free_device_list(list, 1); #endif return true; } @@ -195,7 +199,7 @@ void USBHost::StartThreads() } #ifdef __LIBUSB__ - if (!m_event_thread_running.IsSet()) + if (m_libusb_context && !m_event_thread_running.IsSet()) { m_event_thread_running.Set(); m_event_thread = std::thread([this] { From db7ee668ff205de373d9463fc485bc560acf8e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 6 Feb 2017 22:19:47 +0100 Subject: [PATCH 2/4] Notify user that USB won't work if libusb init fails --- Source/Core/Common/LibusbContext.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Core/Common/LibusbContext.cpp b/Source/Core/Common/LibusbContext.cpp index a2ed128200..1eb729c4a0 100644 --- a/Source/Core/Common/LibusbContext.cpp +++ b/Source/Core/Common/LibusbContext.cpp @@ -8,6 +8,7 @@ #include "Common/LibusbContext.h" #include "Common/MsgHandler.h" +#include "Common/StringUtil.h" namespace LibusbContext { @@ -24,10 +25,12 @@ static libusb_context* Create() #ifdef _WIN32 is_windows = true; #endif - if (is_windows && ret == LIBUSB_ERROR_NOT_FOUND) - PanicAlertT("Failed to initialize libusb because usbdk is not installed."); - else - PanicAlertT("Failed to initialize libusb: %s", libusb_error_name(ret)); + const std::string reason = + is_windows && ret == LIBUSB_ERROR_NOT_FOUND ? + GetStringT("Failed to initialize libusb because usbdk is not installed.") : + StringFromFormat(GetStringT("Failed to initialize libusb (%s).").c_str(), + libusb_error_name(ret)); + PanicAlertT("%s\nSome USB features will not work.", reason.c_str()); return nullptr; } return context; From 6a0bf24e0b9c479eacbf1fd721233ace64057356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 6 Feb 2017 23:04:14 +0100 Subject: [PATCH 3/4] Move libusb context initialization to on first use This prevents libusb warnings from showing up even when the user is not using Bluetooth or USB passthrough, or the Wii U GC adapter. --- Source/Core/InputCommon/GCAdapter.cpp | 18 ++++++------------ Source/Core/UICommon/UICommon.cpp | 2 -- Source/Core/UICommon/USBUtils.cpp | 17 +++-------------- Source/Core/UICommon/USBUtils.h | 3 --- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index c16b1ce635..1baaceee12 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -170,17 +170,8 @@ void Init() s_libusb_driver_not_supported = false; - s_libusb_context = LibusbContext::Get(); - if (!s_libusb_context) - { - s_libusb_driver_not_supported = true; - Shutdown(); - } - else - { - if (UseAdapter()) - StartScanThread(); - } + if (UseAdapter()) + StartScanThread(); } void StartScanThread() @@ -188,6 +179,9 @@ void StartScanThread() if (s_adapter_detect_thread_running.IsSet()) return; + s_libusb_context = LibusbContext::Get(); + if (!s_libusb_context) + return; s_adapter_detect_thread_running.Set(true); s_adapter_detect_thread = std::thread(ScanThreadFunc); } @@ -334,7 +328,7 @@ void Shutdown() { StopScanThread(); #if defined(LIBUSB_API_VERSION) && LIBUSB_API_VERSION >= 0x01000102 - if (s_libusb_hotplug_enabled) + if (s_libusb_context && s_libusb_hotplug_enabled) libusb_hotplug_deregister_callback(s_libusb_context.get(), s_hotplug_handle); #endif Reset(); diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 8de73bd151..0842d511bf 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -30,7 +30,6 @@ void Init() VideoBackendBase::PopulateList(); WiimoteReal::LoadSettings(); GCAdapter::Init(); - USBUtils::Init(); VideoBackendBase::ActivateBackend(SConfig::GetInstance().m_strVideoBackend); SetEnableAlert(SConfig::GetInstance().bUsePanicHandlers); @@ -42,7 +41,6 @@ void Shutdown() WiimoteReal::Shutdown(); VideoBackendBase::ClearList(); SConfig::Shutdown(); - USBUtils::Shutdown(); LogManager::Shutdown(); } diff --git a/Source/Core/UICommon/USBUtils.cpp b/Source/Core/UICommon/USBUtils.cpp index da7c603580..4fbabda856 100644 --- a/Source/Core/UICommon/USBUtils.cpp +++ b/Source/Core/UICommon/USBUtils.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #ifdef __LIBUSB__ #include @@ -14,6 +15,7 @@ #include "UICommon/USBUtils.h" #ifdef __LIBUSB__ +static std::once_flag s_tried_libusb_init; static std::shared_ptr s_libusb_context; #endif @@ -36,25 +38,12 @@ static const std::map, std::string> s_wii_peripherals = {{ namespace USBUtils { -void Init() -{ -#ifdef __LIBUSB__ - s_libusb_context = LibusbContext::Get(); -#endif -} - -void Shutdown() -{ -#ifdef __LIBUSB__ - s_libusb_context = nullptr; -#endif -} - std::map, std::string> GetInsertedDevices() { std::map, std::string> devices; #ifdef __LIBUSB__ + std::call_once(s_tried_libusb_init, []() { s_libusb_context = LibusbContext::Get(); }); if (!s_libusb_context) return devices; diff --git a/Source/Core/UICommon/USBUtils.h b/Source/Core/UICommon/USBUtils.h index 6ae778e8a4..84d54a5381 100644 --- a/Source/Core/UICommon/USBUtils.h +++ b/Source/Core/UICommon/USBUtils.h @@ -12,9 +12,6 @@ namespace USBUtils { -void Init(); -void Shutdown(); - std::map, std::string> GetInsertedDevices(); std::string GetDeviceName(std::pair vid_pid); } // namespace USBUtils From b6d526ba2e94e1bcb155c7d6b2eee7833e3ae81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 6 Feb 2017 23:42:29 +0100 Subject: [PATCH 4/4] IOS: Do not init libusb unless passthrough is enabled --- Source/Core/Core/IOS/USB/Host.cpp | 29 ++++++++++++++++++++++------- Source/Core/Core/IOS/USB/Host.h | 1 - 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index 80c19e34fa..226c107eb0 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -30,9 +30,6 @@ namespace Device { USBHost::USBHost(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { -#ifdef __LIBUSB__ - m_libusb_context = LibusbContext::Get(); -#endif } ReturnCode USBHost::Open(const OpenRequest& request) @@ -116,10 +113,14 @@ bool USBHost::AddNewDevices(std::set& new_devices, DeviceChangeHooks& hooks const bool always_add_hooks) { #ifdef __LIBUSB__ - if (m_libusb_context) + if (SConfig::GetInstance().m_usb_passthrough_devices.empty()) + return true; + + auto libusb_context = LibusbContext::Get(); + if (libusb_context) { libusb_device** list; - const ssize_t count = libusb_get_device_list(m_libusb_context.get(), &list); + const ssize_t count = libusb_get_device_list(libusb_context.get(), &list); if (count < 0) { WARN_LOG(IOS_USB, "Failed to get device list: %s", @@ -199,15 +200,29 @@ void USBHost::StartThreads() } #ifdef __LIBUSB__ - if (m_libusb_context && !m_event_thread_running.IsSet()) + if (!m_event_thread_running.IsSet()) { m_event_thread_running.Set(); m_event_thread = std::thread([this] { Common::SetCurrentThreadName("USB Passthrough Thread"); + std::shared_ptr context; while (m_event_thread_running.IsSet()) { + if (SConfig::GetInstance().m_usb_passthrough_devices.empty()) + { + Common::SleepCurrentThread(50); + continue; + } + + if (!context) + context = LibusbContext::Get(); + + // If we failed to get a libusb context, stop the thread. + if (!context) + return; + static timeval tv = {0, 50000}; - libusb_handle_events_timeout_completed(m_libusb_context.get(), &tv, nullptr); + libusb_handle_events_timeout_completed(context.get(), &tv, nullptr); } }); } diff --git a/Source/Core/Core/IOS/USB/Host.h b/Source/Core/Core/IOS/USB/Host.h index 40c09ca709..27d94d805f 100644 --- a/Source/Core/Core/IOS/USB/Host.h +++ b/Source/Core/Core/IOS/USB/Host.h @@ -71,7 +71,6 @@ private: void DispatchHooks(const DeviceChangeHooks& hooks); #ifdef __LIBUSB__ - std::shared_ptr m_libusb_context; // Event thread for libusb Common::Flag m_event_thread_running; std::thread m_event_thread;