/// <summary> /// /// </summary> /// <param name="deviceHandle"></param> /// <param name="deviceInfo"></param> /// <returns></returns> public static bool GetDeviceInfo(IntPtr deviceHandle, 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.Win32RawInput.NativeMethods.GetRawInputDeviceInfo(deviceHandle, 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); }
/// <summary> /// Function to retrieve the device name. /// </summary> /// <param name="device">Raw input device to gather information from.</param> /// <returns>A device name structure.</returns> private T GetDeviceInfo <T>(ref RAWINPUTDEVICELIST device) where T : class, IGorgonRawInputDeviceInfo { RID_DEVICE_INFO deviceInfo = RawInputApi.GetDeviceInfo(ref device); string deviceName = RawInputApi.GetDeviceName(ref device); if (string.IsNullOrWhiteSpace(deviceName)) { return(null); } string className = RawInputDeviceRegistryInfo.GetDeviceClass(deviceName, _log); string deviceDescription = RawInputDeviceRegistryInfo.GetDeviceDescription(deviceName, _log); switch (deviceInfo.dwType) { case RawInputType.Keyboard: return(new RawKeyboardInfo(device.Device, deviceName, className, deviceDescription, deviceInfo.keyboard) as T); case RawInputType.Mouse: return(new RawMouseInfo(device.Device, deviceName, className, deviceDescription, deviceInfo.mouse) as T); case RawInputType.HID: return(new GorgonRawHIDInfo(device.Device, deviceName, className, deviceDescription, deviceInfo.hid) as T); default: return(null); } }
public static bool Exists() { uint deviceListCount = 0; uint rawInputDeviceListSize = (uint)Marshal.SizeOf <RAWINPUTDEVICELIST>(); if (GetRawInputDeviceList( null, ref deviceListCount, rawInputDeviceListSize) != 0) { return(false); } var devices = new RAWINPUTDEVICELIST[deviceListCount]; if (GetRawInputDeviceList( devices, ref deviceListCount, rawInputDeviceListSize) != deviceListCount) { return(false); } foreach (var device in devices.Where(x => x.dwType == RIM_TYPEHID)) { uint deviceInfoSize = 0; if (GetRawInputDeviceInfo( device.hDevice, RIDI_DEVICEINFO, IntPtr.Zero, ref deviceInfoSize) != 0) { continue; } var deviceInfo = new RID_DEVICE_INFO { cbSize = deviceInfoSize }; if (GetRawInputDeviceInfo( device.hDevice, RIDI_DEVICEINFO, ref deviceInfo, ref deviceInfoSize) == unchecked ((uint)-1)) { continue; } if ((deviceInfo.hid.usUsagePage == TouchpadUsagePage) && (deviceInfo.hid.usUsage == TouchpadUsage)) { return(true); } } return(false); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonRawInputDeviceInfo"/> class. /// </summary> /// <param name="name">The device name.</param> /// <param name="deviceType">The type of device.</param> /// <param name="className">Class name of the device.</param> /// <param name="hidPath">Human interface device path.</param> /// <param name="handle">Handle to the device.</param> /// <exception cref="System.ArgumentException">The handle is set to 0.</exception> /// <exception cref="System.ArgumentNullException">Either the name, className or hidPath are NULL or empty.</exception> public GorgonRawInputDeviceInfo(string name, InputDeviceType deviceType, string className, string hidPath, IntPtr handle) : base(name, deviceType, className, hidPath) { Handle = handle; // Get the usage information for the device. RID_DEVICE_INFO deviceInfo = Win32API.GetDeviceInfo(handle); Usage = (HIDUsage)deviceInfo.hid.usUsage; UsagePage = (HIDUsagePage)deviceInfo.hid.usUsagePage; }
/// <summary> /// Retrieves information about the raw input device. /// </summary> /// <param name="hDevice"> /// A handle to the raw input device. This comes from the <b>lParam</b> of the /// <see cref="RawHidReading.Win32.WinMessage.WM.INPUT">WM_INPUT</see> message, from the <see cref="RAWINPUTHEADER.hDevice">hDevice</see> /// member of <see cref="RAWINPUTHEADER" />, or from <see cref="GetRawInputDeviceList" />. It can also be /// <b>null</b> (IntPtr.Zero) if an application inserts input data, for example, by using <b>SendInput</b>. /// </param> /// <returns>The information about the raw input device.</returns> public static RID_DEVICE_INFO GetRawInputDeviceInfo(HANDLE hDevice) { var size = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO)); var ret = new RID_DEVICE_INFO(); ret.cbSize = size; var err = GetRawInputDeviceInfo(hDevice, RIDI.DEVICEINFO, ref ret, ref size); if (err == uint.MaxValue) { throw new Exception(string.Format("Error determining device information. (Error code: 0x{0:X8})", WinKernel.GetLastError())); } return(ret); }
private static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo, out int errorCode) { var success = true; var deviceInfoBuffer = IntPtr.Zero; try { //Get Device Info var deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO)); deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize); var res = RawInput.GetRawInputDeviceInfo(hDevice, RIDI.DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize); if (res <= 0) { errorCode = Marshal.GetLastWin32Error(); Debug.WriteLine("WM_INPUT could not read device info: " + errorCode); 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); } errorCode = 0; return(success); }
private static string GetFriendlyName(RID_DEVICE_INFO info, string product, string name, ushort productId) { //Work out proper suffix for our device root node. //That allows users to see in a glance what kind of device this is. var suffix = ""; Type usageCollectionType = null; var friendlyName = string.Empty; if (info.dwType == RIM_TYPE.HID) { //Process usage page if (Enum.IsDefined(typeof(UsagePage), info.hid.usUsagePage)) { //We know this usage page, add its name var usagePage = (UsagePage)info.hid.usUsagePage; suffix += " ( " + usagePage + ", "; usageCollectionType = UsageCollectionType(usagePage); } else { //We don't know this usage page, add its value suffix += " ( 0x" + info.hid.usUsagePage.ToString("X4") + ", "; } //Process usage collection //We don't know this usage page, add its value if (usageCollectionType == null || !Enum.IsDefined(usageCollectionType, info.hid.usUsage)) { //Show Hexa suffix += "0x" + info.hid.usUsage.ToString("X4") + " )"; } else { //We know this usage page, add its name suffix += Enum.GetName(usageCollectionType, info.hid.usUsage) + " )"; } } else if (info.dwType == RIM_TYPE.KEYBOARD) { suffix = " - Keyboard"; } else if (info.dwType == RIM_TYPE.MOUSE) { suffix = " - Mouse"; } if (product != null && product.Length > 1) { //This device as a proper name, use it friendlyName = product + suffix; } else { //Extract friendly name from name char[] delimiterChars = { '#', '&' }; var words = name.Split(delimiterChars); if (words.Length >= 2) { //Use our name sub-string to describe this device friendlyName = words[1] + " - 0x" + productId.ToString("X4") + suffix; } else { //No proper name just use the device ID instead friendlyName = "0x" + productId.ToString("X4") + suffix; } } return(friendlyName); }
private static bool CreateHidDevice(IntPtr hRawInputDevice, out HidDevice device, out int errorCode) { var manufacturer = string.Empty; var product = string.Empty; ushort productId = 0; ushort vendorId = 0; ushort version = 0; //Fetch various information defining the given HID device var name = RawInput.GetRawInputDeviceName(hRawInputDevice); //Fetch device info var iInfo = new RID_DEVICE_INFO(); if (!GetDeviceInfo(hRawInputDevice, ref iInfo, out var getDeviceErrorCode)) { device = default(HidDevice); errorCode = getDeviceErrorCode; return(false); } //Open our device from the device name/path var unsafeHandle = FileOperations.CreateFile(name, (FileAccess)0, //none FILE_SHARE.READ | FILE_SHARE.WRITE, IntPtr.Zero, FileMode.OPEN_EXISTING, (FILE_ATTRIBUTE)0x40000000, //.FILE_FLAG_OVERLAPPED, IntPtr.Zero ); var handle = new SafeFileHandle(unsafeHandle, true); //Check if CreateFile worked if (handle.IsInvalid) { throw new Exception("HidDevice: CreateFile failed: " + Marshal.GetLastWin32Error()); } //Get manufacturer string var manufacturerString = new StringBuilder(256); if (HidApiBindings.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity)) { manufacturer = manufacturerString.ToString(); } //Get product string var productString = new StringBuilder(256); if (HidApiBindings.HidD_GetProductString(handle, productString, productString.Capacity)) { product = productString.ToString(); } //Get attributes var attributes = new HIDD_ATTRIBUTES(); if (HidApiBindings.HidD_GetAttributes(handle, ref attributes)) { vendorId = attributes.VendorID; productId = attributes.ProductID; version = attributes.VersionNumber; } handle.Close(); var friendlyName = GetFriendlyName(iInfo, product, name, productId); var usagePage = iInfo.hid.usUsagePage; var usage = iInfo.hid.usUsage; device = new HidDevice(manufacturer, product, vendorId, productId, version, friendlyName, usagePage, usage); errorCode = 0; return(true); }
internal static extern uint GetRawInputDeviceInfo(IntPtr deviceHandle, uint command, ref RID_DEVICE_INFO data, ref uint dataSize);
/// <summary> /// Initialize an HidEvent from a WM_INPUT message /// </summary> /// <param name="hRawInputDevice"> /// Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as /// rawinput.header.hDevice /// </param> public HidEvent(Message aMessage, HidEventRepeatDelegate aRepeatDelegate) { RepeatCount = 0; IsValid = false; IsKeyboard = false; IsGeneric = false; Time = DateTime.Now; OriginalTime = DateTime.Now; Timer = new Timer(); Timer.Elapsed += (sender, e) => OnRepeatTimerElapsed(sender, e, this); Usages = new List <ushort>(); OnHidEventRepeat += aRepeatDelegate; if (aMessage.Msg != Const.WM_INPUT) { //Has to be a WM_INPUT message return; } if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT) { IsForeground = true; } else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK) { IsForeground = false; } //Declare some pointers var rawInputBuffer = IntPtr.Zero; //My understanding is that this is basically our HID descriptor var preParsedData = IntPtr.Zero; try { //Fetch raw input var rawInput = new RAWINPUT(); if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer)) { return; } //Fetch device info var deviceInfo = new RID_DEVICE_INFO(); if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo)) { return; } //Get various information about this HID device Device = new HidDevice(rawInput.header.hDevice); if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID { IsGeneric = true; Debug.WriteLine("WM_INPUT source device is HID."); //Get Usage Page and Usage //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4")); UsagePage = deviceInfo.hid.usUsagePage; UsageCollection = deviceInfo.hid.usUsage; preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice); if ( !(rawInput.hid.dwSizeHid > 1 //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg { return; } //Allocate a buffer for one HID input var hidInputReport = new byte[rawInput.hid.dwSizeHid]; Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)"); //For each HID input report in our raw input for (var i = 0; i < rawInput.hid.dwCount; i++) { //Compute the address from which to copy our HID input var hidInputOffset = 0; unsafe { var source = (byte *)rawInputBuffer; source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i); hidInputOffset = (int)source; } //Copy HID input into our buffer Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid); //Print HID input report in our debug output var hidDump = "HID input report: "; foreach (var b in hidInputReport) { hidDump += b.ToString("X2"); } Debug.WriteLine(hidDump); //Proper parsing now uint usageCount = 1; //Assuming a single usage per input report. Is that correct? var usages = new USAGE_AND_PAGE[usageCount]; var status = Function.HidP_GetUsagesEx(HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length); if (status != HidStatus.HIDP_STATUS_SUCCESS) { Log.Error("HID: Could not parse HID data!"); } else { //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4")); //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4")); //Add this usage to our list Usages.Add(usages[0].Usage); } } } else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE) { IsMouse = true; Debug.WriteLine("WM_INPUT source device is Mouse."); // do mouse handling... } else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD) { IsKeyboard = true; Debug.WriteLine("WM_INPUT source device is Keyboard."); // do keyboard handling... Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType); Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType); Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode); Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys); Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators); Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal); } } finally { //Always executed when leaving our try block Marshal.FreeHGlobal(rawInputBuffer); Marshal.FreeHGlobal(preParsedData); } //Start repeat timer if needed if (IsButtonDown) { StartRepeatTimer(iRepeatDelay); } IsValid = true; }
/// <summary> /// Private constructor. /// </summary> /// <param name="handleToRawInputDevice"></param> private void Construct(IntPtr handleToRawInputDevice) { this.PreParsedData = IntPtr.Zero; this.inputButtonCapabilities = null; this.inputValueCapabilities = null; // Fetch various information defining the given HID device this.Name = RawInputHelper.GetDeviceName(handleToRawInputDevice); // Fetch device info this.info = new RID_DEVICE_INFO(); if (!RawInputHelper.GetDeviceInfo(handleToRawInputDevice, ref this.info)) { throw new Exception("HidDevice: GetDeviceInfo failed: " + Marshal.GetLastWin32Error().ToString()); } // Open our device from the device name/path var handle = Win32.Win32CreateFile.NativeMethods.CreateFile( this.Name, FileAccess.NONE, FileShare.FILE_SHARE_READ | FileShare.FILE_SHARE_WRITE, IntPtr.Zero, CreationDisposition.OPEN_EXISTING, FileFlagsAttributes.FILE_FLAG_OVERLAPPED, IntPtr.Zero); // Check if CreateFile worked if (handle.IsInvalid) { throw new Exception("HidDevice: CreateFile failed: " + Marshal.GetLastWin32Error().ToString()); } // Get manufacturer string var manufacturerString = new StringBuilder(256); if (Win32.Win32Hid.NativeMethods.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity)) { this.Manufacturer = manufacturerString.ToString(); } // Get product string StringBuilder productString = new StringBuilder(256); if (Win32.Win32Hid.NativeMethods.HidD_GetProductString(handle, productString, productString.Capacity)) { this.Product = productString.ToString(); } // Get attributes HIDD_ATTRIBUTES attributes = new HIDD_ATTRIBUTES(); if (Win32.Win32Hid.NativeMethods.HidD_GetAttributes(handle, ref attributes)) { this.VendorId = attributes.VendorID; this.ProductId = attributes.ProductID; this.Version = attributes.VersionNumber; } handle.Close(); this.SetFriendlyName(); // Get our HID descriptor pre-parsed data this.PreParsedData = RawInputHelper.GetPreParsedData(handleToRawInputDevice); if (this.PreParsedData == IntPtr.Zero) { // We are done then. Some devices don't have pre-parsed data. return; } // Get capabilities var status = Win32.Win32Hid.NativeMethods.HidP_GetCaps(this.PreParsedData, ref this.capabilities); if (status != HidStatus.HIDP_STATUS_SUCCESS) { throw new Exception("HidDevice: HidP_GetCaps failed: " + status.ToString()); } this.SetInputCapabilitiesDescription(); // Get input button caps if needed if (this.Capabilities.NumberInputButtonCaps > 0) { this.inputButtonCapabilities = new HIDP_BUTTON_CAPS[this.Capabilities.NumberInputButtonCaps]; ushort buttonCapabilitiesLength = this.Capabilities.NumberInputButtonCaps; status = Win32.Win32Hid.NativeMethods.HidP_GetButtonCaps(HIDP_REPORT_TYPE.HidP_Input, this.inputButtonCapabilities, ref buttonCapabilitiesLength, this.PreParsedData); if (status != HidStatus.HIDP_STATUS_SUCCESS || buttonCapabilitiesLength != this.Capabilities.NumberInputButtonCaps) { throw new Exception("HidDevice: HidP_GetButtonCaps failed: " + status.ToString()); } this.ComputeButtonCount(); } // Get input value caps if needed if (this.Capabilities.NumberInputValueCaps > 0) { this.inputValueCapabilities = new HIDP_VALUE_CAPS[this.Capabilities.NumberInputValueCaps]; ushort valueCapabilitiesLength = this.Capabilities.NumberInputValueCaps; status = Win32.Win32Hid.NativeMethods.HidP_GetValueCaps(HIDP_REPORT_TYPE.HidP_Input, this.inputValueCapabilities, ref valueCapabilitiesLength, this.PreParsedData); if (status != HidStatus.HIDP_STATUS_SUCCESS || valueCapabilitiesLength != this.Capabilities.NumberInputValueCaps) { throw new Exception("HidDevice: HidP_GetValueCaps failed: " + status.ToString()); } } }
/// <summary> /// Iterates through the list provided by GetRawInputDeviceList, /// counting keyboard devices and adding them to deviceList. /// </summary> /// <returns>The number of keyboard devices found.</returns> public int EnumerateDevices() { lock (_deviceList) { int NumberOfDevices = 0; uint deviceCount = 0; int dwSize = (Marshal.SizeOf(typeof(RAWINPUTDEVICELIST))); _deviceList.Clear(); // Get the number of raw input devices in the list, // then allocate sufficient memory and get the entire list if (GetRawInputDeviceList(IntPtr.Zero, ref deviceCount, (uint)dwSize) == 0) { IntPtr pRawInputDeviceList = Marshal.AllocHGlobal((int)(dwSize * deviceCount)); GetRawInputDeviceList(pRawInputDeviceList, ref deviceCount, (uint)dwSize); // Iterate through the list, discarding undesired items // and retrieving further information on keyboard devices for (int i = -1; i < deviceCount; i++) { DeviceInfo dInfo; string deviceName; uint pcbSize = 0; IntPtr hDevice = IntPtr.Zero; int deviceType = 0; RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO(); if (i == -1) { dInfo = new DeviceInfo(); dInfo.DeviceName = "SendInput"; dInfo.DeviceHandle = IntPtr.Zero; dInfo.DeviceType = DeviceType.Keyboard; dInfo.Name = "SendInput (Keystrokes simulated by applications)"; NumberOfDevices++; _deviceList.Add(IntPtr.Zero, dInfo); continue; } RAWINPUTDEVICELIST rid = (RAWINPUTDEVICELIST)Marshal.PtrToStructure( new IntPtr((pRawInputDeviceList.ToInt32() + (dwSize * i))), typeof(RAWINPUTDEVICELIST)); hDevice = rid.hDevice; deviceType = rid.dwType; GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, IntPtr.Zero, ref pcbSize); if (pcbSize > 0) { IntPtr pData = Marshal.AllocHGlobal((int)pcbSize); GetRawInputDeviceInfo(hDevice, RIDI_DEVICENAME, pData, ref pcbSize); deviceName = (string)Marshal.PtrToStringAnsi(pData); Marshal.FreeHGlobal(pData); // Drop the "root" keyboard and mouse devices used for Terminal // Services and the Remote Desktop if (deviceName.ToUpper().StartsWith(@"\\?\ROOT")) { continue; } if (deviceName.ToUpper().StartsWith(@"\??\ROOT")) { continue; } GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, IntPtr.Zero, ref pcbSize); string bits = ""; if (pcbSize > 0) { pData = Marshal.AllocHGlobal((int)pcbSize); GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, pData, ref pcbSize); var data = new byte[pcbSize]; Marshal.Copy(pData, data, 0, (int)pcbSize); bits = BitConverter.ToString(data); deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(pData, typeof(RID_DEVICE_INFO)); Marshal.FreeHGlobal(pData); } // If the device is identified in the list as a keyboard or // HID device, create a DeviceInfo object to store information // about it //if (rid.dwType == RIM_TYPEKEYBOARD || rid.dwType == RIM_TYPEHID) { dInfo = new DeviceInfo(); dInfo.DeviceHandle = hDevice; dInfo.DeviceType = GetDeviceType(deviceType); dInfo.DeviceName = deviceName; dInfo.RawInputDeviceInfo = deviceInfo; // Check the Registry to see whether this is actually a // keyboard, and to retrieve a more friendly description. bool IsKeyboardDevice = false; dInfo.DeviceDesc = ReadReg(deviceName, ref IsKeyboardDevice); dInfo.Name = dInfo.DeviceDesc.Substring(dInfo.DeviceDesc.LastIndexOf(";") + 1); // If it is a keyboard and it isn't already in the list, // add it to the deviceList hashtable and increase the // NumberOfDevices count //if (!deviceList.Contains(hDevice) && IsKeyboardDevice) if (!_deviceList.ContainsKey(hDevice)) { NumberOfDevices++; _deviceList.Add(hDevice, dInfo); } } } } Marshal.FreeHGlobal(pRawInputDeviceList); return(NumberOfDevices); } else { throw new ApplicationException("An error occurred while retrieving the list of devices."); } } }
private static extern uint GetRawInputDeviceInfo(HANDLE hDevice, RIDI uiCommand, ref RID_DEVICE_INFO pData, ref uint pcbSize);
private static extern uint GetRawInputDeviceInfo( IntPtr hDevice, // hDevice by RAWINPUTDEVICELIST uint uiCommand, // RIDI_DEVICEINFO ref RID_DEVICE_INFO pData, ref uint pcbSize);
/// <summary> /// Returns whether a device is a compatible devices, or not. /// </summary> /// <param name="info">The <see cref="RID_DEVICE_INFO"/> describing the device.</param> /// <returns><b>true</b> if the device is compatible with the class; otherwise, <b>false</b>.</returns> public static bool IsSpaceMouse(RID_DEVICE_INFO info) { return(info.dwType == RIM_TYPE.HID && info.hid.usUsage == HID_USAGE_GENERIC_DESKTOP.MULTIAXIS_CONTROLLER && info.hid.usUsagePage == HID_USAGE_PAGE.GENERIC_DESKTOP && (info.hid.dwVendorId == VendorID.Logitech || info.hid.dwVendorId == VendorID.D3connexion)); }