diff -r 72885c950813 -r cdc5f8f1b79e Win32/RawInput.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Win32/RawInput.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,250 @@ +// +// Copyright (C) 2014-2015 Stéphane Lenclud. +// +// This file is part of SharpLibHid. +// +// SharpDisplayManager is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// SharpDisplayManager is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with SharpDisplayManager. If not, see . +// + +using System; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Windows.Forms; + +namespace SharpLib.Win32 +{ + /// + /// Provide some utility functions for raw input handling. + /// + static public class RawInput + { + /// + /// + /// + /// + /// + /// Caller must free up memory on the pointer using Marshal.FreeHGlobal + /// + public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer) + { + bool success = true; + rawInputBuffer = IntPtr.Zero; + + try + { + uint dwSize = 0; + uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER)); + + //Get the size of our raw input data. + Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader); + + //Allocate a large enough buffer + rawInputBuffer = Marshal.AllocHGlobal((int)dwSize); + + //Now read our RAWINPUT data + if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize) + { + return false; + } + + //Cast our buffer + aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT)); + } + catch + { + Debug.WriteLine("GetRawInputData failed!"); + success = false; + } + + return success; + } + + /// + /// + /// + /// + /// + /// + public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo) + { + bool success = true; + IntPtr deviceInfoBuffer = IntPtr.Zero; + try + { + //Get Device Info + uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO)); + deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize); + + int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.RawInputDeviceInfoType.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize); + if (res <= 0) + { + Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString()); + return false; + } + + //Cast our buffer + deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO)); + } + catch + { + Debug.WriteLine("GetRawInputData failed!"); + success = false; + } + finally + { + //Always executes, prevents memory leak + Marshal.FreeHGlobal(deviceInfoBuffer); + } + + + return success; + } + + /// + /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device. + /// + /// + /// + public static IntPtr GetPreParsedData(IntPtr hDevice) + { + uint ppDataSize = 0; + int result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize); + if (result != 0) + { + Debug.WriteLine("Failed to get raw input pre-parsed data size: " + result + " : " + Marshal.GetLastWin32Error()); + return IntPtr.Zero; + } + + IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize); + result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, ppData, ref ppDataSize); + if (result <= 0) + { + Debug.WriteLine("Failed to get raw input pre-parsed data: " + result + " : " + Marshal.GetLastWin32Error()); + return IntPtr.Zero; + } + return ppData; + } + + /// + /// + /// + /// + /// + public static string GetDeviceName(IntPtr device) + { + uint deviceNameSize = 256; + int result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize); + if (result != 0) + { + return string.Empty; + } + + IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2); // size is the character count not byte count + try + { + result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, deviceName, ref deviceNameSize); + if (result > 0) + { + return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination + } + + return string.Empty; + } + finally + { + Marshal.FreeHGlobal(deviceName); + } + } + + + /// + /// Populate the given tree-view control with our Raw Input Devices. + /// + /// + public static void PopulateDeviceList(TreeView aTreeView) + { + + //Get our list of devices + RAWINPUTDEVICELIST[] ridList = null; + uint deviceCount = 0; + int res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount,(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST))); + if (res == -1) + { + //Just give up then + return; + } + + ridList = new RAWINPUTDEVICELIST[deviceCount]; + res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST))); + if (res != deviceCount) + { + //Just give up then + return; + } + + //For each our device add a node to our treeview + foreach (RAWINPUTDEVICELIST device in ridList) + { + SharpLib.Hid.HidDevice hidDevice=new SharpLib.Hid.HidDevice(device.hDevice); + + TreeNode node = null; + if (hidDevice.Product != null && hidDevice.Product.Length > 1) + { + //Add the devices with a proper name at the top + node = aTreeView.Nodes.Insert(0, hidDevice.Name, hidDevice.FriendlyName); + } + else + { + //Add other once at the bottom + node = aTreeView.Nodes.Add(hidDevice.Name, hidDevice.FriendlyName); + } + + node.Nodes.Add("Manufacturer: " + hidDevice.Manufacturer); + node.Nodes.Add("Product ID: 0x" + hidDevice.ProductId.ToString("X4")); + node.Nodes.Add("Vendor ID: 0x" + hidDevice.VendorId.ToString("X4")); + node.Nodes.Add("Version: " + hidDevice.Version); + node.Nodes.Add(hidDevice.Info.dwType.ToString()); + if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID) + { + node.Nodes.Add("UsagePage / UsageCollection: 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + " / 0x" + hidDevice.Info.hid.usUsage.ToString("X4")); + } + + if (hidDevice.InputCapabilitiesDescription != null) + { + node.Nodes.Add(hidDevice.InputCapabilitiesDescription); + } + + //Add button count + node.Nodes.Add("Button Count: " + hidDevice.ButtonCount); + + //Those can be joystick/gamepad axis + if (hidDevice.InputValueCapabilities != null) + { + foreach (HIDP_VALUE_CAPS caps in hidDevice.InputValueCapabilities) + { + string des = SharpLib.Hid.HidDevice.InputValueCapabilityDescription(caps); + if (des != null) + { + node.Nodes.Add(des); + } + } + + } + + node.Nodes.Add(hidDevice.Name); + } + } + + } +} \ No newline at end of file