Skip to content

Commit 8f9f3a7

Browse files
committed
Define Setup device object as base class to HID device
In fact not all Setup devices are HID devices. However all HID devices are Setup devices.
1 parent e6b23ae commit 8f9f3a7

File tree

5 files changed

+160
-19
lines changed

5 files changed

+160
-19
lines changed

Project/Hid/CsWin32.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,42 @@ class K
1616
{
1717
public static readonly Foundation.BOOLEAN TRUE = new Foundation.BOOLEAN(1);
1818
public static readonly Foundation.BOOLEAN FALSE = new Foundation.BOOLEAN(0);
19+
//public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1L);
20+
public static readonly uint INVALID_HANDLE_VALUE = uint.MaxValue;
1921
}
2022

2123

24+
25+
2226
namespace Devices.DeviceAndDriverInstallation
2327
{
28+
29+
[Flags]
30+
public enum DEVICEINFOGETCLASS_FLAGS : uint
31+
{
32+
// Flags controlling what is included in the device information set built by SetupDiGetClassDevs
33+
DIGCF_DEFAULT = 0x00000001, // only valid with DIGCF_DEVICEINTERFACE
34+
DIGCF_PRESENT = 0x00000002,
35+
DIGCF_ALLCLASSES = 0x00000004,
36+
DIGCF_PROFILE = 0x00000008,
37+
DIGCF_DEVICEINTERFACE = 0x00000010
38+
}
39+
40+
/// <summary>
41+
///
42+
/// </summary>
43+
public partial struct SP_DEVINFO_DATA
44+
{
45+
unsafe public SP_DEVINFO_DATA(bool aValid = true)
46+
{
47+
cbSize = (uint)sizeof(SP_DEVINFO_DATA);
48+
ClassGuid = Guid.Empty;
49+
DevInst = K.INVALID_HANDLE_VALUE;
50+
//DevInst = 0;
51+
Reserved = 0;
52+
}
53+
}
54+
2455
/// <summary>
2556
/// We used that as a fixed size buffer to be cast into SP_DEVICE_INTERFACE_DETAIL_DATA_W
2657
/// See: https://github.com/microsoft/CsWin32/discussions/589

Project/Hid/HidDevice.cs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,14 @@ namespace SharpLib.Hid
3131
/// Represent a HID device.
3232
/// Rename to RawInputDevice?
3333
/// </summary>
34-
public class Device: IDisposable
34+
public class Device: Setup.Device
3535
{
3636
/// <summary>
3737
/// Unique name of that HID device.
3838
/// Notably used as input to CreateFile.
3939
/// You can derive the device instance path AKA instance id from it.
4040
/// </summary>
4141
public string Name { get; private set; }
42-
43-
/// <summary>
44-
/// Instance path uniquely identifies a device.
45-
/// Can be used as input to SetupDiGetClassDevs to retrieve device handles and from there other properties.
46-
/// </summary>
47-
public string InstancePath { get; private set; }
4842

4943
/// <summary>
5044
/// Friendly name that people should be able to read.
@@ -95,15 +89,6 @@ public Device(IntPtr hRawInputDevice)
9589
}
9690
}
9791

98-
99-
/// <summary>
100-
/// Make sure dispose is called even if the user forgot about it.
101-
/// </summary>
102-
~Device()
103-
{
104-
Dispose();
105-
}
106-
10792
/// <summary>
10893
/// Private constructor.
10994
/// </summary>
@@ -352,8 +337,9 @@ private void SetFriendlyName()
352337
/// Make sure calling disposed multiple times does not crash.
353338
/// See: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238
354339
/// </summary>
355-
public void Dispose()
340+
public override void Dispose()
356341
{
342+
base.Dispose();
357343
Marshal.FreeHGlobal(PreParsedData);
358344
PreParsedData = IntPtr.Zero;
359345
}

Project/Hid/HidUtils.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ namespace SharpLib.Win32
127127
{
128128
using SharpLib.ToEnum;
129129
using Windows.Win32.Foundation;
130+
using System.ComponentModel;
131+
using System.Diagnostics;
130132
public static class GetLastError
131133
{
132134
public static string String()
@@ -136,9 +138,30 @@ public static string String()
136138

137139
public static WIN32_ERROR Enum()
138140
{
139-
int err = Marshal.GetLastWin32Error();
141+
int err = Int();
140142
return err.ToEnum<WIN32_ERROR>();
141143
}
142144

145+
public static int Int()
146+
{
147+
return Marshal.GetLastWin32Error();
148+
}
149+
150+
public static void Throw()
151+
{
152+
throw new Win32Exception(Int(),String());
153+
}
154+
155+
public static void Log(string aPrefix="")
156+
{
157+
Trace.WriteLine(aPrefix + ".GetLastError: " + String());
158+
}
159+
160+
public static void LogAndThrow(string aPrefix = "")
161+
{
162+
Log(aPrefix);
163+
Throw();
164+
}
165+
143166
}
144167
}

Project/Hid/NativeMethods.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ RID_DEVICE_INFO
1919

2020

2121
DEVPKEY*
22-
DIGCF*
22+
//DIGCF*
2323
ERROR*
2424
//ERROR_NO_MORE_ITEMS
25+
26+
//INVALID_HANDLE_VALUE
27+

Project/Hid/Setup/Device.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
/// <summary>
7+
/// TODO: Move it to another project SharpLibSetup
8+
/// </summary>
9+
namespace SharpLib.Setup
10+
{
11+
12+
using Windows.Win32;
13+
using Windows.Win32.Foundation;
14+
using Windows.Win32.Devices.DeviceAndDriverInstallation;
15+
using SharpLib.Win32;
16+
using System.Diagnostics;
17+
using System.ComponentModel;
18+
19+
/// <summary>
20+
/// A setup device is identified by the set it belongs to (HDEVINFO) and its informations data (SP_DEVINFO_DATA).
21+
/// <see href="https://docs.microsoft.com/en-us/windows-hardware/drivers/install/device-information-sets"/>
22+
/// <see cref="Windows.Win32.Devices.DeviceAndDriverInstallation.HDEVINFO"/>
23+
/// <see cref="Windows.Win32.SetupDiDestroyDeviceInfoListSafeHandle"/>
24+
/// <see cref="Windows.Win32.Devices.DeviceAndDriverInstallation.SP_DEVINFO_DATA"/>
25+
/// </summary>
26+
public class Device : IDisposable
27+
{
28+
29+
SetupDiDestroyDeviceInfoListSafeHandle iDevInfo;
30+
SP_DEVINFO_DATA iDevInfoData = new SP_DEVINFO_DATA(true);
31+
string iInstancePath;
32+
33+
/// <summary>
34+
/// Instance path uniquely identifies a device.
35+
/// Can be used as input to SetupDiGetClassDevs to retrieve device handles and from there other properties.
36+
/// </summary>
37+
public string InstancePath
38+
{
39+
get { return iInstancePath; }
40+
protected set
41+
{
42+
unsafe
43+
{
44+
iInstancePath = value;
45+
// Get our device information set handle, that set though should contain only this device instance really
46+
iDevInfo = PInvoke.SetupDiGetClassDevs(null, iInstancePath, new HWND(0), (uint)(DEVICEINFOGETCLASS_FLAGS.DIGCF_ALLCLASSES | DEVICEINFOGETCLASS_FLAGS.DIGCF_DEVICEINTERFACE));
47+
if (iDevInfo.IsInvalid)
48+
{
49+
//GetLastError.Log();
50+
//return;
51+
GetLastError.LogAndThrow("SetupDiGetClassDevs");
52+
}
53+
54+
uint index = 0;
55+
// Get our device information data
56+
fixed (SP_DEVINFO_DATA* ptrDevInfoData = &iDevInfoData) // Needed for data members apparently
57+
{
58+
if (!PInvoke.SetupDiEnumDeviceInfo(iDevInfo, index++, ptrDevInfoData))
59+
{
60+
GetLastError.LogAndThrow("SetupDiEnumDeviceInfo");
61+
}
62+
}
63+
64+
// Make sure we only have one item in our list
65+
SP_DEVINFO_DATA discard = new SP_DEVINFO_DATA(true);
66+
if (PInvoke.SetupDiEnumDeviceInfo(iDevInfo, index++, &discard))
67+
{
68+
throw new ArgumentException("More than one device in our information set");
69+
//GetLastError.LogAndThrow("SetupDiEnumDeviceInfo");
70+
}
71+
}
72+
}
73+
}
74+
75+
76+
/// <summary>
77+
/// Make sure dispose is called even if the user forgot about it.
78+
/// </summary>
79+
~Device()
80+
{
81+
Dispose();
82+
}
83+
84+
85+
/// <summary>
86+
/// Dispose is just for unmanaged clean-up.
87+
/// Make sure calling disposed multiple times does not crash.
88+
/// See: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238
89+
/// </summary>
90+
public virtual void Dispose()
91+
{
92+
}
93+
94+
95+
96+
97+
}
98+
}

0 commit comments

Comments
 (0)