-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathRawInputDevice.cs
130 lines (105 loc) · 4.4 KB
/
RawInputDevice.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.Linq;
using Linearstar.Windows.RawInput.Native;
namespace Linearstar.Windows.RawInput;
public abstract class RawInputDevice
{
string? productName;
string? manufacturerName;
protected RawInputDeviceInfo DeviceInfo { get; }
public RawInputDeviceHandle Handle { get; }
public RawInputDeviceType DeviceType => DeviceInfo.Type;
public string? DevicePath { get; }
public string? ManufacturerName
{
get
{
if (manufacturerName == null) GetAttributes();
return manufacturerName;
}
}
public string? ProductName
{
get
{
if (productName == null) GetAttributes();
return productName;
}
}
public bool IsConnected =>
DevicePath != null && CfgMgr32.TryLocateDevNode(DevicePath, CfgMgr32.LocateDevNodeFlags.Normal, out _) == ConfigReturnValue.Success;
public abstract HidUsageAndPage UsageAndPage { get; }
public abstract int VendorId { get; }
public abstract int ProductId { get; }
void GetAttributes()
{
if (DevicePath == null) return;
if (manufacturerName == null || productName == null) GetAttributesFromHidD();
if (manufacturerName == null || productName == null) GetAttributesFromCfgMgr();
}
void GetAttributesFromHidD()
{
if (DevicePath == null || !HidD.TryOpenDevice(DevicePath, out var device)) return;
try
{
manufacturerName ??= HidD.GetManufacturerString(device);
productName ??= HidD.GetProductString(device);
}
finally
{
HidD.CloseDevice(device);
}
}
void GetAttributesFromCfgMgr()
{
if (DevicePath == null) return;
var path = DevicePath.Substring(4).Replace('#', '\\');
if (path.Contains("{")) path = path.Substring(0, path.IndexOf('{') - 1);
var device = CfgMgr32.LocateDevNode(path, CfgMgr32.LocateDevNodeFlags.Phantom);
manufacturerName ??= CfgMgr32.GetDevNodePropertyString(device, in DevicePropertyKey.DeviceManufacturer);
productName ??= CfgMgr32.GetDevNodePropertyString(device, in DevicePropertyKey.DeviceFriendlyName);
productName ??= CfgMgr32.GetDevNodePropertyString(device, in DevicePropertyKey.Name);
}
protected RawInputDevice(RawInputDeviceHandle device, RawInputDeviceInfo deviceInfo)
{
Handle = device;
DevicePath = User32.GetRawInputDeviceName(device);
DeviceInfo = deviceInfo;
}
public static RawInputDevice FromHandle(RawInputDeviceHandle device)
{
var deviceInfo = User32.GetRawInputDeviceInfo(device);
switch (deviceInfo.Type)
{
case RawInputDeviceType.Mouse:
return new RawInputMouse(device, deviceInfo);
case RawInputDeviceType.Keyboard:
return new RawInputKeyboard(device, deviceInfo);
case RawInputDeviceType.Hid:
return RawInputDigitizer.IsSupported(deviceInfo.Hid.UsageAndPage)
? new RawInputDigitizer(device, deviceInfo)
: new RawInputHid(device, deviceInfo);
default:
throw new ArgumentException();
}
}
/// <summary>
/// Gets available devices that can be handled with Raw Input.
/// </summary>
/// <returns>Array of <see cref="RawInputDevice"/>, which contains mouse as a <see cref="RawInputMouse"/>, keyboard as a <see cref="RawInputKeyboard"/>, and any other HIDs as a <see cref="RawInputHid"/>.</returns>
public static RawInputDevice[] GetDevices()
{
var devices = User32.GetRawInputDeviceList();
return devices.Select(i => FromHandle(i.Device)).ToArray();
}
public byte[] GetPreparsedData() =>
User32.GetRawInputDevicePreparsedData(Handle);
public static void RegisterDevice(HidUsageAndPage usageAndPage, RawInputDeviceFlags flags, IntPtr hWndTarget) =>
RegisterDevice(new RawInputDeviceRegistration(usageAndPage, flags, hWndTarget));
public static void RegisterDevice(params RawInputDeviceRegistration[] devices) =>
User32.RegisterRawInputDevices(devices);
public static void UnregisterDevice(HidUsageAndPage usageAndPage) =>
RegisterDevice(usageAndPage, RawInputDeviceFlags.Remove, IntPtr.Zero);
public static RawInputDeviceRegistration[] GetRegisteredDevices() =>
User32.GetRegisteredRawInputDevices();
}