Much improved raw input device list.
2 using System.Runtime.InteropServices;
3 using System.Diagnostics;
4 using System.Windows.Forms;
10 /// Provide some utility functions for raw input handling.
17 /// <param name="aRawInputHandle"></param>
18 /// <param name="aRawInput"></param>
19 /// <param name="rawInputBuffer">Caller must free up memory on the pointer using Marshal.FreeHGlobal</param>
20 /// <returns></returns>
21 public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
24 rawInputBuffer = IntPtr.Zero;
29 uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
31 //Get the size of our raw input data.
32 Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
34 //Allocate a large enough buffer
35 rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
37 //Now read our RAWINPUT data
38 if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
44 aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
48 Debug.WriteLine("GetRawInputData failed!");
58 /// <param name="hDevice"></param>
59 /// <param name="deviceInfo"></param>
60 /// <returns></returns>
61 public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
64 IntPtr deviceInfoBuffer = IntPtr.Zero;
68 uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
69 deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
71 int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.RawInputDeviceInfoType.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
74 Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
79 deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
83 Debug.WriteLine("GetRawInputData failed!");
88 //Always executes, prevents memory leak
89 Marshal.FreeHGlobal(deviceInfoBuffer);
97 /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device.
99 /// <param name="device"></param>
100 /// <returns></returns>
101 public static IntPtr GetPreParsedData(IntPtr hDevice)
104 int result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize);
107 Debug.WriteLine("Failed to get raw input pre-parsed data size" + result + Marshal.GetLastWin32Error());
111 IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize);
112 result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, ppData, ref ppDataSize);
115 Debug.WriteLine("Failed to get raw input pre-parsed data" + result + Marshal.GetLastWin32Error());
124 /// <param name="device"></param>
125 /// <returns></returns>
126 public static string GetDeviceName(IntPtr device)
128 uint deviceNameSize = 256;
129 int result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize);
135 IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2); // size is the character count not byte count
138 result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, deviceName, ref deviceNameSize);
141 return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination
148 Marshal.FreeHGlobal(deviceName);
156 /// <param name="aTreeView"></param>
157 public static void PopulateDeviceList(TreeView aTreeView)
160 //Get our list of devices
161 RAWINPUTDEVICELIST[] ridList = null;
162 uint deviceCount = 0;
163 int res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount,(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
170 ridList = new RAWINPUTDEVICELIST[deviceCount];
171 res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
172 if (res != deviceCount)
178 //For each our device add a node to our treeview
179 foreach (RAWINPUTDEVICELIST device in ridList)
181 Hid.HidDevice hidDevice=new Hid.HidDevice(device.hDevice);
183 //Work out proper suffix for our device root node.
184 //That allows users to see in a glance what kind of device this is.
186 if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID)
189 if (Enum.IsDefined(typeof(Hid.UsagePage), hidDevice.Info.hid.usUsagePage))
191 //We know this usage page, add its name
192 Hid.UsagePage usagePage = (Hid.UsagePage)hidDevice.Info.hid.usUsagePage;
193 suffix += " ( " + usagePage.ToString() + ", ";
197 //We don't know this usage page, add its value
198 suffix += " ( 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + ", ";
202 //We don't know this usage page, add its value
203 suffix += "0x" + hidDevice.Info.hid.usUsage.ToString("X4") + " )";
205 else if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD)
207 suffix = " - Keyboard";
209 else if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEMOUSE)
214 TreeNode node = null;
215 if (hidDevice.Product != null && hidDevice.Product.Length > 1)
217 //Add the devices with a proper name at the top
218 node = aTreeView.Nodes.Insert(0, hidDevice.Name, hidDevice.Product + suffix);
222 //Add other once at the bottom
223 node = aTreeView.Nodes.Add(hidDevice.Name, "0x" + hidDevice.ProductId.ToString("X4") + suffix);
226 node.Nodes.Add("Manufacturer: " + hidDevice.Manufacturer);
227 node.Nodes.Add("Product ID: 0x" + hidDevice.ProductId.ToString("X4"));
228 node.Nodes.Add("Vendor ID: 0x" + hidDevice.VendorId.ToString("X4"));
229 node.Nodes.Add("Version: " + hidDevice.Version);
230 node.Nodes.Add(hidDevice.Info.dwType.ToString());
231 if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID)
233 node.Nodes.Add("UsagePage / UsageCollection: 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + " / 0x" + hidDevice.Info.hid.usUsage.ToString("X4"));
236 node.Nodes.Add(hidDevice.Name);