Enhanced Raw Input 1.2
Enhanced Raw Input for Unreal Engine
Loading...
Searching...
No Matches
EnhancedRawInputWindows.h
1// (c) 2025 by Lemontree Softworks - All Rights Reserved.
2
3#pragma once
4
5// A little bit hacky but Unreal only defines WINVER with 0x0601 (Windows 7), but for cfgmgr32 (Hotplug detection) we need at leat Windows 8
6#if WINVER < 0x602 // Win8
7 #undef WINVER
8 #define WINVER 0x602
9#endif
10
11#include "Engine/Engine.h"
12#include "Modules/ModuleManager.h"
13#include "EnhancedRawInput.h"
14#include "EnhancedRawInputSettings.h"
15#include "Framework/Application/SlateApplication.h"
16#include "Windows/WindowsApplication.h"
17#include "GameFramework/HUD.h"
18#include "hidsdi.h"
19#include "cfgmgr32.h"
20
22constexpr auto MaxHidDevices = 16;
23
25constexpr auto MaxHidPovSwitches = 4;
26
27// See https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/hidclass-hardware-ids-for-top-level-collections
28constexpr auto HidUsagePage = 0x01;
29constexpr auto HardwareUsageJoystick = 0x04;
30constexpr auto HardwareUsageGamepad = 0x05;
31constexpr auto HidUsagePov = 0x39;
32
33DECLARE_DELEGATE_OneParam(FHidDeviceConnectedDelegate, FString /* InterfaceName */);
34
36struct ENHANCEDRAWINPUT_API FWindowsHidApi
37{
38public:
39 typedef BOOLEAN(*HidD_GetSerialNumberString_Type)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
40 typedef BOOLEAN(*HidD_GetManufacturerString_Type)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
41 typedef BOOLEAN(*HidD_GetProductString_Type)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength);
42 typedef NTSTATUS(*HidP_GetCaps_Type)(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities);
43 typedef NTSTATUS(*HidP_GetButtonCaps_Type)(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps, PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
44 typedef NTSTATUS(*HidP_GetValueCaps_Type)(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
45 typedef NTSTATUS(*HidP_GetUsages_Type)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
46 typedef NTSTATUS(*HidP_GetUsageValue_Type)(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PULONG UsageValue,PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
47 typedef NTSTATUS(*HidP_GetData_Type)(HIDP_REPORT_TYPE ReportType, PHIDP_DATA DataList, PULONG DataLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
48
49 FWindowsHidApi();
50 ~FWindowsHidApi();
51
52 HANDLE DllHandle = nullptr;
53
54 HidD_GetSerialNumberString_Type HidD_GetSerialNumberString;
55 HidD_GetManufacturerString_Type HidD_GetManufacturerString;
56 HidD_GetProductString_Type HidD_GetProductString;
57 HidP_GetCaps_Type HidP_GetCaps;
58 HidP_GetButtonCaps_Type HidP_GetButtonCaps;
59 HidP_GetValueCaps_Type HidP_GetValueCaps;
60 HidP_GetUsages_Type HidP_GetUsages;
61 HidP_GetUsageValue_Type HidP_GetUsageValue;
62 HidP_GetData_Type HidP_GetData;
63};
64
66struct ENHANCEDRAWINPUT_API FHidAxis
67{
68 FHidAxis() :
69 Value(0.0f),
70 KeyName(NAME_None),
71 bIsEnabled(false),
72 OutputType(ERawInputAxisOutputType::Gamepad),
73 Min(-1),
74 Max(-1),
75 Offset(0.0f),
76 bIsInverted(false),
77 bHasChanged(false)
78 {}
79
81 int32 Value;
82
84 FName KeyName;
85
88
90 ERawInputAxisOutputType OutputType;
91
93 int32 Min;
94
96 int32 Max;
97
99 float Offset;
100
103
106
109 float GetValue() const;
110
113 bool HasValue() const;
114};
115
117struct ENHANCEDRAWINPUT_API FHidButton
118{
119 FHidButton() :
120 bCurrentState(false),
121 bLastState(false),
122 KeyName(NAME_None),
123 bIsEnabled(false)
124 {}
127
130
132 FName KeyName;
133
136};
137
139struct ENHANCEDRAWINPUT_API FHidPov : FHidAxis
140{
141 FHidPov() : DataIndex(0), PovOutputType(ERawInputPovOutputType::POV)
142 {
143 CurrentButtonStates.Init(false, MaxHidPovSwitches);
144 LastButtonStates.Init(false, MaxHidPovSwitches);
145 ButtonKeyNames.Init(NAME_None, MaxHidPovSwitches);
146 }
147
149 uint16 DataIndex;
150
153
154 // @brief Sates of the virtual D-Pad Buttons
155 TArray<bool> LastButtonStates;
156
158 TArray<FName> ButtonKeyNames;
159
161 ERawInputPovOutputType PovOutputType;
162
165 int32 GetPovValueDeg() const;
166
168 void UpdateButtonValues();
169
172 float GetAxisValue() const;
173
177 bool HasButtonValue(uint32 Index) const;
178
181 bool HasAxisValue() const;
182};
183
185struct ENHANCEDRAWINPUT_API FHidDevice
186{
187 FHidDevice() :
188 Handle(nullptr),
189 DeviceInfo(0),
190 ControllerId(0),
191#ifdef MULTI_CONTROLLER_SUPPORT
193#endif
196 UserId(PLATFORMUSERID_NONE),
197 DeviceId(INPUTDEVICEID_NONE),
198 bIsActive(true),
199 ConnectionState(EInputDeviceConnectionState::Invalid)
200 {
201 }
202
204 HANDLE Handle;
205
207 TArray<uint8> PreParsedDataBuffer;
208
210 RID_DEVICE_INFO DeviceInfo;
211
214
217
220
223
226
229
231 FString ProductName;
232
235
237 FPlatformUserId UserId;
238
240 FInputDeviceId DeviceId;
241
244
246 EInputDeviceConnectionState ConnectionState;
247
249 TArray<FHidButton> Buttons;
250
252 TMap<int32, FHidAxis> Axis;
253
255 TArray<FHidPov> PoVs;
256};
257
259class ENHANCEDRAWINPUT_API FEnhancedRawInputWindows : public IEnhancedRawInput, IWindowsMessageHandler
260{
261 friend class UEnhancedRawInputSettings;
262 friend class UEnhancedRawInputLibrary;
263
264public:
265 FEnhancedRawInputWindows(const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler);
266 virtual ~FEnhancedRawInputWindows() override;
267
268 // Begin IEnhancedRawInput
269 virtual void SetBindings(const FString InterfaceName) override;
270 virtual void SetMultiControllerBinding(const int32 ControllerId, const FString InterfaceName);
271 virtual void SetAxisBinding(const FString InterfaceName, const int32 AxisUsage, const FName KeyName) override;
272 virtual void SetButtonBinding(const FString InterfaceName, const int32 ButtonIndex, const FName KeyName) override;
273 virtual void SetPovAxisBinding(const FString InterfaceName, const int32 PovIndex, FName KeyName) override;
274 virtual void SetPovButtonBinding(const FString InterfaceName, const int32 PovIndex, TArray<FName> KeyNames) override;
275 // End IEnhancedRawInput
276
277 // Begin IInputDevice interface
278 virtual void SetChannelValue(int32 ControllerId, FForceFeedbackChannelType ChannelType, float Value) override {}
279 virtual void SetChannelValues(int32 ControllerId, const FForceFeedbackValues &Values) override {}
280 virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override { return false; }
281 virtual void SetMessageHandler(const TSharedRef<FGenericApplicationMessageHandler> &InMessageHandler) override;
282 virtual void Tick(float DeltaTime) override;
283 virtual void SendControllerEvents() override;
284 virtual bool SupportsForceFeedback(int32 ControllerId) override { return false; }
285 // End IInputDevice interface
286
287 // Begin IWindowsMessageHandler interface
288 virtual bool ProcessMessage(HWND Hwnd, uint32 Msg, WPARAM WParam, LPARAM LParam, int32& OutResult) override;
289 // End IWindowsMessageHandler interface
290
292 void EnumerateDevices();
293
296 TArray<FHidDevice> GetConnectedDevices();
297
302 FHidDevice *FindDeviceByUserAndDeviceId(const FPlatformUserId UserId, const FInputDeviceId DeviceId);
303
306 FHidDevice* FindDeviceByInterfaceName(const FString& InterfaceName);
307
311 TMap<int32, FHidAxis> GetAxisInfo(const FString& InterfaceName);
312
316 TArray<FHidPov> GetPovInfo(const FString& InterfaceName);
317
321 void SetDeviceActivity(const FString& InterfaceName, bool bIsActive);
322
326 DWORD NotificationCallback(CM_NOTIFY_ACTION Action);
327
329 FHidDeviceConnectedDelegate HidDeviceConnectedHandler;
330
332 FHidDeviceConnectedDelegate HidDeviceDisconnectedHandler;
333
334private:
335 FWindowsHidApi HidApi;
336 typedef CONFIGRET(*CM_Register_Notification_Type)(PCM_NOTIFY_FILTER pFilter, PVOID pContext, PCM_NOTIFY_CALLBACK pCallback, PHCMNOTIFICATION pNotifyContext);
337 typedef CONFIGRET(*CM_Unregister_Notification)(HCMNOTIFICATION NotifyContext);
338
339 CM_Register_Notification_Type CmRegisterNotification;
340 CM_Unregister_Notification CmUnregisterNotification;
341 HANDLE Cfgmgr32DllHandle = nullptr;
342 HCMNOTIFICATION NotifyContext;
343
344 bool bRefreshDevices = false;
345 FDateTime DeviceRefreshStart;
346
347 bool bDeviceRegistered = false;
348 int32 LastMultiControllerID = -1;
349
350 FHidDevice HidDevices[MaxHidDevices];
351 TArray<FString> ActualConnectedDevices;
352
353
354
355 bool QueryDevices();
356 void QueryDeviceCaps(FHidDevice &Device) const;
357
358 FHidDevice *FindDeviceByHandle(HANDLE Handle);
359
360 void ShowDebug(AHUD* HUD, UCanvas* Canvas, const FDebugDisplayInfo& DisplayInfo, float& YL, float& YPos);
361
362 static bool TryRegisterInputDevice();
363
364 static bool IsMultiController(const FName& KeyName, const FHidDevice &Device);
365
366
367};
368
369typedef FEnhancedRawInputWindows FPlatformEnhancedRawInput;
Windows Implementation.
Definition EnhancedRawInputWindows.h:260
virtual void SetButtonBinding(const FString InterfaceName, const int32 ButtonIndex, const FName KeyName) override
Binds a controller button to a corresponding key.
Definition EnhancedRawInputWindows.cpp:1589
FHidDevice * FindDeviceByInterfaceName(const FString &InterfaceName)
Finds a device by provided interface name.
Definition EnhancedRawInputWindows.cpp:2367
virtual void SetBindings(const FString InterfaceName) override
Applies the key binding settings to the specified controller.
Definition EnhancedRawInputWindows.cpp:294
FHidDeviceConnectedDelegate HidDeviceConnectedHandler
Event when a HID device is connected.
Definition EnhancedRawInputWindows.h:329
FHidDevice * FindDeviceByUserAndDeviceId(const FPlatformUserId UserId, const FInputDeviceId DeviceId)
Finds a device by provided user and device ID.
Definition EnhancedRawInputWindows.cpp:2318
TArray< FHidPov > GetPovInfo(const FString &InterfaceName)
Returns information about all PoVs / Hat switches / D-PADs for a specific device.
Definition EnhancedRawInputWindows.cpp:2347
void SetDeviceActivity(const FString &InterfaceName, bool bIsActive)
Sets the activity of the device.
Definition EnhancedRawInputWindows.cpp:2358
virtual void SetPovAxisBinding(const FString InterfaceName, const int32 PovIndex, FName KeyName) override
Binds a controller POV axis to a corresponding key.
Definition EnhancedRawInputWindows.cpp:1608
TArray< FHidDevice > GetConnectedDevices()
Returns information about all currently connected devices.
Definition EnhancedRawInputWindows.cpp:2304
virtual void SetPovButtonBinding(const FString InterfaceName, const int32 PovIndex, TArray< FName > KeyNames) override
Binds a controller POV to a corresponding keys.
Definition EnhancedRawInputWindows.cpp:1627
void EnumerateDevices()
Updates the list of all connected controllers. Notifies the engine of any new or removed controllers.
Definition EnhancedRawInputWindows.cpp:2127
TMap< int32, FHidAxis > GetAxisInfo(const FString &InterfaceName)
Returns information about all axis for a specific device.
Definition EnhancedRawInputWindows.cpp:2336
DWORD NotificationCallback(CM_NOTIFY_ACTION Action)
Internal callback for hotplug detection, not for public use.
Definition EnhancedRawInputWindows.cpp:1673
FHidDeviceConnectedDelegate HidDeviceDisconnectedHandler
Event when a HID device is disconnected.
Definition EnhancedRawInputWindows.h:332
virtual void SetAxisBinding(const FString InterfaceName, const int32 AxisUsage, const FName KeyName) override
Binds a controller axis to a corresponding key.
Definition EnhancedRawInputWindows.cpp:1569
float Offset
Axis offset as configured.
Definition EnhancedRawInputWindows.h:99
int32 Max
Maximal value, as reported from the driver.
Definition EnhancedRawInputWindows.h:96
FName KeyName
Bound Key name.
Definition EnhancedRawInputWindows.h:84
int32 Min
Minimal value, as reported from the driver.
Definition EnhancedRawInputWindows.h:93
ERawInputAxisOutputType OutputType
Configured output type.
Definition EnhancedRawInputWindows.h:90
bool bIsInverted
Whether is axis inverted (from Configuration)
Definition EnhancedRawInputWindows.h:102
float GetValue() const
Value of this axis, normalised, inverted and/or in specific format, according to configuration.
Definition EnhancedRawInputWindows.cpp:49
bool bIsEnabled
TRUE if axis is enabled in settings.
Definition EnhancedRawInputWindows.h:87
bool HasValue() const
Whether this axis has valid value.
Definition EnhancedRawInputWindows.cpp:72
bool bHasChanged
Whether value has changed since last HID event.
Definition EnhancedRawInputWindows.h:105
int32 Value
Current value of this axis.
Definition EnhancedRawInputWindows.h:81
bool bIsEnabled
TRUE if button is enabled in settings.
Definition EnhancedRawInputWindows.h:135
bool bCurrentState
TRUE if button is pressed.
Definition EnhancedRawInputWindows.h:126
bool bLastState
TRUE if button is pressed.
Definition EnhancedRawInputWindows.h:129
FName KeyName
Bound Key name.
Definition EnhancedRawInputWindows.h:132
Stores information and data about a HID Device.
Definition EnhancedRawInputWindows.h:186
uint32 ButtonUsageMin
Internally used.
Definition EnhancedRawInputWindows.h:234
int32 ControllerId
Internal unique controller ID.
Definition EnhancedRawInputWindows.h:213
FPlatformUserId UserId
Current User ID for this device, as reported from Unreal engine.
Definition EnhancedRawInputWindows.h:237
bool bIsActive
Whether the device is active and being handled.
Definition EnhancedRawInputWindows.h:243
EInputDeviceConnectionState ConnectionState
Connection state for this device.
Definition EnhancedRawInputWindows.h:246
FInputDeviceId DeviceId
Current Device ID for this device, as reported from Unreal engine.
Definition EnhancedRawInputWindows.h:240
int32 MultiControllerId
Multi-controller Id.
Definition EnhancedRawInputWindows.h:216
FString InterfaceName
Interface name as reported from driver.
Definition EnhancedRawInputWindows.h:222
FString SerialNumber
Serial number as reported from driver, may be empty.
Definition EnhancedRawInputWindows.h:228
TArray< FHidPov > PoVs
Information about all PoVs for this device.
Definition EnhancedRawInputWindows.h:255
TArray< FHidButton > Buttons
Information about all buttons for this device.
Definition EnhancedRawInputWindows.h:249
int32 NumberInputValueCaps
Number of HID Value (Axis) capability's, internally used.
Definition EnhancedRawInputWindows.h:219
HANDLE Handle
Internal HID Handle.
Definition EnhancedRawInputWindows.h:204
TArray< uint8 > PreParsedDataBuffer
Pre parsed HID report descriptor. Used internally.
Definition EnhancedRawInputWindows.h:207
FString ProductName
Product name as reported from driver, may be empty.
Definition EnhancedRawInputWindows.h:231
RID_DEVICE_INFO DeviceInfo
Device info from driver, see https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-r...
Definition EnhancedRawInputWindows.h:210
TMap< int32, FHidAxis > Axis
Information about all axis for this device.
Definition EnhancedRawInputWindows.h:252
FString Manufacturer
Manufacturer name as reported from driver, may be empty.
Definition EnhancedRawInputWindows.h:225
bool HasAxisValue() const
Checks if axis is configured and has valid value.
Definition EnhancedRawInputWindows.cpp:155
ERawInputPovOutputType PovOutputType
Output type as configured.
Definition EnhancedRawInputWindows.h:161
float GetAxisValue() const
Returns (normalised, depends on output type) value.
Definition EnhancedRawInputWindows.cpp:119
void UpdateButtonValues()
Updates the virtual D-PAD buttons, internally used.
Definition EnhancedRawInputWindows.cpp:90
uint16 DataIndex
Data index, internally used.
Definition EnhancedRawInputWindows.h:149
int32 GetPovValueDeg() const
Get Value of this POV.
Definition EnhancedRawInputWindows.cpp:79
TArray< bool > CurrentButtonStates
Sates of the virtual D-Pad Buttons.
Definition EnhancedRawInputWindows.h:152
bool HasButtonValue(uint32 Index) const
Checks if a button is configured and has valid value.
Definition EnhancedRawInputWindows.cpp:150
TArray< FName > ButtonKeyNames
Keynames as configured.
Definition EnhancedRawInputWindows.h:158
Internal structure for function pointers to Windows APIs. Not for public use.
Definition EnhancedRawInputWindows.h:37