sl@10: using System;
sl@10: using System.Runtime.InteropServices;
sl@10: using System.Diagnostics;
StephaneLenclud@60: using System.Windows.Forms;
sl@10:
sl@10:
StephaneLenclud@60: namespace Win32
sl@10: {
sl@17: ///
sl@17: /// Provide some utility functions for raw input handling.
sl@17: ///
sl@10: static class RawInput
sl@10: {
sl@10: ///
sl@10: ///
sl@10: ///
sl@10: ///
sl@10: ///
sl@10: /// Caller must free up memory on the pointer using Marshal.FreeHGlobal
sl@10: ///
sl@10: public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
sl@10: {
sl@10: bool success = true;
sl@10: rawInputBuffer = IntPtr.Zero;
sl@10:
sl@10: try
sl@10: {
sl@10: uint dwSize = 0;
sl@10: uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
sl@10:
sl@10: //Get the size of our raw input data.
sl@10: Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
sl@10:
sl@10: //Allocate a large enough buffer
sl@10: rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
sl@10:
sl@10: //Now read our RAWINPUT data
sl@10: if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
sl@10: {
sl@10: return false;
sl@10: }
sl@10:
sl@10: //Cast our buffer
sl@10: aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
sl@10: }
sl@10: catch
sl@10: {
sl@10: Debug.WriteLine("GetRawInputData failed!");
sl@10: success = false;
sl@10: }
sl@10:
sl@10: return success;
sl@10: }
sl@10:
sl@10: ///
sl@10: ///
sl@10: ///
sl@47: ///
sl@47: ///
sl@10: ///
sl@10: public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
sl@10: {
sl@10: bool success = true;
sl@10: IntPtr deviceInfoBuffer = IntPtr.Zero;
sl@10: try
sl@10: {
sl@10: //Get Device Info
sl@10: uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
sl@10: deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
sl@10:
StephaneLenclud@60: int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Win32.RawInputDeviceInfoType.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
sl@10: if (res <= 0)
sl@10: {
sl@10: Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
sl@10: return false;
sl@10: }
sl@10:
sl@10: //Cast our buffer
sl@10: deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
sl@10: }
sl@10: catch
sl@10: {
sl@10: Debug.WriteLine("GetRawInputData failed!");
sl@10: success = false;
sl@10: }
sl@10: finally
sl@10: {
sl@10: //Always executes, prevents memory leak
sl@10: Marshal.FreeHGlobal(deviceInfoBuffer);
sl@10: }
sl@10:
sl@10:
sl@10: return success;
sl@10: }
sl@10:
sl@17: ///
sl@19: /// Fetch pre-parsed data corresponding to HID descriptor for the given HID device.
sl@17: ///
sl@17: ///
sl@17: ///
sl@17: public static IntPtr GetPreParsedData(IntPtr hDevice)
sl@17: {
StephaneLenclud@60: uint ppDataSize = 0;
StephaneLenclud@60: int result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, IntPtr.Zero, ref ppDataSize);
sl@17: if (result != 0)
sl@17: {
StephaneLenclud@71: Debug.WriteLine("Failed to get raw input pre-parsed data size: " + result + " : " + Marshal.GetLastWin32Error());
sl@17: return IntPtr.Zero;
sl@17: }
sl@17:
sl@17: IntPtr ppData = Marshal.AllocHGlobal((int)ppDataSize);
StephaneLenclud@60: result = Win32.Function.GetRawInputDeviceInfo(hDevice, RawInputDeviceInfoType.RIDI_PREPARSEDDATA, ppData, ref ppDataSize);
sl@17: if (result <= 0)
sl@17: {
StephaneLenclud@71: Debug.WriteLine("Failed to get raw input pre-parsed data: " + result + " : " + Marshal.GetLastWin32Error());
sl@17: return IntPtr.Zero;
sl@17: }
sl@17: return ppData;
sl@17: }
sl@17:
sl@22: ///
sl@22: ///
sl@22: ///
sl@22: ///
sl@22: ///
sl@22: public static string GetDeviceName(IntPtr device)
sl@22: {
sl@22: uint deviceNameSize = 256;
StephaneLenclud@60: int result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, IntPtr.Zero, ref deviceNameSize);
sl@22: if (result != 0)
sl@22: {
sl@22: return string.Empty;
sl@22: }
sl@22:
sl@22: IntPtr deviceName = Marshal.AllocHGlobal((int)deviceNameSize * 2); // size is the character count not byte count
sl@22: try
sl@22: {
StephaneLenclud@60: result = Win32.Function.GetRawInputDeviceInfo(device, RawInputDeviceInfoType.RIDI_DEVICENAME, deviceName, ref deviceNameSize);
sl@22: if (result > 0)
sl@22: {
sl@23: return Marshal.PtrToStringAnsi(deviceName, result - 1); // -1 for NULL termination
sl@22: }
sl@22:
sl@22: return string.Empty;
sl@22: }
sl@22: finally
sl@22: {
sl@22: Marshal.FreeHGlobal(deviceName);
sl@22: }
sl@22: }
sl@22:
sl@17:
StephaneLenclud@60: ///
StephaneLenclud@70: /// Populate the given tree-view control with our Raw Input Devices.
StephaneLenclud@60: ///
StephaneLenclud@60: ///
StephaneLenclud@60: public static void PopulateDeviceList(TreeView aTreeView)
StephaneLenclud@60: {
StephaneLenclud@60:
StephaneLenclud@60: //Get our list of devices
StephaneLenclud@60: RAWINPUTDEVICELIST[] ridList = null;
StephaneLenclud@60: uint deviceCount = 0;
StephaneLenclud@60: int res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount,(uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
StephaneLenclud@60: if (res == -1)
StephaneLenclud@60: {
StephaneLenclud@60: //Just give up then
StephaneLenclud@60: return;
StephaneLenclud@60: }
StephaneLenclud@60:
StephaneLenclud@60: ridList = new RAWINPUTDEVICELIST[deviceCount];
StephaneLenclud@60: res = Win32.Function.GetRawInputDeviceList(ridList, ref deviceCount, (uint)Marshal.SizeOf(typeof(RAWINPUTDEVICELIST)));
StephaneLenclud@60: if (res != deviceCount)
StephaneLenclud@60: {
StephaneLenclud@60: //Just give up then
StephaneLenclud@60: return;
StephaneLenclud@60: }
StephaneLenclud@60:
StephaneLenclud@61: //For each our device add a node to our treeview
StephaneLenclud@60: foreach (RAWINPUTDEVICELIST device in ridList)
StephaneLenclud@60: {
StephaneLenclud@61: Hid.HidDevice hidDevice=new Hid.HidDevice(device.hDevice);
StephaneLenclud@61:
StephaneLenclud@61: TreeNode node = null;
StephaneLenclud@61: if (hidDevice.Product != null && hidDevice.Product.Length > 1)
StephaneLenclud@61: {
StephaneLenclud@61: //Add the devices with a proper name at the top
StephaneLenclud@63: node = aTreeView.Nodes.Insert(0, hidDevice.Name, hidDevice.FriendlyName);
StephaneLenclud@61: }
StephaneLenclud@61: else
StephaneLenclud@61: {
StephaneLenclud@61: //Add other once at the bottom
StephaneLenclud@69: node = aTreeView.Nodes.Add(hidDevice.Name, hidDevice.FriendlyName);
StephaneLenclud@61: }
StephaneLenclud@61:
StephaneLenclud@61: node.Nodes.Add("Manufacturer: " + hidDevice.Manufacturer);
StephaneLenclud@61: node.Nodes.Add("Product ID: 0x" + hidDevice.ProductId.ToString("X4"));
StephaneLenclud@61: node.Nodes.Add("Vendor ID: 0x" + hidDevice.VendorId.ToString("X4"));
StephaneLenclud@61: node.Nodes.Add("Version: " + hidDevice.Version);
StephaneLenclud@61: node.Nodes.Add(hidDevice.Info.dwType.ToString());
StephaneLenclud@61: if (hidDevice.Info.dwType == RawInputDeviceType.RIM_TYPEHID)
StephaneLenclud@61: {
StephaneLenclud@61: node.Nodes.Add("UsagePage / UsageCollection: 0x" + hidDevice.Info.hid.usUsagePage.ToString("X4") + " / 0x" + hidDevice.Info.hid.usUsage.ToString("X4"));
StephaneLenclud@61: }
StephaneLenclud@61:
StephaneLenclud@64: if (hidDevice.InputCapabilitiesDescription != null)
StephaneLenclud@64: {
StephaneLenclud@64: node.Nodes.Add(hidDevice.InputCapabilitiesDescription);
StephaneLenclud@64: }
StephaneLenclud@65:
StephaneLenclud@72: //Add button count
StephaneLenclud@72: node.Nodes.Add("Button Count: " + hidDevice.ButtonCount);
StephaneLenclud@72:
StephaneLenclud@72: //Those can be joystick/gamepad axis
StephaneLenclud@65: if (hidDevice.InputValueCapabilities != null)
StephaneLenclud@65: {
StephaneLenclud@65: foreach (HIDP_VALUE_CAPS caps in hidDevice.InputValueCapabilities)
StephaneLenclud@65: {
StephaneLenclud@65: string des = hidDevice.InputValueCapabilityDescription(caps);
StephaneLenclud@65: if (des != null)
StephaneLenclud@65: {
StephaneLenclud@65: node.Nodes.Add(des);
StephaneLenclud@65: }
StephaneLenclud@65: }
StephaneLenclud@65:
StephaneLenclud@65: }
StephaneLenclud@65:
StephaneLenclud@61: node.Nodes.Add(hidDevice.Name);
StephaneLenclud@60: }
StephaneLenclud@60: }
StephaneLenclud@60:
sl@10: }
sl@10: }