1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Win32/RawInput.cs Sun Mar 15 20:25:58 2015 +0100
1.3 @@ -0,0 +1,250 @@
1.4 +//
1.5 +// Copyright (C) 2014-2015 Stéphane Lenclud.
1.6 +//
1.7 +// This file is part of SharpLibHid.
1.8 +//
1.9 +// SharpDisplayManager is free software: you can redistribute it and/or modify
1.10 +// it under the terms of the GNU General Public License as published by
1.11 +// the Free Software Foundation, either version 3 of the License, or
1.12 +// (at your option) any later version.
1.13 +//
1.14 +// SharpDisplayManager is distributed in the hope that it will be useful,
1.15 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 +// GNU General Public License for more details.
1.18 +//
1.19 +// You should have received a copy of the GNU General Public License
1.20 +// along with SharpDisplayManager. If not, see <http://www.gnu.org/licenses/>.
1.21 +//
1.22 +
1.23 +using System;
1.24 +using System.Runtime.InteropServices;
1.25 +using System.Diagnostics;
1.26 +using System.Windows.Forms;
1.27 +
1.28 +namespace SharpLib.Win32
1.29 +{
1.30 + /// <summary>
1.31 + /// Provide some utility functions for raw input handling.
1.32 + /// </summary>
1.33 + static public class RawInput
1.34 + {
1.35 + /// <summary>
1.36 + ///
1.37 + /// </summary>
1.38 + /// <param name="aRawInputHandle"></param>
1.39 + /// <param name="aRawInput"></param>
1.40 + /// <param name="rawInputBuffer">Caller must free up memory on the pointer using Marshal.FreeHGlobal</param>
1.41 + /// <returns></returns>
1.42 + public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
1.43 + {
1.44 + bool success = true;
1.45 + rawInputBuffer = IntPtr.Zero;
1.46 +
1.47 + try
1.48 + {
1.49 + uint dwSize = 0;
1.50 + uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
1.51 +
1.52 + //Get the size of our raw input data.
1.53 + Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
1.54 +
1.55 + //Allocate a large enough buffer
1.56 + rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
1.57 +
1.58 + //Now read our RAWINPUT data
1.59 + if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
1.60 + {
1.61 + return false;
1.62 + }
1.63 +
1.64 + //Cast our buffer
1.65 + aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
1.66 + }
1.67 + catch
1.68 + {
1.69 + Debug.WriteLine("GetRawInputData failed!");
1.70 + success = false;
1.71 + }
1.72 +
1.73 + return success;
1.74 + }
1.75 +
1.76 + /// <summary>
1.77 + ///
1.78 + /// </summary>
1.79 + /// <param name="hDevice"></param>
1.80 + /// <param name="deviceInfo"></param>
1.81 + /// <returns></returns>
1.82 + public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
1.83 + {
1.84 + bool success = true;
1.85 + IntPtr deviceInfoBuffer = IntPtr.Zero;
1.86 + try
1.87 + {
1.88 + //Get Device Info
1.89 + uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
1.90 + deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
1.91 +
1.92 + int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.RawInputDeviceInfoType.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
1.93 + if (res <= 0)
1.94 + {
1.95 + Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
1.96 + return false;
1.97 + }
1.98 +
1.99 + //Cast our buffer
1.100 + deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
1.101 + }
1.102 + catch
1.103 + {
1.104 + Debug.WriteLine("GetRawInputData failed!");
1.105 + success = false;
1.106 + }
1.107 + finally
1.108 + {
1.109 + //Always executes, prevents memory leak
1.110 + Marshal.FreeHGlobal(deviceInfoBuffer);
1.111 + }
1.112 +
1.113 +
1.114 + return success;
1.115 + }
1.116 +
1.117 + /// <summary>
1.118 + /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device.
1.119 + /// </summary>
1.120 + /// <param name="device"></param>
1.121 + /// <returns></returns>
1.122 + public static IntPtr GetPreParsedData(IntPtr hDevice)
1.123 + {
1.124 + uint ppDataSize = 0;
1.125 + int result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize);
1.126 + if (result != 0)
1.127 + {
1.128 + Debug.WriteLine("Failed to get raw input pre-parsed data size: " + result + " : " + Marshal.GetLastWin32Error());
1.129 + return IntPtr.Zero;
1.130 + }
1.131 +
1.132 + IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize);
1.133 + result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, ppData, ref ppDataSize);
1.134 + if (result <= 0)
1.135 + {
1.136 + Debug.WriteLine("Failed to get raw input pre-parsed data: " + result + " : " + Marshal.GetLastWin32Error());
1.137 + return IntPtr.Zero;
1.138 + }
1.139 + return ppData;
1.140 + }
1.141 +
1.142 + /// <summary>
1.143 + ///
1.144 + /// </summary>
1.145 + /// <param name="device"></param>
1.146 + /// <returns></returns>
1.147 + public static string GetDeviceName(IntPtr device)
1.148 + {
1.149 + uint deviceNameSize = 256;
1.150 + int result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize);
1.151 + if (result != 0)
1.152 + {
1.153 + return string.Empty;
1.154 + }
1.155 +
1.156 + IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2); // size is the character count not byte count
1.157 + try
1.158 + {
1.159 + result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, deviceName, ref deviceNameSize);
1.160 + if (result > 0)
1.161 + {
1.162 + return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination
1.163 + }
1.164 +
1.165 + return string.Empty;
1.166 + }
1.167 + finally
1.168 + {
1.169 + Marshal.FreeHGlobal(deviceName);
1.170 + }
1.171 + }
1.172 +
1.173 +
1.174 + /// <summary>
1.175 + /// Populate the given tree-view control with our Raw Input Devices.
1.176 + /// </summary>
1.177 + /// <param name="aTreeView"></param>
1.178 + public static void PopulateDeviceList(TreeView aTreeView)
1.179 + {
1.180 +
1.181 + //Get our list of devices
1.182 + RAWINPUTDEVICELIST[] ridList = null;
1.183 + uint deviceCount = 0;
1.184 + int res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount,(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
1.185 + if (res == -1)
1.186 + {
1.187 + //Just give up then
1.188 + return;
1.189 + }
1.190 +
1.191 + ridList = new RAWINPUTDEVICELIST[deviceCount];
1.192 + res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
1.193 + if (res != deviceCount)
1.194 + {
1.195 + //Just give up then
1.196 + return;
1.197 + }
1.198 +
1.199 + //For each our device add a node to our treeview
1.200 + foreach (RAWINPUTDEVICELIST device in ridList)
1.201 + {
1.202 + SharpLib.Hid.HidDevice hidDevice=new SharpLib.Hid.HidDevice(device.hDevice);
1.203 +
1.204 + TreeNode node = null;
1.205 + if (hidDevice.Product != null && hidDevice.Product.Length > 1)
1.206 + {
1.207 + //Add the devices with a proper name at the top
1.208 + node = aTreeView.Nodes.Insert(0, hidDevice.Name, hidDevice.FriendlyName);
1.209 + }
1.210 + else
1.211 + {
1.212 + //Add other once at the bottom
1.213 + node = aTreeView.Nodes.Add(hidDevice.Name, hidDevice.FriendlyName);
1.214 + }
1.215 +
1.216 + node.Nodes.Add("Manufacturer: " + hidDevice.Manufacturer);
1.217 + node.Nodes.Add("Product ID: 0x" + hidDevice.ProductId.ToString("X4"));
1.218 + node.Nodes.Add("Vendor ID: 0x" + hidDevice.VendorId.ToString("X4"));
1.219 + node.Nodes.Add("Version: " + hidDevice.Version);
1.220 + node.Nodes.Add(hidDevice.Info.dwType.ToString());
1.221 + if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID)
1.222 + {
1.223 + node.Nodes.Add("UsagePage / UsageCollection: 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + " / 0x" + hidDevice.Info.hid.usUsage.ToString("X4"));
1.224 + }
1.225 +
1.226 + if (hidDevice.InputCapabilitiesDescription != null)
1.227 + {
1.228 + node.Nodes.Add(hidDevice.InputCapabilitiesDescription);
1.229 + }
1.230 +
1.231 + //Add button count
1.232 + node.Nodes.Add("Button Count: " + hidDevice.ButtonCount);
1.233 +
1.234 + //Those can be joystick/gamepad axis
1.235 + if (hidDevice.InputValueCapabilities != null)
1.236 + {
1.237 + foreach (HIDP_VALUE_CAPS caps in hidDevice.InputValueCapabilities)
1.238 + {
1.239 + string des = SharpLib.Hid.HidDevice.InputValueCapabilityDescription(caps);
1.240 + if (des != null)
1.241 + {
1.242 + node.Nodes.Add(des);
1.243 + }
1.244 + }
1.245 +
1.246 + }
1.247 +
1.248 + node.Nodes.Add(hidDevice.Name);
1.249 + }
1.250 + }
1.251 +
1.252 + }
1.253 +}
1.254 \ No newline at end of file