From 7e7b0971ab014467ce6c2fccdd29bc9070eb333c Mon Sep 17 00:00:00 2001 From: Pablo Stebler Date: Mon, 14 Mar 2022 22:32:30 +0100 Subject: [PATCH] USBv5: Fix racy device change behavior This prevents the device changes happening between 2 GETDEVICECHANGE calls from being missed by the application. --- Source/Core/Core/IOS/USB/USBV5.cpp | 12 ++++++++---- Source/Core/Core/IOS/USB/USBV5.h | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/IOS/USB/USBV5.cpp b/Source/Core/Core/IOS/USB/USBV5.cpp index b8db618f66..9d429a6bd0 100644 --- a/Source/Core/Core/IOS/USB/USBV5.cpp +++ b/Source/Core/Core/IOS/USB/USBV5.cpp @@ -85,7 +85,7 @@ struct DeviceEntry void USBV5ResourceManager::DoState(PointerWrap& p) { - p.Do(m_devicechange_first_call); + p.Do(m_has_pending_changes); u32 hook_address = m_devicechange_hook_request ? m_devicechange_hook_request->address : 0; p.Do(hook_address); if (hook_address != 0) @@ -119,11 +119,12 @@ std::optional USBV5ResourceManager::GetDeviceChange(const IOCtlRequest std::lock_guard lk{m_devicechange_hook_address_mutex}; m_devicechange_hook_request = std::make_unique(request.address); - // On the first call, the reply is sent immediately (instead of on device insertion/removal) - if (m_devicechange_first_call) + // If there are pending changes, the reply is sent immediately (instead of on device + // insertion/removal). + if (m_has_pending_changes) { TriggerDeviceChangeReply(); - m_devicechange_first_call = false; + m_has_pending_changes = false; } return std::nullopt; } @@ -226,7 +227,10 @@ void USBV5ResourceManager::OnDeviceChangeEnd() void USBV5ResourceManager::TriggerDeviceChangeReply() { if (!m_devicechange_hook_request) + { + m_has_pending_changes = true; return; + } std::lock_guard lock{m_usbv5_devices_mutex}; u8 num_devices = 0; diff --git a/Source/Core/Core/IOS/USB/USBV5.h b/Source/Core/Core/IOS/USB/USBV5.h index 658efd2655..733e90c1ab 100644 --- a/Source/Core/Core/IOS/USB/USBV5.h +++ b/Source/Core/Core/IOS/USB/USBV5.h @@ -89,7 +89,7 @@ protected: void TriggerDeviceChangeReply(); virtual bool HasInterfaceNumberInIDs() const = 0; - bool m_devicechange_first_call = true; + bool m_has_pending_changes = true; std::mutex m_devicechange_hook_address_mutex; std::unique_ptr m_devicechange_hook_request;