summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-12-23 17:01:44 -0500
committerGitHub <noreply@github.com>2025-12-23 17:01:44 -0500
commit4b086b1256855be85873b9cee5b2bdd4efb91caf (patch)
tree00157dd8667f75efccb627aa8f001998c508d70a /Source/Core/Common
parent0a3aac6d85d1e276755e4f1a4215eef567c1c85c (diff)
parentfc4cbf9c6fa76862b153d72baddde11edb8a3958 (diff)
Merge pull request #14223 from jordan-woyak/wmreal-windows-device-enumeration
HW/WiimoteReal: Cache the enumerated Wii remote HID interface list between calls to FindWiimoteHIDDevices.
Diffstat (limited to 'Source/Core/Common')
-rw-r--r--Source/Core/Common/WindowsDevice.cpp59
-rw-r--r--Source/Core/Common/WindowsDevice.h29
2 files changed, 88 insertions, 0 deletions
diff --git a/Source/Core/Common/WindowsDevice.cpp b/Source/Core/Common/WindowsDevice.cpp
index 4bbd213774..34a540ed7b 100644
--- a/Source/Core/Common/WindowsDevice.cpp
+++ b/Source/Core/Common/WindowsDevice.cpp
@@ -90,6 +90,65 @@ NullTerminatedStringList<WCHAR> GetDeviceInterfaceList(LPGUID iface_class_guid,
}
}
+static __callback DWORD OnDevicesChanged(_In_ HCMNOTIFICATION notify_handle, _In_opt_ PVOID context,
+ _In_ CM_NOTIFY_ACTION action,
+ _In_reads_bytes_(event_data_size)
+ PCM_NOTIFY_EVENT_DATA event_data,
+ _In_ DWORD event_data_size)
+{
+ auto& callback = *static_cast<DeviceChangeNotification::CallbackType*>(context);
+ switch (action)
+ {
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL:
+ callback(DeviceChangeNotification::EventType::Arrival);
+ break;
+ case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL:
+ callback(DeviceChangeNotification::EventType::Removal);
+ break;
+ default:
+ break;
+ }
+ return ERROR_SUCCESS;
+}
+
+DeviceChangeNotification::DeviceChangeNotification() = default;
+
+DeviceChangeNotification::~DeviceChangeNotification()
+{
+ Unregister();
+}
+
+void DeviceChangeNotification::Register(CallbackType callback)
+{
+ Unregister();
+ m_callback = std::move(callback);
+
+ CM_NOTIFY_FILTER notify_filter{
+ .cbSize = sizeof(notify_filter),
+ .FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE,
+ .u{.DeviceInterface{.ClassGuid = GUID_DEVINTERFACE_HID}},
+ };
+ const CONFIGRET cfg_rv =
+ CM_Register_Notification(&notify_filter, &m_callback, OnDevicesChanged, &m_notify_handle);
+ if (cfg_rv != CR_SUCCESS)
+ {
+ ERROR_LOG_FMT(COMMON, "CM_Register_Notification failed: {:x}", cfg_rv);
+ }
+}
+
+void DeviceChangeNotification::Unregister()
+{
+ if (m_notify_handle == nullptr)
+ return;
+
+ const CONFIGRET cfg_rv = CM_Unregister_Notification(m_notify_handle);
+ if (cfg_rv != CR_SUCCESS)
+ {
+ ERROR_LOG_FMT(COMMON, "CM_Unregister_Notification failed: {:x}", cfg_rv);
+ }
+ m_notify_handle = nullptr;
+}
+
} // namespace Common
#endif
diff --git a/Source/Core/Common/WindowsDevice.h b/Source/Core/Common/WindowsDevice.h
index 8c682ac850..78e8234c15 100644
--- a/Source/Core/Common/WindowsDevice.h
+++ b/Source/Core/Common/WindowsDevice.h
@@ -22,6 +22,8 @@
#include <cfgmgr32.h>
#include <devpropdef.h>
+#include "Common/Functional.h"
+
namespace Common
{
std::optional<std::wstring> GetDevNodeStringProperty(DEVINST device,
@@ -71,6 +73,33 @@ struct NullTerminatedStringList
NullTerminatedStringList<WCHAR> GetDeviceInterfaceList(LPGUID iface_class_guid, DEVINSTID device_id,
ULONG flags);
+class DeviceChangeNotification
+{
+public:
+ enum class EventType : bool
+ {
+ Arrival,
+ Removal,
+ };
+ using CallbackType = Common::MoveOnlyFunction<void(EventType)>;
+
+ DeviceChangeNotification();
+ ~DeviceChangeNotification();
+
+ // FYI: Currently hardcoded to a GUID_DEVINTERFACE_HID filter.
+ void Register(CallbackType callback);
+ void Unregister();
+
+ DeviceChangeNotification(const DeviceChangeNotification&) = delete;
+ DeviceChangeNotification(DeviceChangeNotification&&) = delete;
+ void operator=(const DeviceChangeNotification&) = delete;
+ void operator=(DeviceChangeNotification&&) = delete;
+
+private:
+ CallbackType m_callback{};
+ HCMNOTIFICATION m_notify_handle{nullptr};
+};
+
} // namespace Common
#endif