diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index cdcf5b5812..605b03817b 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -4,7 +4,9 @@ #include "Core/IOS/USB/Host.h" #include +#include #include +#include #include #include @@ -61,7 +63,11 @@ void USBHost::DoState(PointerWrap& p) std::shared_ptr USBHost::GetDeviceById(const u64 device_id) const { - return m_usb_scanner.GetDeviceById(device_id); + std::lock_guard lk(m_devices_mutex); + const auto it = m_devices.find(device_id); + if (it == m_devices.end()) + return nullptr; + return it->second; } void USBHost::OnDeviceChange(ChangeEvent event, std::shared_ptr changed_device) @@ -85,13 +91,22 @@ void USBHost::Update() void USBHost::DispatchHooks(const DeviceChangeHooks& hooks) { - for (const auto& hook : hooks) + std::lock_guard lk(m_devices_mutex); + + for (const auto& [device, event] : hooks) { INFO_LOG_FMT(IOS_USB, "{} - {} device: {:04x}:{:04x}", GetDeviceName(), - hook.second == ChangeEvent::Inserted ? "New" : "Removed", hook.first->GetVid(), - hook.first->GetPid()); - OnDeviceChange(hook.second, hook.first); + event == ChangeEvent::Inserted ? "New" : "Removed", device->GetVid(), + device->GetPid()); + + if (event == ChangeEvent::Inserted) + m_devices.emplace(device->GetId(), device); + else if (event == ChangeEvent::Removed) + m_devices.erase(device->GetId()); + + OnDeviceChange(event, device); } + if (!hooks.empty()) OnDeviceChangeEnd(); } diff --git a/Source/Core/Core/IOS/USB/Host.h b/Source/Core/Core/IOS/USB/Host.h index 196104bc1a..ab4e9e8c6d 100644 --- a/Source/Core/Core/IOS/USB/Host.h +++ b/Source/Core/Core/IOS/USB/Host.h @@ -4,7 +4,9 @@ #pragma once #include +#include #include +#include #include #include @@ -45,6 +47,9 @@ protected: std::optional HandleTransfer(std::shared_ptr device, u32 request, std::function submit) const; + std::map> m_devices; + mutable std::recursive_mutex m_devices_mutex; + USBScanner m_usb_scanner{this}; private: diff --git a/Source/Core/Core/IOS/USB/OH0/OH0.cpp b/Source/Core/Core/IOS/USB/OH0/OH0.cpp index 58eb344c8b..e0bb771c18 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0.cpp @@ -73,7 +73,7 @@ std::optional OH0::IOCtlV(const IOCtlVRequest& request) void OH0::DoState(PointerWrap& p) { - if (p.IsReadMode() && !m_usb_scanner.m_devices.empty()) + if (p.IsReadMode() && !m_devices.empty()) { Core::DisplayMessage("It is suggested that you unplug and replug all connected USB devices.", 5000); @@ -114,8 +114,8 @@ IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const const u8 interface_class = memory.Read_U8(request.in_vectors[1].address); u8 entries_count = 0; - std::lock_guard lk(m_usb_scanner.m_devices_mutex); - for (const auto& device : m_usb_scanner.m_devices) + std::lock_guard lk(m_devices_mutex); + for (const auto& device : m_devices) { if (entries_count >= max_entries_count) break; @@ -231,14 +231,13 @@ std::optional OH0::RegisterClassChangeHook(const IOCtlVRequest& reques bool OH0::HasDeviceWithVidPid(const u16 vid, const u16 pid) const { - return std::ranges::any_of(m_usb_scanner.m_devices, [=](const auto& device) { + return std::ranges::any_of(m_devices, [=](const auto& device) { return device.second->GetVid() == vid && device.second->GetPid() == pid; }); } void OH0::OnDeviceChange(const ChangeEvent event, std::shared_ptr device) { - std::lock_guard lk(m_usb_scanner.m_devices_mutex); if (event == ChangeEvent::Inserted) TriggerHook(m_insertion_hooks, {device->GetVid(), device->GetPid()}, IPC_SUCCESS); else if (event == ChangeEvent::Removed) @@ -259,10 +258,10 @@ void OH0::TriggerHook(std::map& hooks, T value, const ReturnCode return_ std::pair OH0::DeviceOpen(const u16 vid, const u16 pid) { - std::lock_guard lk(m_usb_scanner.m_devices_mutex); + std::lock_guard lk(m_devices_mutex); bool has_device_with_vid_pid = false; - for (const auto& device : m_usb_scanner.m_devices) + for (const auto& device : m_devices) { if (device.second->GetVid() != vid || device.second->GetPid() != pid) continue; diff --git a/Source/Core/Core/IOS/USB/USBScanner.h b/Source/Core/Core/IOS/USB/USBScanner.h index 5762beaeb2..c6594886ee 100644 --- a/Source/Core/Core/IOS/USB/USBScanner.h +++ b/Source/Core/Core/IOS/USB/USBScanner.h @@ -32,8 +32,6 @@ public: void WaitForFirstScan(); bool UpdateDevices(bool always_add_hooks = false); - std::shared_ptr GetDeviceById(u64 device_id) const; - enum class ChangeEvent { Inserted, @@ -41,9 +39,6 @@ public: }; using DeviceChangeHooks = std::map, ChangeEvent>; - std::map> m_devices; - mutable std::mutex m_devices_mutex; - private: bool AddDevice(std::unique_ptr device); bool AddNewDevices(std::set& new_devices, DeviceChangeHooks& hooks, bool always_add_hooks); @@ -53,6 +48,11 @@ private: void CheckAndAddDevice(std::unique_ptr device, std::set& new_devices, DeviceChangeHooks& hooks, bool always_add_hooks); + std::shared_ptr GetDeviceById(u64 device_id) const; + + std::map> m_devices; + mutable std::mutex m_devices_mutex; + USBHost* m_host = nullptr; Common::Flag m_thread_running; std::thread m_thread; diff --git a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp index 3214d7e771..f20928eba0 100644 --- a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp +++ b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp @@ -207,10 +207,10 @@ void USB_HIDv4::TriggerDeviceChangeReply() auto& memory = system.GetMemory(); { - std::lock_guard lk(m_usb_scanner.m_devices_mutex); + std::lock_guard lk(m_devices_mutex); const u32 dest = m_devicechange_hook_request->buffer_out; u32 offset = 0; - for (const auto& device : m_usb_scanner.m_devices) + for (const auto& device : m_devices) { const std::vector device_section = GetDeviceEntry(*device.second.get()); if (offset + device_section.size() > m_devicechange_hook_request->buffer_out_size - 1)