# HG changeset patch # User StephaneLenclud # Date 1426447558 -3600 # Node ID cdc5f8f1b79ea74cc7670395c8470eb65db46570 # Parent 72885c950813b72c889d43b1933ce9a0b8d9f9c5 Moving files around. diff -r 72885c950813 -r cdc5f8f1b79e Hid/HidDevice.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hid/HidDevice.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,372 @@ +// +// 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.Windows.Forms; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using Microsoft.Win32.SafeHandles; +using SharpLib.Win32; + +namespace SharpLib.Hid +{ + /// + /// Represent a HID device. + /// Rename to RawInputDevice? + /// + public class HidDevice: IDisposable + { + /// + /// Unique name of that HID device. + /// Notably used as input to CreateFile. + /// + public string Name { get; private set; } + + /// + /// Friendly name that people should be able to read. + /// + public string FriendlyName { get; private set; } + + // + public string Manufacturer { get; private set; } + public string Product { get; private set; } + public ushort VendorId { get; private set; } + public ushort ProductId { get; private set; } + public ushort Version { get; private set; } + //Pre-parsed HID descriptor + public IntPtr PreParsedData {get; private set;} + //Info + public RID_DEVICE_INFO Info { get {return iInfo;} } + private RID_DEVICE_INFO iInfo; + //Capabilities + public HIDP_CAPS Capabilities { get { return iCapabilities; } } + private HIDP_CAPS iCapabilities; + public string InputCapabilitiesDescription { get; private set; } + //Input Button Capabilities + public HIDP_BUTTON_CAPS[] InputButtonCapabilities { get { return iInputButtonCapabilities; } } + private HIDP_BUTTON_CAPS[] iInputButtonCapabilities; + //Input Value Capabilities + public HIDP_VALUE_CAPS[] InputValueCapabilities { get { return iInputValueCapabilities; } } + private HIDP_VALUE_CAPS[] iInputValueCapabilities; + + // + public int ButtonCount { get; private set; } + + /// + /// Class constructor will fetch this object properties from HID sub system. + /// + /// Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice + public HidDevice(IntPtr hRawInputDevice) + { + //Try construct and rollback if needed + try + { + Construct(hRawInputDevice); + } + catch (System.Exception ex) + { + //Just rollback and propagate + Dispose(); + throw ex; + } + } + + + /// + /// Make sure dispose is called even if the user forgot about it. + /// + ~HidDevice() + { + Dispose(); + } + + /// + /// Private constructor. + /// + /// + private void Construct(IntPtr hRawInputDevice) + { + PreParsedData = IntPtr.Zero; + iInputButtonCapabilities = null; + iInputValueCapabilities = null; + + //Fetch various information defining the given HID device + Name = Win32.RawInput.GetDeviceName(hRawInputDevice); + + //Fetch device info + iInfo = new RID_DEVICE_INFO(); + if (!Win32.RawInput.GetDeviceInfo(hRawInputDevice, ref iInfo)) + { + throw new Exception("HidDevice: GetDeviceInfo failed: " + Marshal.GetLastWin32Error().ToString()); + } + + //Open our device from the device name/path + SafeFileHandle handle = Win32.Function.CreateFile(Name, + Win32.FileAccess.NONE, + Win32.FileShare.FILE_SHARE_READ | Win32.FileShare.FILE_SHARE_WRITE, + IntPtr.Zero, + Win32.CreationDisposition.OPEN_EXISTING, + Win32.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 + StringBuilder manufacturerString = new StringBuilder(256); + if (Win32.Function.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity)) + { + Manufacturer = manufacturerString.ToString(); + } + + //Get product string + StringBuilder productString = new StringBuilder(256); + if (Win32.Function.HidD_GetProductString(handle, productString, productString.Capacity)) + { + Product = productString.ToString(); + } + + //Get attributes + Win32.HIDD_ATTRIBUTES attributes = new Win32.HIDD_ATTRIBUTES(); + if (Win32.Function.HidD_GetAttributes(handle, ref attributes)) + { + VendorId = attributes.VendorID; + ProductId = attributes.ProductID; + Version = attributes.VersionNumber; + } + + handle.Close(); + + SetFriendlyName(); + + //Get our HID descriptor pre-parsed data + PreParsedData = Win32.RawInput.GetPreParsedData(hRawInputDevice); + + if (PreParsedData == IntPtr.Zero) + { + //We are done then. + //Some devices don't have pre-parsed data. + return; + } + + //Get capabilities + HidStatus status = Win32.Function.HidP_GetCaps(PreParsedData, ref iCapabilities); + if (status != HidStatus.HIDP_STATUS_SUCCESS) + { + throw new Exception("HidDevice: HidP_GetCaps failed: " + status.ToString()); + } + + SetInputCapabilitiesDescription(); + + //Get input button caps if needed + if (Capabilities.NumberInputButtonCaps > 0) + { + iInputButtonCapabilities = new HIDP_BUTTON_CAPS[Capabilities.NumberInputButtonCaps]; + ushort buttonCapabilitiesLength = Capabilities.NumberInputButtonCaps; + status = Win32.Function.HidP_GetButtonCaps(HIDP_REPORT_TYPE.HidP_Input, iInputButtonCapabilities, ref buttonCapabilitiesLength, PreParsedData); + if (status != HidStatus.HIDP_STATUS_SUCCESS || buttonCapabilitiesLength != Capabilities.NumberInputButtonCaps) + { + throw new Exception("HidDevice: HidP_GetButtonCaps failed: " + status.ToString()); + } + + ComputeButtonCount(); + } + + //Get input value caps if needed + if (Capabilities.NumberInputValueCaps > 0) + { + iInputValueCapabilities = new HIDP_VALUE_CAPS[Capabilities.NumberInputValueCaps]; + ushort valueCapabilitiesLength = Capabilities.NumberInputValueCaps; + status = Win32.Function.HidP_GetValueCaps(HIDP_REPORT_TYPE.HidP_Input, iInputValueCapabilities, ref valueCapabilitiesLength, PreParsedData); + if (status != HidStatus.HIDP_STATUS_SUCCESS || valueCapabilitiesLength != Capabilities.NumberInputValueCaps) + { + throw new Exception("HidDevice: HidP_GetValueCaps failed: " + status.ToString()); + } + } + } + + + /// + /// Useful for gamepads. + /// + void ComputeButtonCount() + { + ButtonCount = 0; + foreach (HIDP_BUTTON_CAPS bc in iInputButtonCapabilities) + { + if (bc.IsRange) + { + ButtonCount += (bc.Range.UsageMax - bc.Range.UsageMin + 1); + } + } + } + + + /// + /// + /// + void SetInputCapabilitiesDescription() + { + InputCapabilitiesDescription = "[ Input Capabilities ] Button: " + Capabilities.NumberInputButtonCaps + " - Value: " + Capabilities.NumberInputValueCaps + " - Data indices: " + Capabilities.NumberInputDataIndices; + } + + /// + /// + /// + private void SetFriendlyName() + { + //Work out proper suffix for our device root node. + //That allows users to see in a glance what kind of device this is. + string suffix = ""; + Type usageCollectionType = null; + if (Info.dwType == RawInputDeviceType.RIM_TYPEHID) + { + //Process usage page + if (Enum.IsDefined(typeof(UsagePage), Info.hid.usUsagePage)) + { + //We know this usage page, add its name + UsagePage usagePage = (UsagePage)Info.hid.usUsagePage; + suffix += " ( " + usagePage.ToString() + ", "; + usageCollectionType = Utils.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 == RawInputDeviceType.RIM_TYPEKEYBOARD) + { + suffix = " - Keyboard"; + } + else if (Info.dwType == RawInputDeviceType.RIM_TYPEMOUSE) + { + 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 = { '#', '&'}; + string[] 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; + } + } + + } + + /// + /// Dispose is just for unmanaged clean-up. + /// Make sure calling disposed multiple times does not crash. + /// See: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238 + /// + public void Dispose() + { + Marshal.FreeHGlobal(PreParsedData); + PreParsedData = IntPtr.Zero; + } + + /// + /// Provide a description for the given capabilities. + /// Notably describes axis on a gamepad/joystick. + /// + /// + /// + static public string InputValueCapabilityDescription(HIDP_VALUE_CAPS aCaps) + { + if (!aCaps.IsRange && Enum.IsDefined(typeof(UsagePage), aCaps.UsagePage)) + { + Type usageType = Utils.UsageType((UsagePage)aCaps.UsagePage); + string name = Enum.GetName(usageType, aCaps.NotRange.Usage); + if (name == null) + { + //Could not find that usage in our enum. + //Provide a relevant warning instead. + name = "Usage 0x" + aCaps.NotRange.Usage.ToString("X2") + " not defined in " + usageType.Name; + } + else + { + //Prepend our usage type name + name = usageType.Name + "." + name; + } + return "Input Value: " + name; + } + + return null; + } + + public bool IsGamePad + { + get + { + return ((UsagePage)iCapabilities.UsagePage == UsagePage.GenericDesktopControls && (UsageCollection.GenericDesktop)iCapabilities.Usage == UsageCollection.GenericDesktop.GamePad); + } + } + + + /// + /// Print information about this device to our debug output. + /// + public void DebugWrite() + { + Debug.WriteLine("================ HID ========================================================================================="); + Debug.WriteLine("==== Name: " + Name); + Debug.WriteLine("==== Manufacturer: " + Manufacturer); + Debug.WriteLine("==== Product: " + Product); + Debug.WriteLine("==== VendorID: 0x" + VendorId.ToString("X4")); + Debug.WriteLine("==== ProductID: 0x" + ProductId.ToString("X4")); + Debug.WriteLine("==== Version: " + Version.ToString()); + Debug.WriteLine("=============================================================================================================="); + } + + } + +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Hid/HidEvent.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hid/HidEvent.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,598 @@ +// +// 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.Windows.Forms; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using Microsoft.Win32.SafeHandles; +using SharpLib.Win32; +using System.Collections.Generic; +using System.Timers; +using SharpLib.Hid.Usage; + + +namespace SharpLib.Hid +{ + /// + /// We provide utility functions to interpret gamepad dpad state. + /// + public enum DirectionPadState + { + Rest=-1, + Up=0, + UpRight=1, + Right=2, + DownRight=3, + Down=4, + DownLeft=5, + Left=6, + UpLeft=7 + } + + /// + /// Represent a HID event. + /// TODO: Rename this into HidRawInput? + /// + public class HidEvent : IDisposable + { + public bool IsValid { get; private set; } + public bool IsForeground { get; private set; } + public bool IsBackground { get { return !IsForeground; } } + public bool IsMouse { get; private set; } + public bool IsKeyboard { get; private set; } + /// + /// If this not a mouse or keyboard event then it's a generic HID event. + /// + public bool IsGeneric { get; private set; } + public bool IsButtonDown { get { return Usages.Count == 1 && Usages[0] != 0; } } + public bool IsButtonUp { get { return Usages.Count == 0; } } + public bool IsRepeat { get { return RepeatCount != 0; } } + public uint RepeatCount { get; private set; } + + public HidDevice Device { get; private set; } + public RAWINPUT RawInput { get {return iRawInput;} } + private RAWINPUT iRawInput; + + public ushort UsagePage { get; private set; } + public ushort UsageCollection { get; private set; } + public uint UsageId { get { return ((uint)UsagePage << 16 | (uint)UsageCollection); } } + public List Usages { get; private set; } + /// + /// Sorted in the same order as Device.InputValueCapabilities. + /// + public Dictionary UsageValues { get; private set; } + //TODO: We need a collection of input report + public byte[] InputReport { get; private set; } + // + public delegate void HidEventRepeatDelegate(HidEvent aHidEvent); + public event HidEventRepeatDelegate OnHidEventRepeat; + + private System.Timers.Timer Timer { get; set; } + public DateTime Time { get; private set; } + public DateTime OriginalTime { get; private set; } + + //Compute repeat delay and speed based on system settings + //Those computations were taken from the Petzold here: ftp://ftp.charlespetzold.com/ProgWinForms/4%20Custom%20Controls/NumericScan/NumericScan/ClickmaticButton.cs + private int iRepeatDelay = 250 * (1 + SystemInformation.KeyboardDelay); + private int iRepeatSpeed = 405 - 12 * SystemInformation.KeyboardSpeed; + + /// + /// Tells whether this event has already been disposed of. + /// + public bool IsStray { get { return Timer == null; } } + + /// + /// We typically dispose of events as soon as we get the corresponding key up signal. + /// + public void Dispose() + { + Timer.Enabled = false; + Timer.Dispose(); + //Mark this event as a stray + Timer = null; + } + + /// + /// Initialize an HidEvent from a WM_INPUT message + /// + /// Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice + public HidEvent(Message aMessage, HidEventRepeatDelegate aRepeatDelegate) + { + RepeatCount = 0; + IsValid = false; + IsKeyboard = false; + IsGeneric = false; + + Time = DateTime.Now; + OriginalTime = DateTime.Now; + Timer = new System.Timers.Timer(); + Timer.Elapsed += (sender, e) => OnRepeatTimerElapsed(sender, e, this); + Usages = new List(); + UsageValues = new Dictionary(); + 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 + IntPtr rawInputBuffer = IntPtr.Zero; + + try + { + //Fetch raw input + iRawInput = new RAWINPUT(); + if (!Win32.RawInput.GetRawInputData(aMessage.LParam, ref iRawInput, ref rawInputBuffer)) + { + Debug.WriteLine("GetRawInputData failed!"); + return; + } + + //Our device can actually be null. + //This is notably happening for some keyboard events + if (RawInput.header.hDevice != IntPtr.Zero) + { + //Get various information about this HID device + Device = new HidDevice(RawInput.header.hDevice); + } + + if (RawInput.header.dwType == Win32.RawInputDeviceType.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 = Device.Info.hid.usUsagePage; + UsageCollection = Device.Info.hid.usUsage; + + 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 + InputReport = 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 (int i = 0; i < RawInput.hid.dwCount; i++) + { + //Compute the address from which to copy our HID input + int hidInputOffset = 0; + unsafe + { + byte* 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), InputReport, 0, (int)RawInput.hid.dwSizeHid); + // + ProcessInputReport(InputReport); + } + } + else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEMOUSE) + { + IsMouse = true; + + Debug.WriteLine("WM_INPUT source device is Mouse."); + // do mouse handling... + } + else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD) + { + IsKeyboard = true; + + Debug.WriteLine("WM_INPUT source device is Keyboard."); + // do keyboard handling... + if (Device != null) + { + Debug.WriteLine("Type: " + Device.Info.keyboard.dwType.ToString()); + Debug.WriteLine("SubType: " + Device.Info.keyboard.dwSubType.ToString()); + Debug.WriteLine("Mode: " + Device.Info.keyboard.dwKeyboardMode.ToString()); + Debug.WriteLine("Number of function keys: " + Device.Info.keyboard.dwNumberOfFunctionKeys.ToString()); + Debug.WriteLine("Number of indicators: " + Device.Info.keyboard.dwNumberOfIndicators.ToString()); + Debug.WriteLine("Number of keys total: " + Device.Info.keyboard.dwNumberOfKeysTotal.ToString()); + } + } + } + finally + { + //Always executed when leaving our try block + Marshal.FreeHGlobal(rawInputBuffer); + } + + // + if (IsButtonDown) + { + //TODO: Make this optional + //StartRepeatTimer(iRepeatDelay); + } + + IsValid = true; + } + + /// + /// + /// + private void ProcessInputReport(byte[] aInputReport) + { + //Print HID input report in our debug output + //string hidDump = "HID input report: " + InputReportString(); + //Debug.WriteLine(hidDump); + + //Get all our usages, those are typically the buttons currently pushed on a gamepad. + //For a remote control it's usually just the one button that was pushed. + GetUsages(aInputReport); + + //Now process direction pad (d-pad, dpad) and axes + GetUsageValues(aInputReport); + } + + /// + /// Typically fetches values of a joystick/gamepad axis and dpad directions. + /// + /// + private void GetUsageValues(byte[] aInputReport) + { + if (Device.InputValueCapabilities == null) + { + return; + } + + foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) + { + if (caps.IsRange) + { + //What should we do with those guys? + continue; + } + + //Now fetch and add our usage value + uint usageValue = 0; + Win32.HidStatus status = Win32.Function.HidP_GetUsageValue(Win32.HIDP_REPORT_TYPE.HidP_Input, caps.UsagePage, caps.LinkCollection, caps.NotRange.Usage, ref usageValue, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); + if (status == Win32.HidStatus.HIDP_STATUS_SUCCESS) + { + UsageValues[caps]=usageValue; + } + } + } + + /// + /// Get all our usages, those are typically the buttons currently pushed on a gamepad. + /// For a remote control it's usually just the one button that was pushed. + /// + private void GetUsages(byte[] aInputReport) + { + //Do proper parsing of our HID report + //First query our usage count + uint usageCount = 0; + Win32.USAGE_AND_PAGE[] usages = null; + Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); + if (status == Win32.HidStatus.HIDP_STATUS_BUFFER_TOO_SMALL) + { + //Allocate a large enough buffer + usages = new Win32.USAGE_AND_PAGE[usageCount]; + //...and fetch our usages + status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); + if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS) + { + Debug.WriteLine("Second pass could not parse HID data: " + status.ToString()); + } + } + else if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS) + { + Debug.WriteLine("First pass could not parse HID data: " + status.ToString()); + } + + Debug.WriteLine("Usage count: " + usageCount.ToString()); + + //Copy usages into this event + if (usages != null) + { + foreach (USAGE_AND_PAGE up in usages) + { + //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(up.Usage); + } + } + } + + /// + /// + /// + /// + /// + /// + public uint GetUsageValue(ushort aUsagePage, ushort aUsage) + { + foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) + { + if (caps.IsRange) + { + //What should we do with those guys? + continue; + } + + //Check if we have a match + if (caps.UsagePage == aUsagePage && caps.NotRange.Usage == aUsage) + { + return UsageValues[caps]; + } + } + + return 0; + } + + /// + /// + /// + /// + /// + /// + public int GetValueCapabilitiesIndex(ushort aUsagePage, ushort aUsage) + { + int i = -1; + foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) + { + i++; + if (caps.IsRange) + { + //What should we do with those guys? + continue; + } + + //Check if we have a match + if (caps.UsagePage == aUsagePage && caps.NotRange.Usage == aUsage) + { + return i; + } + } + + return i; + } + + + /// + /// TODO: Move this to another level? + /// + /// + public void StartRepeatTimer(double aInterval) + { + if (Timer == null) + { + return; + } + Timer.Enabled = false; + //Initial delay do not use auto reset + //After our initial delay however we do setup our timer one more time using auto reset + Timer.AutoReset = (RepeatCount != 0); + Timer.Interval = aInterval; + Timer.Enabled = true; + } + + static private void OnRepeatTimerElapsed(object sender, ElapsedEventArgs e, HidEvent aHidEvent) + { + if (aHidEvent.IsStray) + { + //Skip events if canceled + return; + } + + aHidEvent.RepeatCount++; + aHidEvent.Time = DateTime.Now; + if (aHidEvent.RepeatCount == 1) + { + //Re-Start our timer only after the initial delay + aHidEvent.StartRepeatTimer(aHidEvent.iRepeatSpeed); + } + + //Broadcast our repeat event + aHidEvent.OnHidEventRepeat(aHidEvent); + } + + /// + /// Provide the state of the dpad or hat switch if any. + /// If no dpad is found we return 'at rest'. + /// + /// + public DirectionPadState GetDirectionPadState() + { + int index=GetValueCapabilitiesIndex((ushort)Hid.UsagePage.GenericDesktopControls, (ushort)GenericDesktop.HatSwitch); + if (index < 0) + { + //No hat switch found + return DirectionPadState.Rest; + } + + HIDP_VALUE_CAPS caps=Device.InputValueCapabilities[index]; + if (caps.IsRange) + { + //Defensive + return DirectionPadState.Rest; + } + + uint dpadUsageValue = UsageValues[caps]; + + if (dpadUsageValue < caps.LogicalMin || dpadUsageValue > caps.LogicalMax) + { + //Out of range means at rest + return DirectionPadState.Rest; + } + + //Normalize value to start at zero + //TODO: more error check here? + DirectionPadState res = (DirectionPadState)((int)dpadUsageValue - caps.LogicalMin); + return res; + } + + /// + /// Print information about this device to our debug output. + /// + public void DebugWrite() + { + if (!IsValid) + { + Debug.WriteLine("==== Invalid HidEvent"); + return; + } + + if (Device!=null) + { + Device.DebugWrite(); + } + + if (IsGeneric) Debug.WriteLine("==== Generic"); + if (IsKeyboard) Debug.WriteLine("==== Keyboard"); + if (IsMouse) Debug.WriteLine("==== Mouse"); + Debug.WriteLine("==== Foreground: " + IsForeground.ToString()); + Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4")); + Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4")); + Debug.WriteLine("==== InputReport: 0x" + InputReportString()); + foreach (ushort usage in Usages) + { + Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4")); + } + } + + /// + /// + /// + /// + public string InputReportString() + { + if (InputReport == null) + { + return "null"; + } + + string hidDump = ""; + foreach (byte b in InputReport) + { + hidDump += b.ToString("X2"); + } + return hidDump; + } + + + /// + /// Create a list view item describing this HidEvent + /// + /// + public ListViewItem ToListViewItem() + { + string usageText = ""; + + foreach (ushort usage in Usages) + { + if (usageText != "") + { + //Add a separator + usageText += ", "; + } + + UsagePage usagePage = (UsagePage)UsagePage; + switch (usagePage) + { + case Hid.UsagePage.Consumer: + usageText += ((ConsumerControl)usage).ToString(); + break; + + case Hid.UsagePage.WindowsMediaCenterRemoteControl: + usageText += ((WindowsMediaCenterRemoteControl)usage).ToString(); + break; + + default: + usageText += usage.ToString("X2"); + break; + } + } + + //If we are a gamepad display axis and dpad values + if (Device.IsGamePad) + { + //uint dpadUsageValue = GetUsageValue((ushort)Hid.UsagePage.GenericDesktopControls, (ushort)Hid.Usage.GenericDesktop.HatSwitch); + //usageText = dpadUsageValue.ToString("X") + " (dpad), " + usageText; + + if (usageText != "") + { + //Add a separator + usageText += " (Buttons)"; + } + + if (usageText != "") + { + //Add a separator + usageText += ", "; + } + + usageText += GetDirectionPadState().ToString(); + + foreach (KeyValuePair entry in UsageValues) + { + if (entry.Key.IsRange) + { + continue; + } + + Type usageType = Utils.UsageType((UsagePage)entry.Key.UsagePage); + if (usageType == null) + { + //TODO: check why this is happening on Logitech rumble gamepad 2. + //Probably some of our axis are hiding in there. + continue; + } + string name = Enum.GetName(usageType, entry.Key.NotRange.Usage); + + if (usageText != "") + { + //Add a separator + usageText += ", "; + } + usageText += entry.Value.ToString("X") + " ("+ name +")"; + } + } + + //Now create our list item + ListViewItem item = new ListViewItem(new[] { usageText, InputReportString(), UsagePage.ToString("X2"), UsageCollection.ToString("X2"), RepeatCount.ToString(), Time.ToString("HH:mm:ss:fff") }); + return item; + } + + } + +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Hid/HidHandler.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hid/HidHandler.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,104 @@ +// +// 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.Windows.Forms; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using Microsoft.Win32.SafeHandles; +using SharpLib.Win32; +using System.Collections.Generic; + + +namespace SharpLib.Hid +{ + /// + /// Our HID handler manages raw input registrations, processes WM_INPUT messages and broadcasts HID events in return. + /// + public class HidHandler + { + public delegate void HidEventHandler(object aSender, HidEvent aHidEvent); + public event HidEventHandler OnHidEvent; + List iHidEvents; + + + public bool IsRegistered { get; private set; } + + public HidHandler(RAWINPUTDEVICE[] aRawInputDevices) + { + iHidEvents=new List(); + IsRegistered = Function.RegisterRawInputDevices(aRawInputDevices, (uint)aRawInputDevices.Length, (uint)Marshal.SizeOf(aRawInputDevices[0])); + } + + /// + /// Process a WM_INPUT message. + /// + /// + public void ProcessInput(ref Message aMessage) + { + if (aMessage.Msg != Const.WM_INPUT) + { + //We only process WM_INPUT messages + return; + } + + HidEvent hidEvent = new HidEvent(aMessage, OnHidEventRepeat); + hidEvent.DebugWrite(); + + if (!hidEvent.IsValid || !hidEvent.IsGeneric) + { + Debug.WriteLine("Skipping HID message."); + return; + } + + // + if (hidEvent.IsButtonUp) + { + //This is a key up event + //We need to discard any events belonging to the same page and collection + for (int i = (iHidEvents.Count-1); i >= 0; i--) + { + if (iHidEvents[i].UsageId == hidEvent.UsageId) + { + iHidEvents[i].Dispose(); + iHidEvents.RemoveAt(i); + } + } + } + else + { + //Keep that event until we get a key up message + iHidEvents.Add(hidEvent); + } + + //Broadcast our events + OnHidEvent(this, hidEvent); + } + + public void OnHidEventRepeat(HidEvent aHidEvent) + { + //Broadcast our events + OnHidEvent(this, aHidEvent); + } + + } + +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Hid/HidUsageTables.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hid/HidUsageTables.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,928 @@ +// +// 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 . +// + +namespace SharpLib.Hid +{ + /// + /// From USB HID usage tables. + /// http://www.usb.org/developers/hidpage#HID_Usage + /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf + /// + public enum UsagePage : ushort + { + Undefined = 0, + GenericDesktopControls, + SimulationControls, + VirtualRealityControls, + SportControls, + GameControls, + GenericDeviceControls, + Keyboard, + LightEmittingDiode, + Button, + Ordinal, + Telephony, + Consumer, + Digitiser, + PhysicalInterfaceDevice = 0x0f, + Unicode = 0x10, + AlphaNumericDisplay = 0x14, + MedicalInstruments = 0x40, + MonitorPage0 = 0x80, + MonitorPage1, + MonitorPage2, + MonitorPage3, + PowerPage0, + PowerPage1, + PowerPage2, + PowerPage3, + BarCodeScanner = 0x8c, + Scale, + MagneticStripeReader, + ReservedPointOfSale, + CameraControl, + Arcade, + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx + WindowsMediaCenterRemoteControl = 0xffbc, + TerraTecRemote = 0xffcc + } + + /// + /// Usage Collections are special values from our Usage enumeration. + /// Thus they are also part of the corresponding Usage enumeration. + /// + namespace UsageCollection + { + /// + /// Usage Collection for usage page GenericDesktopControls. + /// + public enum GenericDesktop : ushort + { + Pointer = 0x01, + Mouse = 0x02, + Joystick = 0x04, + GamePad = 0x05, + Keyboard = 0x06, + KeyPad = 0x07, + MultiAxisController = 0x08, + TabletPCSystemControls = 0x09, + SystemControl = 0x80 + } + + /// + /// Usage Collection for usage page Consumer. + /// + public enum Consumer : ushort + { + ConsumerControl = 0x01, + NumericKeyPad = 0x02, + ProgrammableButtons = 0x03, + Microphone = 0x04, + Headphone = 0x05, + GraphicEqualizer = 0x06, + FunctionButtons = 0x36, + Selection = 0x80, + MediaSelection = 0x0087, + SelectDisc = 0x00BA, + PlaybackSpeed = 0x00F1, + Proximity = 0x0109, + SpeakerSystem = 0x0160, + ChannelLeft = 0x0161, + ChannelRight = 0x0162, + ChannelCenter = 0x0163, + ChannelFront = 0x0164, + ChannelCenterFront = 0x0165, + ChannelSide = 0x0166, + ChannelSurrond = 0x0167, + ChannelLowFrequencyEnhancement = 0x0168, + ChannelTop = 0x0169, + ChannelUnknown = 0x016A, + ApplicationLaunchButtons = 0x016A, + GenericGuiApplicationControls = 0x0200, + } + + + public enum WindowsMediaCenter : ushort + { + WindowsMediaCenterRemoteControl = 0x88 + } + + } + + + + namespace Usage + { + /// + /// + /// + public enum WindowsMediaCenterRemoteControl : ushort + { + /// + /// Not defined by the Microsoft specs. + /// + Null = 0x00, + GreenStart = 0x0D, + ClosedCaptioning = 0x2B, + Teletext = 0x5A, + TeletextRed = 0x5B, + TeletextGreen = 0x5C, + TeletextYellow = 0x5D, + TeletextBlue = 0x5E, + LiveTv = 0x25, + Tv = 0x46, + Music = 0x47, + RecordedTv = 0x48, + Pictures = 0x49, + Videos = 0x4A, + FmRadio = 0x50, + Extras = 0x3C, + ExtrasApp = 0x3D, + DvdMenu = 0x24, + DvdAngle = 0x4B, + DvdAudio = 0x4C, + DvdSubtitle = 0x4D, + /// + /// First press action: Ejects a DVD drive. + /// + /// Second press action: Repeats first press action. + /// + /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application. + /// + Eject = 0x28, + DvdTopMenu = 0x43, + /// + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific + /// Collection (page 0xFFBC, usage 0x88). + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08). + /// + /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks. + /// + Ext0 = 0x32, + /// + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific + /// Collection (page 0xFFBC, usage 0x88). + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08). + /// + /// According to HP specs it plays a slide show of all the pictures on your hard disk drive. + /// + Ext1 = 0x33, + /// + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific + /// Collection (page 0xFFBC, usage 0x88). + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08). + /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310). + /// + Ext2 = 0x34, + /// + /// First press action: Generates EXTn HID message in the Media Center Vendor Specific + /// Collection (page 0xFFBC, usage 0x88). + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08). + /// + Ext3 = 0x35, + Ext4 = 0x36, + Ext5 = 0x37, + Ext6 = 0x38, + Ext7 = 0x39, + Ext8 = 0x3A, + Ext9 = 0x80, + Ext10 = 0x81, + Ext11 = 0x6F, + Zoom = 0x27, + ChannelInput = 0x42, + SubAudio = 0x2D, + Channel10 = 0x3E, + Channel11 = 0x3F, + Channel12 = 0x40, + /// + /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific + /// Collection. This button is intended to control the front panel display of home entertainment + /// computers. When this button is pressed, the display could be turned on or off, or the display + /// mode could change. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application. + /// + Display = 0x4F, + /// + /// First press action: To be determined. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + Kiosk = 0x6A, + NetworkSelection = 0x2C, + BlueRayTool = 0x78, + ChannelInfo = 0x41, + VideoSelection = 0x61 + } + + /// + /// Those codes come from experimenting with HP remotes. + /// + public enum HpWindowsMediaCenterRemoteControl : ushort + { + /// + /// Displays visual imagery that is synchronized to the sound of your music tracks. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08). + /// + /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks. + /// + Visualization = WindowsMediaCenterRemoteControl.Ext0, + /// + /// Plays a slide show of all the pictures on your hard disk drive. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08). + /// + /// According to HP specs it plays a slide show of all the pictures on your hard disk drive. + /// + SlideShow = WindowsMediaCenterRemoteControl.Ext1, + /// + /// Eject optical drive. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08). + /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310). + /// + HpEject = WindowsMediaCenterRemoteControl.Ext2, + /// + /// Not sure what this should do. + /// + /// Second press action: Repeats message. + /// + /// Auto-repeat: No + /// + /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08). + /// + InputSelection = WindowsMediaCenterRemoteControl.Ext3, + } + + /// + /// Usage Table for Consumer Controls + /// 0x0C 0X01 + /// + public enum ConsumerControl : ushort + { + Null = 0x00, + ConsumerControl = 0x01, + NumericKeyPad = 0x02, + ProgrammableButtons = 0x03, + Microphone = 0x04, + Headphone = 0x05, + GraphicEqualizer = 0x06, + Plus10 = 0x20, + Plus100 = 0x21, + AmPm = 0x22, + Power = 0x30, + Reset = 0x31, + Sleep = 0x32, + SleepAfter = 0x33, + SleepMode = 0x34, + Illumination = 0x35, + FunctionButtons = 0x36, + Menu = 0x40, + MenuPick = 0x41, + MenuUp = 0x42, + MenuDown = 0x43, + MenuLeft = 0x44, + MenuRight = 0x45, + MenuEscape = 0x46, + MenuValueIncrease = 0x47, + MenuValueDecrease = 0x48, + DataOnScreen = 0x60, + ClosedCaption = 0x61, + ClosedCaptionSelect = 0x62, + VcrTv = 0x63, + BroadcastMode = 0x64, + Snapshot = 0x65, + Still = 0x66, + Selection = 0x80, + AssignSelection = 0x81, + ModeStep = 0x82, + RecallLast = 0x83, + EnterChannel = 0x84, + OrderMovie = 0x85, + Channel = 0x86, + MediaSelection = 0x87, + MediaSelectComputer = 0x88, + MediaSelectTv = 0x89, + MediaSelectWww = 0x8A, + MediaSelectDvd = 0x8B, + MediaSelectTelephone = 0x8C, + MediaSelectProgramGuide = 0x8D, + MediaSelectVideoPhone = 0x8E, + MediaSelectGames = 0x8F, + MediaSelectMessages = 0x90, + MediaSelectCd = 0x91, + MediaSelectVcr = 0x92, + MediaSelectTuner = 0x93, + Quit = 0x94, + Help = 0x95, + MediaSelectTape = 0x96, + MediaSelectCable = 0x97, + MediaSelectSatellite = 0x98, + MediaSelectSecurity = 0x99, + MediaSelectHome = 0x9A, + MediaSelectCall = 0x9B, + ChannelIncrement = 0x9C, + ChannelDecrement = 0x9D, + MediaSelectSap = 0x9E, + VcrPlus = 0xA0, + Once = 0xA1, + Daily = 0xA2, + Weekly = 0xA3, + Monthly = 0xA4, + Play = 0xB0, + Pause = 0xB1, + Record = 0xB2, + FastForward = 0xB3, + Rewind = 0xB4, + ScanNextTrack = 0xB5, + ScanPreviousTrack = 0xB6, + Stop = 0xB7, + Eject = 0xB8, + RandomPlay = 0xB9, + SelectDisc = 0xBA, + EnterDisc = 0xBB, + Repeat = 0xBC, + Tracking = 0xBD, + TrackNormal = 0xBE, + SlowTracking = 0xBF, + FrameForward = 0xC0, + FrameBack = 0xC1, + Mark = 0xC2, + ClearMark = 0xC3, + RepeatFromMark = 0xC4, + ReturnToMark = 0xC5, + SearchMarkForward = 0xC6, + SearchMarkBackwards = 0xC7, + CounterReset = 0xC8, + ShowCounter = 0xC9, + TrackingIncrement = 0xCA, + TrackingDecrement = 0xCB, + StopEject = 0xCC, + PlayPause = 0xCD, + PlaySkip = 0xCE, + Volume = 0xE0, + Balance = 0xE1, + Mute = 0xE2, + Bass = 0xE3, + Treble = 0xE4, + BassBoost = 0xE5, + SurroundMode = 0xE6, + Loudness = 0xE7, + Mpx = 0xE8, + VolumeIncrement = 0xE9, + VolumeDecrement = 0xEA, + SpeedSelect = 0xF0, + PlaybackSpeed = 0xF1, + StandardPlay = 0xF2, + LongPlay = 0xF3, + ExtendedPlay = 0xF4, + Slow = 0xF5, + FanEnable = 0x100, + FanSpeed = 0x101, + LightEnable = 0x102, + LightIlluminationLevel = 0x103, + ClimateControlEnable = 0x104, + RoomTemperature = 0x105, + SecurityEnable = 0x106, + FireAlarm = 0x107, + PoliceAlarm = 0x108, + Proximity = 0x109, + Motion = 0x10A, + DuressAlarm = 0x10B, + HoldupAlarm = 0x10C, + MedicalAlarm = 0x10D, + BalanceRight = 0x150, + BalanceLeft = 0x151, + BassIncrement = 0x152, + BassDecrement = 0x153, + TrebleIncrement = 0x154, + TrebleDecrement = 0x155, + SpeakerSystem = 0x160, + ChannelLeft = 0x161, + ChannelRight = 0x162, + ChannelCenter = 0x163, + ChannelFront = 0x164, + ChannelCenterFront = 0x165, + ChannelSide = 0x166, + ChannelSurround = 0x167, + ChannelLowFrequencyEnhancement = 0x168, + ChannelTop = 0x169, + ChannelUnknown = 0x16A, + SubChannel = 0x170, + SubChannelIncrement = 0x171, + SubChannelDecrement = 0x172, + AlternateAudioIncrement = 0x173, + AlternateAudioDecrement = 0x174, + ApplicationLaunchButtons = 0x180, + AppLaunchLaunchButtonConfigurationTool = 0x181, + AppLaunchProgrammableButtonConfiguration = 0x182, + AppLaunchConsumerControlConfiguration = 0x183, + AppLaunchWordProcessor = 0x184, + AppLaunchTextEditor = 0x185, + AppLaunchSpreadsheet = 0x186, + AppLaunchGraphicsEditor = 0x187, + AppLaunchPresentationApp = 0x188, + AppLaunchDatabaseApp = 0x189, + AppLaunchEmailReader = 0x18A, + AppLaunchNewsreader = 0x18B, + AppLaunchVoicemail = 0x18C, + AppLaunchContactsAddressBook = 0x18D, + AppLaunchCalendarSchedule = 0x18E, + AppLaunchTaskProjectManager = 0x18F, + AppLaunchLogJournalTimecard = 0x190, + AppLaunchCheckbookFinance = 0x191, + AppLaunchCalculator = 0x192, + AppLaunchAVCapturePlayback = 0x193, + AppLaunchLocalMachineBrowser = 0x194, + AppLaunchLanWanBrowser = 0x195, + AppLaunchInternetBrowser = 0x196, + AppLaunchRemoteNetworkingIspConnect = 0x197, + AppLaunchNetworkConference = 0x198, + AppLaunchNetworkChat = 0x199, + AppLaunchTelephonyDialer = 0x19A, + AppLaunchLogon = 0x19B, + AppLaunchLogoff = 0x19C, + AppLaunchLogonLogoff = 0x19D, + AppLaunchTerminalLockScreensaver = 0x19E, + AppLaunchControlPanel = 0x19F, + AppLaunchCommandLineProcessorRun = 0x1A0, + AppLaunchProcessTaskManager = 0x1A1, + AppLaunchSelectTaskApplication = 0x1A2, + AppLaunchNextTaskApplication = 0x1A3, + AppLaunchPreviousTaskApplication = 0x1A4, + AppLaunchPreemptiveHaltTaskApplication = 0x1A5, + AppLaunchIntegratedHelpCenter = 0x1A6, + AppLaunchDocuments = 0x1A7, + AppLaunchThesaurus = 0x1A8, + AppLaunchDictionary = 0x1A9, + AppLaunchDesktop = 0x1AA, + AppLaunchSpellCheck = 0x1AB, + AppLaunchGrammarCheck = 0x1AC, + AppLaunchWirelessStatus = 0x1AD, + AppLaunchKeyboardLayout = 0x1AE, + AppLaunchVirusProtection = 0x1AF, + AppLaunchEncryption = 0x1B0, + AppLaunchScreenSaver = 0x1B1, + AppLaunchAlarms = 0x1B2, + AppLaunchClock = 0x1B3, + AppLaunchFileBrowser = 0x1B4, + AppLaunchPowerStatus = 0x1B5, + AppLaunchImageBrowser = 0x1B6, + AppLaunchAudioBrowser = 0x1B7, + AppLaunchMovieBrowser = 0x1B8, + AppLaunchDigitalRightsManager = 0x1B9, + AppLaunchDigitalWallet = 0x1BA, + AppLaunchInstantMessaging = 0x1BC, + AppLaunchOemFeaturesTipsTutorialBrowser = 0x1BD, + AppLaunchOemHelp = 0x1BE, + AppLaunchOnlineCommunity = 0x1BF, + AppLaunchEntertainmentContentBrowser = 0x1C0, + AppLaunchOnlineShoppingBrowser = 0x1C1, + AppLaunchSmartcardInformationHelp = 0x1C2, + AppLaunchMarketMonitorFinanceBrowser = 0x1C3, + AppLaunchCustomizedCorporateNewsBrowser = 0x1C4, + AppLaunchOnlineActivityBrowser = 0x1C5, + AppLaunchResearchSearchBrowser = 0x1C6, + AppLaunchAudioPlayer = 0x1C7, + GenericGuiApplicationControls = 0x200, + AppCtrlNew = 0x201, + AppCtrlOpen = 0x202, + AppCtrlClose = 0x203, + AppCtrlExit = 0x204, + AppCtrlMaximize = 0x205, + AppCtrlMinimize = 0x206, + AppCtrlSave = 0x207, + AppCtrlPrint = 0x208, + AppCtrlProperties = 0x209, + AppCtrlUndo = 0x21A, + AppCtrlCopy = 0x21B, + AppCtrlCut = 0x21C, + AppCtrlPaste = 0x21D, + AppCtrlSelectAll = 0x21E, + AppCtrlFind = 0x21F, + AppCtrlFindAndReplace = 0x220, + AppCtrlSearch = 0x221, + AppCtrlGoTo = 0x222, + AppCtrlHome = 0x223, + AppCtrlBack = 0x224, + AppCtrlForward = 0x225, + AppCtrlStop = 0x226, + AppCtrlRefresh = 0x227, + AppCtrlPreviousLink = 0x228, + AppCtrlNextLink = 0x229, + AppCtrlBookmarks = 0x22A, + AppCtrlHistory = 0x22B, + AppCtrlSubscriptions = 0x22C, + AppCtrlZoomIn = 0x22D, + AppCtrlZoomOut = 0x22E, + AppCtrlZoom = 0x22F, + AppCtrlFullScreenView = 0x230, + AppCtrlNormalView = 0x231, + AppCtrlViewToggle = 0x232, + AppCtrlScrollUp = 0x233, + AppCtrlScrollDown = 0x234, + AppCtrlScroll = 0x235, + AppCtrlPanLeft = 0x236, + AppCtrlPanRight = 0x237, + AppCtrlPan = 0x238, + AppCtrlNewWindow = 0x239, + AppCtrlTileHorizontally = 0x23A, + AppCtrlTileVertically = 0x23B, + AppCtrlFormat = 0x23C, + AppCtrlEdit = 0x23D, + AppCtrlBold = 0x23E, + AppCtrlItalics = 0x23F, + AppCtrlUnderline = 0x240, + AppCtrlStrikethrough = 0x241, + AppCtrlSubscript = 0x242, + AppCtrlSuperscript = 0x243, + AppCtrlAllCaps = 0x244, + AppCtrlRotate = 0x245, + AppCtrlResize = 0x246, + AppCtrlFlipHorizontal = 0x247, + AppCtrlFlipVertical = 0x248, + AppCtrlMirrorHorizontal = 0x249, + AppCtrlMirrorVertical = 0x24A, + AppCtrlFontSelect = 0x24B, + AppCtrlFontColor = 0x24C, + AppCtrlFontSize = 0x24D, + AppCtrlJustifyLeft = 0x24E, + AppCtrlJustifyCenterH = 0x24F, + AppCtrlJustifyRight = 0x250, + AppCtrlJustifyBlockH = 0x251, + AppCtrlJustifyTop = 0x252, + AppCtrlJustifyCenterV = 0x253, + AppCtrlJustifyBottom = 0x254, + AppCtrlJustifyBlockV = 0x255, + AppCtrlIndentDecrease = 0x256, + AppCtrlIndentIncrease = 0x257, + AppCtrlNumberedList = 0x258, + AppCtrlRestartNumbering = 0x259, + AppCtrlBulletedList = 0x25A, + AppCtrlPromote = 0x25B, + AppCtrlDemote = 0x25C, + AppCtrlYes = 0x25D, + AppCtrlNo = 0x25E, + AppCtrlCancel = 0x25F, + AppCtrlCatalog = 0x260, + AppCtrlBuyCheckout = 0x261, + AppCtrlAddToCart = 0x262, + AppCtrlExpand = 0x263, + AppCtrlExpandAll = 0x264, + AppCtrlCollapse = 0x265, + AppCtrlCollapseAll = 0x266, + AppCtrlPrintPreview = 0x267, + AppCtrlPasteSpecial = 0x268, + AppCtrlInsertMode = 0x269, + AppCtrlDelete = 0x26A, + AppCtrlLock = 0x26B, + AppCtrlUnlock = 0x26C, + AppCtrlProtect = 0x26D, + AppCtrlUnprotect = 0x26E, + AppCtrlAttachComment = 0x26F, + AppCtrlDeleteComment = 0x270, + AppCtrlViewComment = 0x271, + AppCtrlSelectWord = 0x272, + AppCtrlSelectSentence = 0x273, + AppCtrlSelectParagraph = 0x274, + AppCtrlSelectColumn = 0x275, + AppCtrlSelectRow = 0x276, + AppCtrlSelectTable = 0x277, + AppCtrlSelectObject = 0x278, + AppCtrlRedoRepeat = 0x279, + AppCtrlSort = 0x27A, + AppCtrlSortAscending = 0x27B, + AppCtrlSortDescending = 0x27C, + AppCtrlFilter = 0x27D, + AppCtrlSetClock = 0x27E, + AppCtrlViewClock = 0x27F, + AppCtrlSelectTimeZone = 0x280, + AppCtrlEditTimeZones = 0x281, + AppCtrlSetAlarm = 0x282, + AppCtrlClearAlarm = 0x283, + AppCtrlSnoozeAlarm = 0x284, + AppCtrlResetAlarm = 0x285, + AppCtrlSynchronize = 0x286, + AppCtrlSendReceive = 0x287, + AppCtrlSendTo = 0x288, + AppCtrlReply = 0x289, + AppCtrlReplyAll = 0x28A, + AppCtrlForwardMsg = 0x28B, + AppCtrlSend = 0x28C, + AppCtrlAttachFile = 0x28D, + AppCtrlUpload = 0x28E, + AppCtrlDownloadSaveTargetAs = 0x28F, + AppCtrlSetBorders = 0x290, + AppCtrlInsertRow = 0x291, + AppCtrlInsertColumn = 0x292, + AppCtrlInsertFile = 0x293, + AppCtrlInsertPicture = 0x294, + AppCtrlInsertObject = 0x295, + AppCtrlInsertSymbol = 0x296, + AppCtrlSaveAndClose = 0x297, + AppCtrlRename = 0x298, + AppCtrlMerge = 0x299, + AppCtrlSplit = 0x29A, + AppCtrlDistributeHorizontally = 0x29B, + AppCtrlDistributeVertically = 0x29C + } + + /// + /// + /// + enum GenericDesktop : ushort + { + Null = 0x00, + Pointer = 0x01, + Mouse = 0x02, + Joystick = 0x04, + GamePad = 0x05, + Keyboard = 0x06, + Keypad = 0x07, + MultiAxisController = 0x08, + TabletPcSystemControls = 0x09, + X = 0x30, + Y = 0x31, + Z = 0x32, + Rx = 0x33, + Ry = 0x34, + Rz = 0x35, + Slider = 0x36, + Dial = 0x37, + Wheel = 0x38, + HatSwitch = 0x39, + CountedBuffer = 0x3A, + ByteCount = 0x3B, + MotionWakeup = 0x3C, + Start = 0x3D, + Select = 0x3E, + Vx = 0x40, + Vy = 0x41, + Vz = 0x42, + Vbrx = 0x43, + Vbry = 0x44, + Vbrz = 0x45, + Vno = 0x46, + SystemControl = 0x80, + SystemPowerDown = 0x81, + SystemSleep = 0x82, + SystemWakeUp = 0x83, + SystemContextMenu = 0x84, + SystemMainMenu = 0x85, + SystemAppMenu = 0x86, + SystemMenuHelp = 0x87, + SystemMenuExit = 0x88, + SystemMenuSelect = 0x89, + SystemMenuRight = 0x8A, + SystemMenuLeft = 0x8B, + SystemMenuUp = 0x8C, + SystemMenuDown = 0x8D, + SystemColdRestart = 0x8E, + SystemWarmRestart = 0x8F, + DPadUp = 0x90, + DPadDown = 0x91, + DPadRight = 0x92, + DPadLeft = 0x93, + SystemDock = 0xA0, + SystemUndock = 0xA1, + SystemSetup = 0xA2, + SystemBreak = 0xA3, + SystemDebuggerBreak = 0xA4, + ApplicationBreak = 0xA5, + ApplicationDebuggerBreak = 0xA6, + SystemSpeakerMute = 0xA7, + SystemHibernate = 0xA8, + SystemDisplayInvert = 0xB0, + SystemDisplayInternal = 0xB1, + SystemDisplayExternal = 0xB2, + SystemDisplayBoth = 0xB3, + SystemDisplayDual = 0xB4, + SystemDisplayToggleIntExt = 0xB5, + SystemDisplaySwapPrimarySecondary = 0xB6, + SystemDisplayLcdAutoscale = 0xB7 + } + + /// + /// + /// + enum SimulationControl : ushort + { + Null = 0x00, + FlightSimulationDevice = 0x01, + AutomobileSimulationDevice = 0x02, + TankSimulationDevice = 0x03, + SpaceshipSimulationDevice = 0x04, + SubmarineSimulationDevice = 0x05, + SailingSimulationDevice = 0x06, + MotorcycleSimulationDevice = 0x07, + SportsSimulationDevice = 0x08, + AirplaneSimulationDevice = 0x09, + HelicopterSimulationDevice = 0x0A, + MagicCarpetSimulationDevice = 0x0B, + BicycleSimulationDevice = 0x0C, + FlightControlStick = 0x20, + FlightStick = 0x21, + CyclicControl = 0x22, + CyclicTrim = 0x23, + FlightYoke = 0x24, + TrackControl = 0x25, + Aileron = 0xB0, + AileronTrim = 0xB1, + AntiTorqueControl = 0xB2, + AutopilotEnable = 0xB3, + ChaffRelease = 0xB4, + CollectiveControl = 0xB5, + DiveBrake = 0xB6, + ElectronicCountermeasures = 0xB7, + Elevator = 0xB8, + ElevatorTrim = 0xB9, + Rudder = 0xBA, + Throttle = 0xBB, + FlightCommunications = 0xBC, + FlareRelease = 0xBD, + LandingGear = 0xBE, + ToeBrake = 0xBF, + Trigger = 0xC0, + WeaponsArm = 0xC1, + WeaponsSelect = 0xC2, + WingFlaps = 0xC3, + Accelerator = 0xC4, + Brake = 0xC5, + Clutch = 0xC6, + Shifter = 0xC7, + Steering = 0xC8, + TurretDirection = 0xC9, + BarrelElevation = 0xCA, + DivePlane = 0xCB, + Ballast = 0xCC, + BicycleCrank = 0xCD, + HandleBars = 0xCE, + FrontBrake = 0xCF, + RearBrake = 0xD0 + } + + /// + /// + /// + enum GameControl : ushort + { + Null = 0x00, + GameController3D = 0x01, + PinballDevice = 0x02, + GunDevice = 0x03, + PointOfView = 0x20, + TurnRightLeft = 0x21, + PitchForwardBackward = 0x22, + RollRightLeft = 0x23, + MoveRightLeft = 0x24, + MoveForwardBackward = 0x25, + MoveUpDown = 0x26, + LeanRightLeft = 0x27, + LeanForwardBackward = 0x28, + HeightOfPov = 0x29, + Flipper = 0x2A, + SecondaryFlipper = 0x2B, + Bump = 0x2C, + NewGame = 0x2D, + ShootBall = 0x2E, + Player = 0x2F, + GunBolt = 0x30, + GunClip = 0x31, + GunSelector = 0x32, + GunSingleShot = 0x33, + GunBurst = 0x34, + GunAutomatic = 0x35, + GunSafety = 0x36, + GamepadFireJump = 0x37, + GamepadTrigger = 0x39 + } + + /// + /// + /// + enum TelephonyDevice : ushort + { + Null = 0x00, + Phone = 0x01, + AnsweringMachine = 0x02, + MessageControls = 0x03, + Handset = 0x04, + Headset = 0x05, + TelephonyKeyPad = 0x06, + ProgrammableButton = 0x07, + HookSwitch = 0x20, + Flash = 0x21, + Feature = 0x22, + Hold = 0x23, + Redial = 0x24, + Transfer = 0x25, + Drop = 0x26, + Park = 0x27, + ForwardCalls = 0x28, + AlternateFunction = 0x29, + Line = 0x2A, + SpeakerPhone = 0x2B, + Conference = 0x2C, + RingEnable = 0x2D, + RingSelect = 0x2E, + PhoneMute = 0x2F, + CallerId = 0x30, + Send = 0x31, + SpeedDial = 0x50, + StoreNumber = 0x51, + RecallNumber = 0x52, + PhoneDirectory = 0x53, + VoiceMail = 0x70, + ScreenCalls = 0x71, + DoNotDisturb = 0x72, + Message = 0x73, + AnswerOnOff = 0x74, + InsideDialTone = 0x90, + OutsideDialTone = 0x91, + InsideRingTone = 0x92, + OutsideRingTone = 0x93, + PriorityRingTone = 0x94, + InsideRingback = 0x95, + PriorityRingback = 0x96, + LineBusyTone = 0x97, + ReorderTone = 0x98, + CallWaitingTone = 0x99, + ConfirmationTone1 = 0x9A, + ConfirmationTone2 = 0x9B, + TonesOff = 0x9C, + OutsideRingback = 0x9D, + Ringer = 0x9E, + PhoneKey0 = 0xB0, + PhoneKey1 = 0xB1, + PhoneKey2 = 0xB2, + PhoneKey3 = 0xB3, + PhoneKey4 = 0xB4, + PhoneKey5 = 0xB5, + PhoneKey6 = 0xB6, + PhoneKey7 = 0xB7, + PhoneKey8 = 0xB8, + PhoneKey9 = 0xB9, + PhoneKeyStar = 0xBA, + PhoneKeyPound = 0xBB, + PhoneKeyA = 0xBC, + PhoneKeyB = 0xBD, + PhoneKeyC = 0xBE, + PhoneKeyD = 0xBF + } + } +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Hid/HidUtils.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hid/HidUtils.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,84 @@ +// +// 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.Collections.Generic; +using System.Text; + +namespace SharpLib.Hid +{ + static class Utils + { + /// + /// Provide the type for the usage collection corresponding to the given usage page. + /// + /// + /// + public static Type UsageCollectionType(UsagePage aUsagePage) + { + switch (aUsagePage) + { + case UsagePage.GenericDesktopControls: + return typeof(UsageCollection.GenericDesktop); + + case UsagePage.Consumer: + return typeof(UsageCollection.Consumer); + + case UsagePage.WindowsMediaCenterRemoteControl: + return typeof(UsageCollection.WindowsMediaCenter); + + default: + return null; + } + } + + /// + /// Provide the type for the usage corresponding to the given usage page. + /// + /// + /// + public static Type UsageType(UsagePage aUsagePage) + { + switch (aUsagePage) + { + case UsagePage.GenericDesktopControls: + return typeof(Usage.GenericDesktop); + + case UsagePage.Consumer: + return typeof(Usage.ConsumerControl); + + case UsagePage.WindowsMediaCenterRemoteControl: + return typeof(Usage.WindowsMediaCenterRemoteControl); + + case UsagePage.Telephony: + return typeof(Usage.TelephonyDevice); + + case UsagePage.SimulationControls: + return typeof(Usage.SimulationControl); + + case UsagePage.GameControls: + return typeof(Usage.GameControl); + + default: + return null; + } + } + + } +} diff -r 72885c950813 -r cdc5f8f1b79e HidDevice.cs --- a/HidDevice.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,372 +0,0 @@ -// -// 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.Windows.Forms; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Text; -using Microsoft.Win32.SafeHandles; -using SharpLib.Win32; - -namespace SharpLib.Hid -{ - /// - /// Represent a HID device. - /// Rename to RawInputDevice? - /// - public class HidDevice: IDisposable - { - /// - /// Unique name of that HID device. - /// Notably used as input to CreateFile. - /// - public string Name { get; private set; } - - /// - /// Friendly name that people should be able to read. - /// - public string FriendlyName { get; private set; } - - // - public string Manufacturer { get; private set; } - public string Product { get; private set; } - public ushort VendorId { get; private set; } - public ushort ProductId { get; private set; } - public ushort Version { get; private set; } - //Pre-parsed HID descriptor - public IntPtr PreParsedData {get; private set;} - //Info - public RID_DEVICE_INFO Info { get {return iInfo;} } - private RID_DEVICE_INFO iInfo; - //Capabilities - public HIDP_CAPS Capabilities { get { return iCapabilities; } } - private HIDP_CAPS iCapabilities; - public string InputCapabilitiesDescription { get; private set; } - //Input Button Capabilities - public HIDP_BUTTON_CAPS[] InputButtonCapabilities { get { return iInputButtonCapabilities; } } - private HIDP_BUTTON_CAPS[] iInputButtonCapabilities; - //Input Value Capabilities - public HIDP_VALUE_CAPS[] InputValueCapabilities { get { return iInputValueCapabilities; } } - private HIDP_VALUE_CAPS[] iInputValueCapabilities; - - // - public int ButtonCount { get; private set; } - - /// - /// Class constructor will fetch this object properties from HID sub system. - /// - /// Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice - public HidDevice(IntPtr hRawInputDevice) - { - //Try construct and rollback if needed - try - { - Construct(hRawInputDevice); - } - catch (System.Exception ex) - { - //Just rollback and propagate - Dispose(); - throw ex; - } - } - - - /// - /// Make sure dispose is called even if the user forgot about it. - /// - ~HidDevice() - { - Dispose(); - } - - /// - /// Private constructor. - /// - /// - private void Construct(IntPtr hRawInputDevice) - { - PreParsedData = IntPtr.Zero; - iInputButtonCapabilities = null; - iInputValueCapabilities = null; - - //Fetch various information defining the given HID device - Name = Win32.RawInput.GetDeviceName(hRawInputDevice); - - //Fetch device info - iInfo = new RID_DEVICE_INFO(); - if (!Win32.RawInput.GetDeviceInfo(hRawInputDevice, ref iInfo)) - { - throw new Exception("HidDevice: GetDeviceInfo failed: " + Marshal.GetLastWin32Error().ToString()); - } - - //Open our device from the device name/path - SafeFileHandle handle = Win32.Function.CreateFile(Name, - Win32.FileAccess.NONE, - Win32.FileShare.FILE_SHARE_READ | Win32.FileShare.FILE_SHARE_WRITE, - IntPtr.Zero, - Win32.CreationDisposition.OPEN_EXISTING, - Win32.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 - StringBuilder manufacturerString = new StringBuilder(256); - if (Win32.Function.HidD_GetManufacturerString(handle, manufacturerString, manufacturerString.Capacity)) - { - Manufacturer = manufacturerString.ToString(); - } - - //Get product string - StringBuilder productString = new StringBuilder(256); - if (Win32.Function.HidD_GetProductString(handle, productString, productString.Capacity)) - { - Product = productString.ToString(); - } - - //Get attributes - Win32.HIDD_ATTRIBUTES attributes = new Win32.HIDD_ATTRIBUTES(); - if (Win32.Function.HidD_GetAttributes(handle, ref attributes)) - { - VendorId = attributes.VendorID; - ProductId = attributes.ProductID; - Version = attributes.VersionNumber; - } - - handle.Close(); - - SetFriendlyName(); - - //Get our HID descriptor pre-parsed data - PreParsedData = Win32.RawInput.GetPreParsedData(hRawInputDevice); - - if (PreParsedData == IntPtr.Zero) - { - //We are done then. - //Some devices don't have pre-parsed data. - return; - } - - //Get capabilities - HidStatus status = Win32.Function.HidP_GetCaps(PreParsedData, ref iCapabilities); - if (status != HidStatus.HIDP_STATUS_SUCCESS) - { - throw new Exception("HidDevice: HidP_GetCaps failed: " + status.ToString()); - } - - SetInputCapabilitiesDescription(); - - //Get input button caps if needed - if (Capabilities.NumberInputButtonCaps > 0) - { - iInputButtonCapabilities = new HIDP_BUTTON_CAPS[Capabilities.NumberInputButtonCaps]; - ushort buttonCapabilitiesLength = Capabilities.NumberInputButtonCaps; - status = Win32.Function.HidP_GetButtonCaps(HIDP_REPORT_TYPE.HidP_Input, iInputButtonCapabilities, ref buttonCapabilitiesLength, PreParsedData); - if (status != HidStatus.HIDP_STATUS_SUCCESS || buttonCapabilitiesLength != Capabilities.NumberInputButtonCaps) - { - throw new Exception("HidDevice: HidP_GetButtonCaps failed: " + status.ToString()); - } - - ComputeButtonCount(); - } - - //Get input value caps if needed - if (Capabilities.NumberInputValueCaps > 0) - { - iInputValueCapabilities = new HIDP_VALUE_CAPS[Capabilities.NumberInputValueCaps]; - ushort valueCapabilitiesLength = Capabilities.NumberInputValueCaps; - status = Win32.Function.HidP_GetValueCaps(HIDP_REPORT_TYPE.HidP_Input, iInputValueCapabilities, ref valueCapabilitiesLength, PreParsedData); - if (status != HidStatus.HIDP_STATUS_SUCCESS || valueCapabilitiesLength != Capabilities.NumberInputValueCaps) - { - throw new Exception("HidDevice: HidP_GetValueCaps failed: " + status.ToString()); - } - } - } - - - /// - /// Useful for gamepads. - /// - void ComputeButtonCount() - { - ButtonCount = 0; - foreach (HIDP_BUTTON_CAPS bc in iInputButtonCapabilities) - { - if (bc.IsRange) - { - ButtonCount += (bc.Range.UsageMax - bc.Range.UsageMin + 1); - } - } - } - - - /// - /// - /// - void SetInputCapabilitiesDescription() - { - InputCapabilitiesDescription = "[ Input Capabilities ] Button: " + Capabilities.NumberInputButtonCaps + " - Value: " + Capabilities.NumberInputValueCaps + " - Data indices: " + Capabilities.NumberInputDataIndices; - } - - /// - /// - /// - private void SetFriendlyName() - { - //Work out proper suffix for our device root node. - //That allows users to see in a glance what kind of device this is. - string suffix = ""; - Type usageCollectionType = null; - if (Info.dwType == RawInputDeviceType.RIM_TYPEHID) - { - //Process usage page - if (Enum.IsDefined(typeof(UsagePage), Info.hid.usUsagePage)) - { - //We know this usage page, add its name - UsagePage usagePage = (UsagePage)Info.hid.usUsagePage; - suffix += " ( " + usagePage.ToString() + ", "; - usageCollectionType = Utils.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 == RawInputDeviceType.RIM_TYPEKEYBOARD) - { - suffix = " - Keyboard"; - } - else if (Info.dwType == RawInputDeviceType.RIM_TYPEMOUSE) - { - 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 = { '#', '&'}; - string[] 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; - } - } - - } - - /// - /// Dispose is just for unmanaged clean-up. - /// Make sure calling disposed multiple times does not crash. - /// See: http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface/538238#538238 - /// - public void Dispose() - { - Marshal.FreeHGlobal(PreParsedData); - PreParsedData = IntPtr.Zero; - } - - /// - /// Provide a description for the given capabilities. - /// Notably describes axis on a gamepad/joystick. - /// - /// - /// - static public string InputValueCapabilityDescription(HIDP_VALUE_CAPS aCaps) - { - if (!aCaps.IsRange && Enum.IsDefined(typeof(UsagePage), aCaps.UsagePage)) - { - Type usageType = Utils.UsageType((UsagePage)aCaps.UsagePage); - string name = Enum.GetName(usageType, aCaps.NotRange.Usage); - if (name == null) - { - //Could not find that usage in our enum. - //Provide a relevant warning instead. - name = "Usage 0x" + aCaps.NotRange.Usage.ToString("X2") + " not defined in " + usageType.Name; - } - else - { - //Prepend our usage type name - name = usageType.Name + "." + name; - } - return "Input Value: " + name; - } - - return null; - } - - public bool IsGamePad - { - get - { - return ((UsagePage)iCapabilities.UsagePage == UsagePage.GenericDesktopControls && (UsageCollection.GenericDesktop)iCapabilities.Usage == UsageCollection.GenericDesktop.GamePad); - } - } - - - /// - /// Print information about this device to our debug output. - /// - public void DebugWrite() - { - Debug.WriteLine("================ HID ========================================================================================="); - Debug.WriteLine("==== Name: " + Name); - Debug.WriteLine("==== Manufacturer: " + Manufacturer); - Debug.WriteLine("==== Product: " + Product); - Debug.WriteLine("==== VendorID: 0x" + VendorId.ToString("X4")); - Debug.WriteLine("==== ProductID: 0x" + ProductId.ToString("X4")); - Debug.WriteLine("==== Version: " + Version.ToString()); - Debug.WriteLine("=============================================================================================================="); - } - - } - -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e HidEvent.cs --- a/HidEvent.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,598 +0,0 @@ -// -// 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.Windows.Forms; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Text; -using Microsoft.Win32.SafeHandles; -using SharpLib.Win32; -using System.Collections.Generic; -using System.Timers; -using SharpLib.Hid.Usage; - - -namespace SharpLib.Hid -{ - /// - /// We provide utility functions to interpret gamepad dpad state. - /// - public enum DirectionPadState - { - Rest=-1, - Up=0, - UpRight=1, - Right=2, - DownRight=3, - Down=4, - DownLeft=5, - Left=6, - UpLeft=7 - } - - /// - /// Represent a HID event. - /// TODO: Rename this into HidRawInput? - /// - public class HidEvent : IDisposable - { - public bool IsValid { get; private set; } - public bool IsForeground { get; private set; } - public bool IsBackground { get { return !IsForeground; } } - public bool IsMouse { get; private set; } - public bool IsKeyboard { get; private set; } - /// - /// If this not a mouse or keyboard event then it's a generic HID event. - /// - public bool IsGeneric { get; private set; } - public bool IsButtonDown { get { return Usages.Count == 1 && Usages[0] != 0; } } - public bool IsButtonUp { get { return Usages.Count == 0; } } - public bool IsRepeat { get { return RepeatCount != 0; } } - public uint RepeatCount { get; private set; } - - public HidDevice Device { get; private set; } - public RAWINPUT RawInput { get {return iRawInput;} } - private RAWINPUT iRawInput; - - public ushort UsagePage { get; private set; } - public ushort UsageCollection { get; private set; } - public uint UsageId { get { return ((uint)UsagePage << 16 | (uint)UsageCollection); } } - public List Usages { get; private set; } - /// - /// Sorted in the same order as Device.InputValueCapabilities. - /// - public Dictionary UsageValues { get; private set; } - //TODO: We need a collection of input report - public byte[] InputReport { get; private set; } - // - public delegate void HidEventRepeatDelegate(HidEvent aHidEvent); - public event HidEventRepeatDelegate OnHidEventRepeat; - - private System.Timers.Timer Timer { get; set; } - public DateTime Time { get; private set; } - public DateTime OriginalTime { get; private set; } - - //Compute repeat delay and speed based on system settings - //Those computations were taken from the Petzold here: ftp://ftp.charlespetzold.com/ProgWinForms/4%20Custom%20Controls/NumericScan/NumericScan/ClickmaticButton.cs - private int iRepeatDelay = 250 * (1 + SystemInformation.KeyboardDelay); - private int iRepeatSpeed = 405 - 12 * SystemInformation.KeyboardSpeed; - - /// - /// Tells whether this event has already been disposed of. - /// - public bool IsStray { get { return Timer == null; } } - - /// - /// We typically dispose of events as soon as we get the corresponding key up signal. - /// - public void Dispose() - { - Timer.Enabled = false; - Timer.Dispose(); - //Mark this event as a stray - Timer = null; - } - - /// - /// Initialize an HidEvent from a WM_INPUT message - /// - /// Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice - public HidEvent(Message aMessage, HidEventRepeatDelegate aRepeatDelegate) - { - RepeatCount = 0; - IsValid = false; - IsKeyboard = false; - IsGeneric = false; - - Time = DateTime.Now; - OriginalTime = DateTime.Now; - Timer = new System.Timers.Timer(); - Timer.Elapsed += (sender, e) => OnRepeatTimerElapsed(sender, e, this); - Usages = new List(); - UsageValues = new Dictionary(); - 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 - IntPtr rawInputBuffer = IntPtr.Zero; - - try - { - //Fetch raw input - iRawInput = new RAWINPUT(); - if (!Win32.RawInput.GetRawInputData(aMessage.LParam, ref iRawInput, ref rawInputBuffer)) - { - Debug.WriteLine("GetRawInputData failed!"); - return; - } - - //Our device can actually be null. - //This is notably happening for some keyboard events - if (RawInput.header.hDevice != IntPtr.Zero) - { - //Get various information about this HID device - Device = new HidDevice(RawInput.header.hDevice); - } - - if (RawInput.header.dwType == Win32.RawInputDeviceType.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 = Device.Info.hid.usUsagePage; - UsageCollection = Device.Info.hid.usUsage; - - 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 - InputReport = 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 (int i = 0; i < RawInput.hid.dwCount; i++) - { - //Compute the address from which to copy our HID input - int hidInputOffset = 0; - unsafe - { - byte* 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), InputReport, 0, (int)RawInput.hid.dwSizeHid); - // - ProcessInputReport(InputReport); - } - } - else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEMOUSE) - { - IsMouse = true; - - Debug.WriteLine("WM_INPUT source device is Mouse."); - // do mouse handling... - } - else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD) - { - IsKeyboard = true; - - Debug.WriteLine("WM_INPUT source device is Keyboard."); - // do keyboard handling... - if (Device != null) - { - Debug.WriteLine("Type: " + Device.Info.keyboard.dwType.ToString()); - Debug.WriteLine("SubType: " + Device.Info.keyboard.dwSubType.ToString()); - Debug.WriteLine("Mode: " + Device.Info.keyboard.dwKeyboardMode.ToString()); - Debug.WriteLine("Number of function keys: " + Device.Info.keyboard.dwNumberOfFunctionKeys.ToString()); - Debug.WriteLine("Number of indicators: " + Device.Info.keyboard.dwNumberOfIndicators.ToString()); - Debug.WriteLine("Number of keys total: " + Device.Info.keyboard.dwNumberOfKeysTotal.ToString()); - } - } - } - finally - { - //Always executed when leaving our try block - Marshal.FreeHGlobal(rawInputBuffer); - } - - // - if (IsButtonDown) - { - //TODO: Make this optional - //StartRepeatTimer(iRepeatDelay); - } - - IsValid = true; - } - - /// - /// - /// - private void ProcessInputReport(byte[] aInputReport) - { - //Print HID input report in our debug output - //string hidDump = "HID input report: " + InputReportString(); - //Debug.WriteLine(hidDump); - - //Get all our usages, those are typically the buttons currently pushed on a gamepad. - //For a remote control it's usually just the one button that was pushed. - GetUsages(aInputReport); - - //Now process direction pad (d-pad, dpad) and axes - GetUsageValues(aInputReport); - } - - /// - /// Typically fetches values of a joystick/gamepad axis and dpad directions. - /// - /// - private void GetUsageValues(byte[] aInputReport) - { - if (Device.InputValueCapabilities == null) - { - return; - } - - foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) - { - if (caps.IsRange) - { - //What should we do with those guys? - continue; - } - - //Now fetch and add our usage value - uint usageValue = 0; - Win32.HidStatus status = Win32.Function.HidP_GetUsageValue(Win32.HIDP_REPORT_TYPE.HidP_Input, caps.UsagePage, caps.LinkCollection, caps.NotRange.Usage, ref usageValue, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); - if (status == Win32.HidStatus.HIDP_STATUS_SUCCESS) - { - UsageValues[caps]=usageValue; - } - } - } - - /// - /// Get all our usages, those are typically the buttons currently pushed on a gamepad. - /// For a remote control it's usually just the one button that was pushed. - /// - private void GetUsages(byte[] aInputReport) - { - //Do proper parsing of our HID report - //First query our usage count - uint usageCount = 0; - Win32.USAGE_AND_PAGE[] usages = null; - Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); - if (status == Win32.HidStatus.HIDP_STATUS_BUFFER_TOO_SMALL) - { - //Allocate a large enough buffer - usages = new Win32.USAGE_AND_PAGE[usageCount]; - //...and fetch our usages - status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, Device.PreParsedData, aInputReport, (uint)aInputReport.Length); - if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS) - { - Debug.WriteLine("Second pass could not parse HID data: " + status.ToString()); - } - } - else if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS) - { - Debug.WriteLine("First pass could not parse HID data: " + status.ToString()); - } - - Debug.WriteLine("Usage count: " + usageCount.ToString()); - - //Copy usages into this event - if (usages != null) - { - foreach (USAGE_AND_PAGE up in usages) - { - //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(up.Usage); - } - } - } - - /// - /// - /// - /// - /// - /// - public uint GetUsageValue(ushort aUsagePage, ushort aUsage) - { - foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) - { - if (caps.IsRange) - { - //What should we do with those guys? - continue; - } - - //Check if we have a match - if (caps.UsagePage == aUsagePage && caps.NotRange.Usage == aUsage) - { - return UsageValues[caps]; - } - } - - return 0; - } - - /// - /// - /// - /// - /// - /// - public int GetValueCapabilitiesIndex(ushort aUsagePage, ushort aUsage) - { - int i = -1; - foreach (HIDP_VALUE_CAPS caps in Device.InputValueCapabilities) - { - i++; - if (caps.IsRange) - { - //What should we do with those guys? - continue; - } - - //Check if we have a match - if (caps.UsagePage == aUsagePage && caps.NotRange.Usage == aUsage) - { - return i; - } - } - - return i; - } - - - /// - /// TODO: Move this to another level? - /// - /// - public void StartRepeatTimer(double aInterval) - { - if (Timer == null) - { - return; - } - Timer.Enabled = false; - //Initial delay do not use auto reset - //After our initial delay however we do setup our timer one more time using auto reset - Timer.AutoReset = (RepeatCount != 0); - Timer.Interval = aInterval; - Timer.Enabled = true; - } - - static private void OnRepeatTimerElapsed(object sender, ElapsedEventArgs e, HidEvent aHidEvent) - { - if (aHidEvent.IsStray) - { - //Skip events if canceled - return; - } - - aHidEvent.RepeatCount++; - aHidEvent.Time = DateTime.Now; - if (aHidEvent.RepeatCount == 1) - { - //Re-Start our timer only after the initial delay - aHidEvent.StartRepeatTimer(aHidEvent.iRepeatSpeed); - } - - //Broadcast our repeat event - aHidEvent.OnHidEventRepeat(aHidEvent); - } - - /// - /// Provide the state of the dpad or hat switch if any. - /// If no dpad is found we return 'at rest'. - /// - /// - public DirectionPadState GetDirectionPadState() - { - int index=GetValueCapabilitiesIndex((ushort)Hid.UsagePage.GenericDesktopControls, (ushort)GenericDesktop.HatSwitch); - if (index < 0) - { - //No hat switch found - return DirectionPadState.Rest; - } - - HIDP_VALUE_CAPS caps=Device.InputValueCapabilities[index]; - if (caps.IsRange) - { - //Defensive - return DirectionPadState.Rest; - } - - uint dpadUsageValue = UsageValues[caps]; - - if (dpadUsageValue < caps.LogicalMin || dpadUsageValue > caps.LogicalMax) - { - //Out of range means at rest - return DirectionPadState.Rest; - } - - //Normalize value to start at zero - //TODO: more error check here? - DirectionPadState res = (DirectionPadState)((int)dpadUsageValue - caps.LogicalMin); - return res; - } - - /// - /// Print information about this device to our debug output. - /// - public void DebugWrite() - { - if (!IsValid) - { - Debug.WriteLine("==== Invalid HidEvent"); - return; - } - - if (Device!=null) - { - Device.DebugWrite(); - } - - if (IsGeneric) Debug.WriteLine("==== Generic"); - if (IsKeyboard) Debug.WriteLine("==== Keyboard"); - if (IsMouse) Debug.WriteLine("==== Mouse"); - Debug.WriteLine("==== Foreground: " + IsForeground.ToString()); - Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4")); - Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4")); - Debug.WriteLine("==== InputReport: 0x" + InputReportString()); - foreach (ushort usage in Usages) - { - Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4")); - } - } - - /// - /// - /// - /// - public string InputReportString() - { - if (InputReport == null) - { - return "null"; - } - - string hidDump = ""; - foreach (byte b in InputReport) - { - hidDump += b.ToString("X2"); - } - return hidDump; - } - - - /// - /// Create a list view item describing this HidEvent - /// - /// - public ListViewItem ToListViewItem() - { - string usageText = ""; - - foreach (ushort usage in Usages) - { - if (usageText != "") - { - //Add a separator - usageText += ", "; - } - - UsagePage usagePage = (UsagePage)UsagePage; - switch (usagePage) - { - case Hid.UsagePage.Consumer: - usageText += ((ConsumerControl)usage).ToString(); - break; - - case Hid.UsagePage.WindowsMediaCenterRemoteControl: - usageText += ((WindowsMediaCenterRemoteControl)usage).ToString(); - break; - - default: - usageText += usage.ToString("X2"); - break; - } - } - - //If we are a gamepad display axis and dpad values - if (Device.IsGamePad) - { - //uint dpadUsageValue = GetUsageValue((ushort)Hid.UsagePage.GenericDesktopControls, (ushort)Hid.Usage.GenericDesktop.HatSwitch); - //usageText = dpadUsageValue.ToString("X") + " (dpad), " + usageText; - - if (usageText != "") - { - //Add a separator - usageText += " (Buttons)"; - } - - if (usageText != "") - { - //Add a separator - usageText += ", "; - } - - usageText += GetDirectionPadState().ToString(); - - foreach (KeyValuePair entry in UsageValues) - { - if (entry.Key.IsRange) - { - continue; - } - - Type usageType = Utils.UsageType((UsagePage)entry.Key.UsagePage); - if (usageType == null) - { - //TODO: check why this is happening on Logitech rumble gamepad 2. - //Probably some of our axis are hiding in there. - continue; - } - string name = Enum.GetName(usageType, entry.Key.NotRange.Usage); - - if (usageText != "") - { - //Add a separator - usageText += ", "; - } - usageText += entry.Value.ToString("X") + " ("+ name +")"; - } - } - - //Now create our list item - ListViewItem item = new ListViewItem(new[] { usageText, InputReportString(), UsagePage.ToString("X2"), UsageCollection.ToString("X2"), RepeatCount.ToString(), Time.ToString("HH:mm:ss:fff") }); - return item; - } - - } - -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e HidHandler.cs --- a/HidHandler.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -// -// 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.Windows.Forms; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Text; -using Microsoft.Win32.SafeHandles; -using SharpLib.Win32; -using System.Collections.Generic; - - -namespace SharpLib.Hid -{ - /// - /// Our HID handler manages raw input registrations, processes WM_INPUT messages and broadcasts HID events in return. - /// - public class HidHandler - { - public delegate void HidEventHandler(object aSender, HidEvent aHidEvent); - public event HidEventHandler OnHidEvent; - List iHidEvents; - - - public bool IsRegistered { get; private set; } - - public HidHandler(RAWINPUTDEVICE[] aRawInputDevices) - { - iHidEvents=new List(); - IsRegistered = Function.RegisterRawInputDevices(aRawInputDevices, (uint)aRawInputDevices.Length, (uint)Marshal.SizeOf(aRawInputDevices[0])); - } - - /// - /// Process a WM_INPUT message. - /// - /// - public void ProcessInput(ref Message aMessage) - { - if (aMessage.Msg != Const.WM_INPUT) - { - //We only process WM_INPUT messages - return; - } - - HidEvent hidEvent = new HidEvent(aMessage, OnHidEventRepeat); - hidEvent.DebugWrite(); - - if (!hidEvent.IsValid || !hidEvent.IsGeneric) - { - Debug.WriteLine("Skipping HID message."); - return; - } - - // - if (hidEvent.IsButtonUp) - { - //This is a key up event - //We need to discard any events belonging to the same page and collection - for (int i = (iHidEvents.Count-1); i >= 0; i--) - { - if (iHidEvents[i].UsageId == hidEvent.UsageId) - { - iHidEvents[i].Dispose(); - iHidEvents.RemoveAt(i); - } - } - } - else - { - //Keep that event until we get a key up message - iHidEvents.Add(hidEvent); - } - - //Broadcast our events - OnHidEvent(this, hidEvent); - } - - public void OnHidEventRepeat(HidEvent aHidEvent) - { - //Broadcast our events - OnHidEvent(this, aHidEvent); - } - - } - -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e HidUsageTables.cs --- a/HidUsageTables.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,928 +0,0 @@ -// -// 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 . -// - -namespace SharpLib.Hid -{ - /// - /// From USB HID usage tables. - /// http://www.usb.org/developers/hidpage#HID_Usage - /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf - /// - public enum UsagePage : ushort - { - Undefined = 0, - GenericDesktopControls, - SimulationControls, - VirtualRealityControls, - SportControls, - GameControls, - GenericDeviceControls, - Keyboard, - LightEmittingDiode, - Button, - Ordinal, - Telephony, - Consumer, - Digitiser, - PhysicalInterfaceDevice = 0x0f, - Unicode = 0x10, - AlphaNumericDisplay = 0x14, - MedicalInstruments = 0x40, - MonitorPage0 = 0x80, - MonitorPage1, - MonitorPage2, - MonitorPage3, - PowerPage0, - PowerPage1, - PowerPage2, - PowerPage3, - BarCodeScanner = 0x8c, - Scale, - MagneticStripeReader, - ReservedPointOfSale, - CameraControl, - Arcade, - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx - WindowsMediaCenterRemoteControl = 0xffbc, - TerraTecRemote = 0xffcc - } - - /// - /// Usage Collections are special values from our Usage enumeration. - /// Thus they are also part of the corresponding Usage enumeration. - /// - namespace UsageCollection - { - /// - /// Usage Collection for usage page GenericDesktopControls. - /// - public enum GenericDesktop : ushort - { - Pointer = 0x01, - Mouse = 0x02, - Joystick = 0x04, - GamePad = 0x05, - Keyboard = 0x06, - KeyPad = 0x07, - MultiAxisController = 0x08, - TabletPCSystemControls = 0x09, - SystemControl = 0x80 - } - - /// - /// Usage Collection for usage page Consumer. - /// - public enum Consumer : ushort - { - ConsumerControl = 0x01, - NumericKeyPad = 0x02, - ProgrammableButtons = 0x03, - Microphone = 0x04, - Headphone = 0x05, - GraphicEqualizer = 0x06, - FunctionButtons = 0x36, - Selection = 0x80, - MediaSelection = 0x0087, - SelectDisc = 0x00BA, - PlaybackSpeed = 0x00F1, - Proximity = 0x0109, - SpeakerSystem = 0x0160, - ChannelLeft = 0x0161, - ChannelRight = 0x0162, - ChannelCenter = 0x0163, - ChannelFront = 0x0164, - ChannelCenterFront = 0x0165, - ChannelSide = 0x0166, - ChannelSurrond = 0x0167, - ChannelLowFrequencyEnhancement = 0x0168, - ChannelTop = 0x0169, - ChannelUnknown = 0x016A, - ApplicationLaunchButtons = 0x016A, - GenericGuiApplicationControls = 0x0200, - } - - - public enum WindowsMediaCenter : ushort - { - WindowsMediaCenterRemoteControl = 0x88 - } - - } - - - - namespace Usage - { - /// - /// - /// - public enum WindowsMediaCenterRemoteControl : ushort - { - /// - /// Not defined by the Microsoft specs. - /// - Null = 0x00, - GreenStart = 0x0D, - ClosedCaptioning = 0x2B, - Teletext = 0x5A, - TeletextRed = 0x5B, - TeletextGreen = 0x5C, - TeletextYellow = 0x5D, - TeletextBlue = 0x5E, - LiveTv = 0x25, - Tv = 0x46, - Music = 0x47, - RecordedTv = 0x48, - Pictures = 0x49, - Videos = 0x4A, - FmRadio = 0x50, - Extras = 0x3C, - ExtrasApp = 0x3D, - DvdMenu = 0x24, - DvdAngle = 0x4B, - DvdAudio = 0x4C, - DvdSubtitle = 0x4D, - /// - /// First press action: Ejects a DVD drive. - /// - /// Second press action: Repeats first press action. - /// - /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application. - /// - Eject = 0x28, - DvdTopMenu = 0x43, - /// - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific - /// Collection (page 0xFFBC, usage 0x88). - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08). - /// - /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks. - /// - Ext0 = 0x32, - /// - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific - /// Collection (page 0xFFBC, usage 0x88). - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08). - /// - /// According to HP specs it plays a slide show of all the pictures on your hard disk drive. - /// - Ext1 = 0x33, - /// - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific - /// Collection (page 0xFFBC, usage 0x88). - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08). - /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310). - /// - Ext2 = 0x34, - /// - /// First press action: Generates EXTn HID message in the Media Center Vendor Specific - /// Collection (page 0xFFBC, usage 0x88). - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08). - /// - Ext3 = 0x35, - Ext4 = 0x36, - Ext5 = 0x37, - Ext6 = 0x38, - Ext7 = 0x39, - Ext8 = 0x3A, - Ext9 = 0x80, - Ext10 = 0x81, - Ext11 = 0x6F, - Zoom = 0x27, - ChannelInput = 0x42, - SubAudio = 0x2D, - Channel10 = 0x3E, - Channel11 = 0x3F, - Channel12 = 0x40, - /// - /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific - /// Collection. This button is intended to control the front panel display of home entertainment - /// computers. When this button is pressed, the display could be turned on or off, or the display - /// mode could change. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application. - /// - Display = 0x4F, - /// - /// First press action: To be determined. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - Kiosk = 0x6A, - NetworkSelection = 0x2C, - BlueRayTool = 0x78, - ChannelInfo = 0x41, - VideoSelection = 0x61 - } - - /// - /// Those codes come from experimenting with HP remotes. - /// - public enum HpWindowsMediaCenterRemoteControl : ushort - { - /// - /// Displays visual imagery that is synchronized to the sound of your music tracks. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08). - /// - /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks. - /// - Visualization = WindowsMediaCenterRemoteControl.Ext0, - /// - /// Plays a slide show of all the pictures on your hard disk drive. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08). - /// - /// According to HP specs it plays a slide show of all the pictures on your hard disk drive. - /// - SlideShow = WindowsMediaCenterRemoteControl.Ext1, - /// - /// Eject optical drive. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08). - /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310). - /// - HpEject = WindowsMediaCenterRemoteControl.Ext2, - /// - /// Not sure what this should do. - /// - /// Second press action: Repeats message. - /// - /// Auto-repeat: No - /// - /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08). - /// - InputSelection = WindowsMediaCenterRemoteControl.Ext3, - } - - /// - /// Usage Table for Consumer Controls - /// 0x0C 0X01 - /// - public enum ConsumerControl : ushort - { - Null = 0x00, - ConsumerControl = 0x01, - NumericKeyPad = 0x02, - ProgrammableButtons = 0x03, - Microphone = 0x04, - Headphone = 0x05, - GraphicEqualizer = 0x06, - Plus10 = 0x20, - Plus100 = 0x21, - AmPm = 0x22, - Power = 0x30, - Reset = 0x31, - Sleep = 0x32, - SleepAfter = 0x33, - SleepMode = 0x34, - Illumination = 0x35, - FunctionButtons = 0x36, - Menu = 0x40, - MenuPick = 0x41, - MenuUp = 0x42, - MenuDown = 0x43, - MenuLeft = 0x44, - MenuRight = 0x45, - MenuEscape = 0x46, - MenuValueIncrease = 0x47, - MenuValueDecrease = 0x48, - DataOnScreen = 0x60, - ClosedCaption = 0x61, - ClosedCaptionSelect = 0x62, - VcrTv = 0x63, - BroadcastMode = 0x64, - Snapshot = 0x65, - Still = 0x66, - Selection = 0x80, - AssignSelection = 0x81, - ModeStep = 0x82, - RecallLast = 0x83, - EnterChannel = 0x84, - OrderMovie = 0x85, - Channel = 0x86, - MediaSelection = 0x87, - MediaSelectComputer = 0x88, - MediaSelectTv = 0x89, - MediaSelectWww = 0x8A, - MediaSelectDvd = 0x8B, - MediaSelectTelephone = 0x8C, - MediaSelectProgramGuide = 0x8D, - MediaSelectVideoPhone = 0x8E, - MediaSelectGames = 0x8F, - MediaSelectMessages = 0x90, - MediaSelectCd = 0x91, - MediaSelectVcr = 0x92, - MediaSelectTuner = 0x93, - Quit = 0x94, - Help = 0x95, - MediaSelectTape = 0x96, - MediaSelectCable = 0x97, - MediaSelectSatellite = 0x98, - MediaSelectSecurity = 0x99, - MediaSelectHome = 0x9A, - MediaSelectCall = 0x9B, - ChannelIncrement = 0x9C, - ChannelDecrement = 0x9D, - MediaSelectSap = 0x9E, - VcrPlus = 0xA0, - Once = 0xA1, - Daily = 0xA2, - Weekly = 0xA3, - Monthly = 0xA4, - Play = 0xB0, - Pause = 0xB1, - Record = 0xB2, - FastForward = 0xB3, - Rewind = 0xB4, - ScanNextTrack = 0xB5, - ScanPreviousTrack = 0xB6, - Stop = 0xB7, - Eject = 0xB8, - RandomPlay = 0xB9, - SelectDisc = 0xBA, - EnterDisc = 0xBB, - Repeat = 0xBC, - Tracking = 0xBD, - TrackNormal = 0xBE, - SlowTracking = 0xBF, - FrameForward = 0xC0, - FrameBack = 0xC1, - Mark = 0xC2, - ClearMark = 0xC3, - RepeatFromMark = 0xC4, - ReturnToMark = 0xC5, - SearchMarkForward = 0xC6, - SearchMarkBackwards = 0xC7, - CounterReset = 0xC8, - ShowCounter = 0xC9, - TrackingIncrement = 0xCA, - TrackingDecrement = 0xCB, - StopEject = 0xCC, - PlayPause = 0xCD, - PlaySkip = 0xCE, - Volume = 0xE0, - Balance = 0xE1, - Mute = 0xE2, - Bass = 0xE3, - Treble = 0xE4, - BassBoost = 0xE5, - SurroundMode = 0xE6, - Loudness = 0xE7, - Mpx = 0xE8, - VolumeIncrement = 0xE9, - VolumeDecrement = 0xEA, - SpeedSelect = 0xF0, - PlaybackSpeed = 0xF1, - StandardPlay = 0xF2, - LongPlay = 0xF3, - ExtendedPlay = 0xF4, - Slow = 0xF5, - FanEnable = 0x100, - FanSpeed = 0x101, - LightEnable = 0x102, - LightIlluminationLevel = 0x103, - ClimateControlEnable = 0x104, - RoomTemperature = 0x105, - SecurityEnable = 0x106, - FireAlarm = 0x107, - PoliceAlarm = 0x108, - Proximity = 0x109, - Motion = 0x10A, - DuressAlarm = 0x10B, - HoldupAlarm = 0x10C, - MedicalAlarm = 0x10D, - BalanceRight = 0x150, - BalanceLeft = 0x151, - BassIncrement = 0x152, - BassDecrement = 0x153, - TrebleIncrement = 0x154, - TrebleDecrement = 0x155, - SpeakerSystem = 0x160, - ChannelLeft = 0x161, - ChannelRight = 0x162, - ChannelCenter = 0x163, - ChannelFront = 0x164, - ChannelCenterFront = 0x165, - ChannelSide = 0x166, - ChannelSurround = 0x167, - ChannelLowFrequencyEnhancement = 0x168, - ChannelTop = 0x169, - ChannelUnknown = 0x16A, - SubChannel = 0x170, - SubChannelIncrement = 0x171, - SubChannelDecrement = 0x172, - AlternateAudioIncrement = 0x173, - AlternateAudioDecrement = 0x174, - ApplicationLaunchButtons = 0x180, - AppLaunchLaunchButtonConfigurationTool = 0x181, - AppLaunchProgrammableButtonConfiguration = 0x182, - AppLaunchConsumerControlConfiguration = 0x183, - AppLaunchWordProcessor = 0x184, - AppLaunchTextEditor = 0x185, - AppLaunchSpreadsheet = 0x186, - AppLaunchGraphicsEditor = 0x187, - AppLaunchPresentationApp = 0x188, - AppLaunchDatabaseApp = 0x189, - AppLaunchEmailReader = 0x18A, - AppLaunchNewsreader = 0x18B, - AppLaunchVoicemail = 0x18C, - AppLaunchContactsAddressBook = 0x18D, - AppLaunchCalendarSchedule = 0x18E, - AppLaunchTaskProjectManager = 0x18F, - AppLaunchLogJournalTimecard = 0x190, - AppLaunchCheckbookFinance = 0x191, - AppLaunchCalculator = 0x192, - AppLaunchAVCapturePlayback = 0x193, - AppLaunchLocalMachineBrowser = 0x194, - AppLaunchLanWanBrowser = 0x195, - AppLaunchInternetBrowser = 0x196, - AppLaunchRemoteNetworkingIspConnect = 0x197, - AppLaunchNetworkConference = 0x198, - AppLaunchNetworkChat = 0x199, - AppLaunchTelephonyDialer = 0x19A, - AppLaunchLogon = 0x19B, - AppLaunchLogoff = 0x19C, - AppLaunchLogonLogoff = 0x19D, - AppLaunchTerminalLockScreensaver = 0x19E, - AppLaunchControlPanel = 0x19F, - AppLaunchCommandLineProcessorRun = 0x1A0, - AppLaunchProcessTaskManager = 0x1A1, - AppLaunchSelectTaskApplication = 0x1A2, - AppLaunchNextTaskApplication = 0x1A3, - AppLaunchPreviousTaskApplication = 0x1A4, - AppLaunchPreemptiveHaltTaskApplication = 0x1A5, - AppLaunchIntegratedHelpCenter = 0x1A6, - AppLaunchDocuments = 0x1A7, - AppLaunchThesaurus = 0x1A8, - AppLaunchDictionary = 0x1A9, - AppLaunchDesktop = 0x1AA, - AppLaunchSpellCheck = 0x1AB, - AppLaunchGrammarCheck = 0x1AC, - AppLaunchWirelessStatus = 0x1AD, - AppLaunchKeyboardLayout = 0x1AE, - AppLaunchVirusProtection = 0x1AF, - AppLaunchEncryption = 0x1B0, - AppLaunchScreenSaver = 0x1B1, - AppLaunchAlarms = 0x1B2, - AppLaunchClock = 0x1B3, - AppLaunchFileBrowser = 0x1B4, - AppLaunchPowerStatus = 0x1B5, - AppLaunchImageBrowser = 0x1B6, - AppLaunchAudioBrowser = 0x1B7, - AppLaunchMovieBrowser = 0x1B8, - AppLaunchDigitalRightsManager = 0x1B9, - AppLaunchDigitalWallet = 0x1BA, - AppLaunchInstantMessaging = 0x1BC, - AppLaunchOemFeaturesTipsTutorialBrowser = 0x1BD, - AppLaunchOemHelp = 0x1BE, - AppLaunchOnlineCommunity = 0x1BF, - AppLaunchEntertainmentContentBrowser = 0x1C0, - AppLaunchOnlineShoppingBrowser = 0x1C1, - AppLaunchSmartcardInformationHelp = 0x1C2, - AppLaunchMarketMonitorFinanceBrowser = 0x1C3, - AppLaunchCustomizedCorporateNewsBrowser = 0x1C4, - AppLaunchOnlineActivityBrowser = 0x1C5, - AppLaunchResearchSearchBrowser = 0x1C6, - AppLaunchAudioPlayer = 0x1C7, - GenericGuiApplicationControls = 0x200, - AppCtrlNew = 0x201, - AppCtrlOpen = 0x202, - AppCtrlClose = 0x203, - AppCtrlExit = 0x204, - AppCtrlMaximize = 0x205, - AppCtrlMinimize = 0x206, - AppCtrlSave = 0x207, - AppCtrlPrint = 0x208, - AppCtrlProperties = 0x209, - AppCtrlUndo = 0x21A, - AppCtrlCopy = 0x21B, - AppCtrlCut = 0x21C, - AppCtrlPaste = 0x21D, - AppCtrlSelectAll = 0x21E, - AppCtrlFind = 0x21F, - AppCtrlFindAndReplace = 0x220, - AppCtrlSearch = 0x221, - AppCtrlGoTo = 0x222, - AppCtrlHome = 0x223, - AppCtrlBack = 0x224, - AppCtrlForward = 0x225, - AppCtrlStop = 0x226, - AppCtrlRefresh = 0x227, - AppCtrlPreviousLink = 0x228, - AppCtrlNextLink = 0x229, - AppCtrlBookmarks = 0x22A, - AppCtrlHistory = 0x22B, - AppCtrlSubscriptions = 0x22C, - AppCtrlZoomIn = 0x22D, - AppCtrlZoomOut = 0x22E, - AppCtrlZoom = 0x22F, - AppCtrlFullScreenView = 0x230, - AppCtrlNormalView = 0x231, - AppCtrlViewToggle = 0x232, - AppCtrlScrollUp = 0x233, - AppCtrlScrollDown = 0x234, - AppCtrlScroll = 0x235, - AppCtrlPanLeft = 0x236, - AppCtrlPanRight = 0x237, - AppCtrlPan = 0x238, - AppCtrlNewWindow = 0x239, - AppCtrlTileHorizontally = 0x23A, - AppCtrlTileVertically = 0x23B, - AppCtrlFormat = 0x23C, - AppCtrlEdit = 0x23D, - AppCtrlBold = 0x23E, - AppCtrlItalics = 0x23F, - AppCtrlUnderline = 0x240, - AppCtrlStrikethrough = 0x241, - AppCtrlSubscript = 0x242, - AppCtrlSuperscript = 0x243, - AppCtrlAllCaps = 0x244, - AppCtrlRotate = 0x245, - AppCtrlResize = 0x246, - AppCtrlFlipHorizontal = 0x247, - AppCtrlFlipVertical = 0x248, - AppCtrlMirrorHorizontal = 0x249, - AppCtrlMirrorVertical = 0x24A, - AppCtrlFontSelect = 0x24B, - AppCtrlFontColor = 0x24C, - AppCtrlFontSize = 0x24D, - AppCtrlJustifyLeft = 0x24E, - AppCtrlJustifyCenterH = 0x24F, - AppCtrlJustifyRight = 0x250, - AppCtrlJustifyBlockH = 0x251, - AppCtrlJustifyTop = 0x252, - AppCtrlJustifyCenterV = 0x253, - AppCtrlJustifyBottom = 0x254, - AppCtrlJustifyBlockV = 0x255, - AppCtrlIndentDecrease = 0x256, - AppCtrlIndentIncrease = 0x257, - AppCtrlNumberedList = 0x258, - AppCtrlRestartNumbering = 0x259, - AppCtrlBulletedList = 0x25A, - AppCtrlPromote = 0x25B, - AppCtrlDemote = 0x25C, - AppCtrlYes = 0x25D, - AppCtrlNo = 0x25E, - AppCtrlCancel = 0x25F, - AppCtrlCatalog = 0x260, - AppCtrlBuyCheckout = 0x261, - AppCtrlAddToCart = 0x262, - AppCtrlExpand = 0x263, - AppCtrlExpandAll = 0x264, - AppCtrlCollapse = 0x265, - AppCtrlCollapseAll = 0x266, - AppCtrlPrintPreview = 0x267, - AppCtrlPasteSpecial = 0x268, - AppCtrlInsertMode = 0x269, - AppCtrlDelete = 0x26A, - AppCtrlLock = 0x26B, - AppCtrlUnlock = 0x26C, - AppCtrlProtect = 0x26D, - AppCtrlUnprotect = 0x26E, - AppCtrlAttachComment = 0x26F, - AppCtrlDeleteComment = 0x270, - AppCtrlViewComment = 0x271, - AppCtrlSelectWord = 0x272, - AppCtrlSelectSentence = 0x273, - AppCtrlSelectParagraph = 0x274, - AppCtrlSelectColumn = 0x275, - AppCtrlSelectRow = 0x276, - AppCtrlSelectTable = 0x277, - AppCtrlSelectObject = 0x278, - AppCtrlRedoRepeat = 0x279, - AppCtrlSort = 0x27A, - AppCtrlSortAscending = 0x27B, - AppCtrlSortDescending = 0x27C, - AppCtrlFilter = 0x27D, - AppCtrlSetClock = 0x27E, - AppCtrlViewClock = 0x27F, - AppCtrlSelectTimeZone = 0x280, - AppCtrlEditTimeZones = 0x281, - AppCtrlSetAlarm = 0x282, - AppCtrlClearAlarm = 0x283, - AppCtrlSnoozeAlarm = 0x284, - AppCtrlResetAlarm = 0x285, - AppCtrlSynchronize = 0x286, - AppCtrlSendReceive = 0x287, - AppCtrlSendTo = 0x288, - AppCtrlReply = 0x289, - AppCtrlReplyAll = 0x28A, - AppCtrlForwardMsg = 0x28B, - AppCtrlSend = 0x28C, - AppCtrlAttachFile = 0x28D, - AppCtrlUpload = 0x28E, - AppCtrlDownloadSaveTargetAs = 0x28F, - AppCtrlSetBorders = 0x290, - AppCtrlInsertRow = 0x291, - AppCtrlInsertColumn = 0x292, - AppCtrlInsertFile = 0x293, - AppCtrlInsertPicture = 0x294, - AppCtrlInsertObject = 0x295, - AppCtrlInsertSymbol = 0x296, - AppCtrlSaveAndClose = 0x297, - AppCtrlRename = 0x298, - AppCtrlMerge = 0x299, - AppCtrlSplit = 0x29A, - AppCtrlDistributeHorizontally = 0x29B, - AppCtrlDistributeVertically = 0x29C - } - - /// - /// - /// - enum GenericDesktop : ushort - { - Null = 0x00, - Pointer = 0x01, - Mouse = 0x02, - Joystick = 0x04, - GamePad = 0x05, - Keyboard = 0x06, - Keypad = 0x07, - MultiAxisController = 0x08, - TabletPcSystemControls = 0x09, - X = 0x30, - Y = 0x31, - Z = 0x32, - Rx = 0x33, - Ry = 0x34, - Rz = 0x35, - Slider = 0x36, - Dial = 0x37, - Wheel = 0x38, - HatSwitch = 0x39, - CountedBuffer = 0x3A, - ByteCount = 0x3B, - MotionWakeup = 0x3C, - Start = 0x3D, - Select = 0x3E, - Vx = 0x40, - Vy = 0x41, - Vz = 0x42, - Vbrx = 0x43, - Vbry = 0x44, - Vbrz = 0x45, - Vno = 0x46, - SystemControl = 0x80, - SystemPowerDown = 0x81, - SystemSleep = 0x82, - SystemWakeUp = 0x83, - SystemContextMenu = 0x84, - SystemMainMenu = 0x85, - SystemAppMenu = 0x86, - SystemMenuHelp = 0x87, - SystemMenuExit = 0x88, - SystemMenuSelect = 0x89, - SystemMenuRight = 0x8A, - SystemMenuLeft = 0x8B, - SystemMenuUp = 0x8C, - SystemMenuDown = 0x8D, - SystemColdRestart = 0x8E, - SystemWarmRestart = 0x8F, - DPadUp = 0x90, - DPadDown = 0x91, - DPadRight = 0x92, - DPadLeft = 0x93, - SystemDock = 0xA0, - SystemUndock = 0xA1, - SystemSetup = 0xA2, - SystemBreak = 0xA3, - SystemDebuggerBreak = 0xA4, - ApplicationBreak = 0xA5, - ApplicationDebuggerBreak = 0xA6, - SystemSpeakerMute = 0xA7, - SystemHibernate = 0xA8, - SystemDisplayInvert = 0xB0, - SystemDisplayInternal = 0xB1, - SystemDisplayExternal = 0xB2, - SystemDisplayBoth = 0xB3, - SystemDisplayDual = 0xB4, - SystemDisplayToggleIntExt = 0xB5, - SystemDisplaySwapPrimarySecondary = 0xB6, - SystemDisplayLcdAutoscale = 0xB7 - } - - /// - /// - /// - enum SimulationControl : ushort - { - Null = 0x00, - FlightSimulationDevice = 0x01, - AutomobileSimulationDevice = 0x02, - TankSimulationDevice = 0x03, - SpaceshipSimulationDevice = 0x04, - SubmarineSimulationDevice = 0x05, - SailingSimulationDevice = 0x06, - MotorcycleSimulationDevice = 0x07, - SportsSimulationDevice = 0x08, - AirplaneSimulationDevice = 0x09, - HelicopterSimulationDevice = 0x0A, - MagicCarpetSimulationDevice = 0x0B, - BicycleSimulationDevice = 0x0C, - FlightControlStick = 0x20, - FlightStick = 0x21, - CyclicControl = 0x22, - CyclicTrim = 0x23, - FlightYoke = 0x24, - TrackControl = 0x25, - Aileron = 0xB0, - AileronTrim = 0xB1, - AntiTorqueControl = 0xB2, - AutopilotEnable = 0xB3, - ChaffRelease = 0xB4, - CollectiveControl = 0xB5, - DiveBrake = 0xB6, - ElectronicCountermeasures = 0xB7, - Elevator = 0xB8, - ElevatorTrim = 0xB9, - Rudder = 0xBA, - Throttle = 0xBB, - FlightCommunications = 0xBC, - FlareRelease = 0xBD, - LandingGear = 0xBE, - ToeBrake = 0xBF, - Trigger = 0xC0, - WeaponsArm = 0xC1, - WeaponsSelect = 0xC2, - WingFlaps = 0xC3, - Accelerator = 0xC4, - Brake = 0xC5, - Clutch = 0xC6, - Shifter = 0xC7, - Steering = 0xC8, - TurretDirection = 0xC9, - BarrelElevation = 0xCA, - DivePlane = 0xCB, - Ballast = 0xCC, - BicycleCrank = 0xCD, - HandleBars = 0xCE, - FrontBrake = 0xCF, - RearBrake = 0xD0 - } - - /// - /// - /// - enum GameControl : ushort - { - Null = 0x00, - GameController3D = 0x01, - PinballDevice = 0x02, - GunDevice = 0x03, - PointOfView = 0x20, - TurnRightLeft = 0x21, - PitchForwardBackward = 0x22, - RollRightLeft = 0x23, - MoveRightLeft = 0x24, - MoveForwardBackward = 0x25, - MoveUpDown = 0x26, - LeanRightLeft = 0x27, - LeanForwardBackward = 0x28, - HeightOfPov = 0x29, - Flipper = 0x2A, - SecondaryFlipper = 0x2B, - Bump = 0x2C, - NewGame = 0x2D, - ShootBall = 0x2E, - Player = 0x2F, - GunBolt = 0x30, - GunClip = 0x31, - GunSelector = 0x32, - GunSingleShot = 0x33, - GunBurst = 0x34, - GunAutomatic = 0x35, - GunSafety = 0x36, - GamepadFireJump = 0x37, - GamepadTrigger = 0x39 - } - - /// - /// - /// - enum TelephonyDevice : ushort - { - Null = 0x00, - Phone = 0x01, - AnsweringMachine = 0x02, - MessageControls = 0x03, - Handset = 0x04, - Headset = 0x05, - TelephonyKeyPad = 0x06, - ProgrammableButton = 0x07, - HookSwitch = 0x20, - Flash = 0x21, - Feature = 0x22, - Hold = 0x23, - Redial = 0x24, - Transfer = 0x25, - Drop = 0x26, - Park = 0x27, - ForwardCalls = 0x28, - AlternateFunction = 0x29, - Line = 0x2A, - SpeakerPhone = 0x2B, - Conference = 0x2C, - RingEnable = 0x2D, - RingSelect = 0x2E, - PhoneMute = 0x2F, - CallerId = 0x30, - Send = 0x31, - SpeedDial = 0x50, - StoreNumber = 0x51, - RecallNumber = 0x52, - PhoneDirectory = 0x53, - VoiceMail = 0x70, - ScreenCalls = 0x71, - DoNotDisturb = 0x72, - Message = 0x73, - AnswerOnOff = 0x74, - InsideDialTone = 0x90, - OutsideDialTone = 0x91, - InsideRingTone = 0x92, - OutsideRingTone = 0x93, - PriorityRingTone = 0x94, - InsideRingback = 0x95, - PriorityRingback = 0x96, - LineBusyTone = 0x97, - ReorderTone = 0x98, - CallWaitingTone = 0x99, - ConfirmationTone1 = 0x9A, - ConfirmationTone2 = 0x9B, - TonesOff = 0x9C, - OutsideRingback = 0x9D, - Ringer = 0x9E, - PhoneKey0 = 0xB0, - PhoneKey1 = 0xB1, - PhoneKey2 = 0xB2, - PhoneKey3 = 0xB3, - PhoneKey4 = 0xB4, - PhoneKey5 = 0xB5, - PhoneKey6 = 0xB6, - PhoneKey7 = 0xB7, - PhoneKey8 = 0xB8, - PhoneKey9 = 0xB9, - PhoneKeyStar = 0xBA, - PhoneKeyPound = 0xBB, - PhoneKeyA = 0xBC, - PhoneKeyB = 0xBD, - PhoneKeyC = 0xBE, - PhoneKeyD = 0xBF - } - } -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e HidUtils.cs --- a/HidUtils.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -// -// 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.Collections.Generic; -using System.Text; - -namespace SharpLib.Hid -{ - static class Utils - { - /// - /// Provide the type for the usage collection corresponding to the given usage page. - /// - /// - /// - public static Type UsageCollectionType(UsagePage aUsagePage) - { - switch (aUsagePage) - { - case UsagePage.GenericDesktopControls: - return typeof(UsageCollection.GenericDesktop); - - case UsagePage.Consumer: - return typeof(UsageCollection.Consumer); - - case UsagePage.WindowsMediaCenterRemoteControl: - return typeof(UsageCollection.WindowsMediaCenter); - - default: - return null; - } - } - - /// - /// Provide the type for the usage corresponding to the given usage page. - /// - /// - /// - public static Type UsageType(UsagePage aUsagePage) - { - switch (aUsagePage) - { - case UsagePage.GenericDesktopControls: - return typeof(Usage.GenericDesktop); - - case UsagePage.Consumer: - return typeof(Usage.ConsumerControl); - - case UsagePage.WindowsMediaCenterRemoteControl: - return typeof(Usage.WindowsMediaCenterRemoteControl); - - case UsagePage.Telephony: - return typeof(Usage.TelephonyDevice); - - case UsagePage.SimulationControls: - return typeof(Usage.SimulationControl); - - case UsagePage.GameControls: - return typeof(Usage.GameControl); - - default: - return null; - } - } - - } -} diff -r 72885c950813 -r cdc5f8f1b79e RawInput.cs --- a/RawInput.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -// -// 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 diff -r 72885c950813 -r cdc5f8f1b79e SharpLibHid.csproj --- a/SharpLibHid.csproj Sun Mar 15 16:56:31 2015 +0100 +++ b/SharpLibHid.csproj Sun Mar 15 20:25:58 2015 +0100 @@ -42,17 +42,27 @@ - - - - - + + Code + + + Code + + + Code + + + Code + + + Code + - - - - - + + + + + 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 diff -r 72885c950813 -r cdc5f8f1b79e Win32/Win32AppCommand.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Win32/Win32AppCommand.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,37 @@ +// +// 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; + +namespace SharpLib.Win32 +{ + static public partial class Const + { + public const int WM_APPCOMMAND = 0x0319; + } + + static public partial class Macro + { + public static int GET_APPCOMMAND_LPARAM(IntPtr lParam) + { + return ((short)HIWORD(lParam.ToInt32()) & ~Const.FAPPCOMMAND_MASK); + } + } +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Win32/Win32CreateFile.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Win32/Win32CreateFile.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,228 @@ +// +// 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 Microsoft.Win32.SafeHandles; + +namespace SharpLib.Win32 +{ + + static partial class Function + { + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern SafeFileHandle CreateFile( + [MarshalAs(UnmanagedType.LPTStr)] string lpFileName, + [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, + [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, + IntPtr lpSecurityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero + [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, + [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, + IntPtr hTemplateFile); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SafeFileHandle CreateFileA( + [MarshalAs(UnmanagedType.LPStr)] string lpFileName, + [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, + [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, + IntPtr lpSecurityAttributes, + [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, + [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, + IntPtr hTemplateFile); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern SafeFileHandle CreateFileW( + [MarshalAs(UnmanagedType.LPWStr)] string lpFileName, + [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, + [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, + IntPtr lpSecurityAttributes, + [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, + [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, + IntPtr hTemplateFile); + } + + + static partial class Macro + { + + } + + + + static partial class Const + { + + } + + [Flags] + enum FileAccess : uint + { + NONE = 0, + + GENERIC_ALL = 0x10000000, + GENERIC_EXECUTE = 0x20000000, + GENERIC_READ = 0x80000000, + GENERIC_WRITE = 0x40000000, + + FILE_READ_DATA = (0x0001), // file & pipe + FILE_LIST_DIRECTORY = (0x0001), // directory + + FILE_WRITE_DATA = (0x0002), // file & pipe + FILE_ADD_FILE = (0x0002), // directory + + FILE_APPEND_DATA = (0x0004), // file + FILE_ADD_SUBDIRECTORY = (0x0004), // directory + FILE_CREATE_PIPE_INSTANCE = (0x0004), // named pipe + + FILE_READ_EA = (0x0008), // file & directory + + FILE_WRITE_EA = (0x0010), // file & directory + + FILE_EXECUTE = (0x0020), // file + FILE_TRAVERSE = (0x0020), // directory + + FILE_DELETE_CHILD = (0x0040), // directory + + FILE_READ_ATTRIBUTES = (0x0080), // all + + FILE_WRITE_ATTRIBUTES = (0x0100), // all + + FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF), + + FILE_GENERIC_READ = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE), + FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE), + FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE), + + DELETE = (0x00010000), + READ_CONTROL = (0x00020000), + WRITE_DAC = (0x00040000), + WRITE_OWNER = (0x00080000), + SYNCHRONIZE = (0x00100000), + + STANDARD_RIGHTS_REQUIRED = (0x000F0000), + + STANDARD_RIGHTS_READ = (READ_CONTROL), + STANDARD_RIGHTS_WRITE = (READ_CONTROL), + STANDARD_RIGHTS_EXECUTE = (READ_CONTROL), + + STANDARD_RIGHTS_ALL = (0x001F0000), + + SPECIFIC_RIGHTS_ALL = (0x0000FFFF), + + ACCESS_SYSTEM_SECURITY = (0x01000000), + + MAXIMUM_ALLOWED = (0x02000000) + } + + + + [Flags] + public enum FileShare : uint + { + /// + /// Prevents other processes from opening a file or device if they request delete, read, or write access. + /// + FILE_SHARE_NONE = 0x00000000, + /// + /// Enables subsequent open operations on an object to request read access. + /// Otherwise, other processes cannot open the object if they request read access. + /// If this flag is not specified, but the object has been opened for read access, the function fails. + /// + FILE_SHARE_READ = 0x00000001, + /// + /// Enables subsequent open operations on an object to request write access. + /// Otherwise, other processes cannot open the object if they request write access. + /// If this flag is not specified, but the object has been opened for write access, the function fails. + /// + FILE_SHARE_WRITE = 0x00000002, + /// + /// Enables subsequent open operations on an object to request delete access. + /// Otherwise, other processes cannot open the object if they request delete access. + /// If this flag is not specified, but the object has been opened for delete access, the function fails. + /// + FILE_SHARE_DELETE = 0x00000004 + } + + public enum CreationDisposition : uint + { + /// + /// Creates a new file. The function fails if a specified file exists. + /// + CREATE_NEW = 1, + /// + /// Creates a new file, always. + /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, + /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies. + /// + CREATE_ALWAYS = 2, + /// + /// Opens a file. The function fails if the file does not exist. + /// + OPEN_EXISTING = 3, + /// + /// Opens a file, always. + /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW. + /// + OPEN_ALWAYS = 4, + /// + /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist. + /// The calling process must open the file with the GENERIC_WRITE access right. + /// + TRUNCATE_EXISTING = 5 + } + + [Flags] + public enum FileFlagsAttributes : uint + { + FILE_ATTRIBUTE_READONLY = 0x00000001, + FILE_ATTRIBUTE_HIDDEN = 0x00000002, + FILE_ATTRIBUTE_SYSTEM = 0x00000004, + FILE_ATTRIBUTE_DIRECTORY = 0x00000010, + FILE_ATTRIBUTE_ARCHIVE = 0x00000020, + FILE_ATTRIBUTE_DEVICE = 0x00000040, + FILE_ATTRIBUTE_NORMAL = 0x00000080, + FILE_ATTRIBUTE_TEMPORARY = 0x00000100, + FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200, + FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400, + FILE_ATTRIBUTE_COMPRESSED = 0x00000800, + FILE_ATTRIBUTE_OFFLINE = 0x00001000, + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000, + FILE_ATTRIBUTE_ENCRYPTED = 0x00004000, + FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000, + FILE_ATTRIBUTE_VIRTUAL = 0x00010000, + FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000, + // These are flags supported through CreateFile (W7) and CreateFile2 (W8 and beyond) + FILE_FLAG_WRITE_THROUGH = 0x80000000, + FILE_FLAG_OVERLAPPED = 0x40000000, + FILE_FLAG_NO_BUFFERING = 0x20000000, + FILE_FLAG_RANDOM_ACCESS = 0x10000000, + FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000, + FILE_FLAG_DELETE_ON_CLOSE = 0x04000000, + FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, + FILE_FLAG_POSIX_SEMANTICS = 0x01000000, + FILE_FLAG_SESSION_AWARE = 0x00800000, + FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000, + FILE_FLAG_OPEN_NO_RECALL = 0x00100000, + FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000 + } + + + + +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Win32/Win32Hid.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Win32/Win32Hid.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,515 @@ +// +// 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 Microsoft.Win32.SafeHandles; +using System.Text; + +namespace SharpLib.Win32 +{ + + static partial class Function + { + [DllImport("hid.dll", CharSet = CharSet.Unicode)] + public static extern HidStatus HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, ushort LinkCollection, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] USAGE_AND_PAGE[] ButtonList, ref uint UsageLength, IntPtr PreparsedData, [MarshalAs(UnmanagedType.LPArray)] byte[] Report, uint ReportLength); + + [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern Boolean HidD_GetManufacturerString(SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength); + + [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern Boolean HidD_GetProductString(SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength); + + [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes); + + /// Return Type: NTSTATUS->LONG->int + ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* + ///Capabilities: PHIDP_CAPS->_HIDP_CAPS* + [DllImport("hid.dll", EntryPoint = "HidP_GetCaps", CallingConvention = CallingConvention.StdCall)] + public static extern HidStatus HidP_GetCaps(System.IntPtr PreparsedData, ref HIDP_CAPS Capabilities); + + /// Return Type: NTSTATUS->LONG->int + ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE + ///ButtonCaps: PHIDP_BUTTON_CAPS->_HIDP_BUTTON_CAPS* + ///ButtonCapsLength: PUSHORT->USHORT* + ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* + [DllImport("hid.dll", EntryPoint = "HidP_GetButtonCaps", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] + public static extern HidStatus HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] HIDP_BUTTON_CAPS[] ButtonCaps, ref ushort ButtonCapsLength, System.IntPtr PreparsedData); + + /// Return Type: NTSTATUS->LONG->int + ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE + ///ValueCaps: PHIDP_VALUE_CAPS->_HIDP_VALUE_CAPS* + ///ValueCapsLength: PUSHORT->USHORT* + ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* + [DllImport("hid.dll", EntryPoint = "HidP_GetValueCaps", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] + public static extern HidStatus HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] HIDP_VALUE_CAPS[] ValueCaps, ref ushort ValueCapsLength, System.IntPtr PreparsedData); + + /// Return Type: NTSTATUS->LONG->int + ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE + ///UsagePage: USAGE->USHORT->unsigned short + ///LinkCollection: USHORT->unsigned short + ///Usage: USAGE->USHORT->unsigned short + ///UsageValue: PULONG->ULONG* + ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* + ///Report: PCHAR->CHAR* + ///ReportLength: ULONG->unsigned int + [DllImport("hid.dll", EntryPoint = "HidP_GetUsageValue", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] + public static extern HidStatus HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, ushort UsagePage, ushort LinkCollection, ushort Usage, ref uint UsageValue, System.IntPtr PreparsedData, [MarshalAs(UnmanagedType.LPArray)] byte[] Report, uint ReportLength); + + + + } + + + static partial class Macro + { + + + } + + + static partial class Const + { + + + } + + + public enum HIDP_REPORT_TYPE : ushort + { + HidP_Input = 0, + HidP_Output, + HidP_Feature + } + + + public enum HidStatus : uint + { + HIDP_STATUS_SUCCESS = 0x110000, + HIDP_STATUS_NULL = 0x80110001, + HIDP_STATUS_INVALID_PREPARSED_DATA = 0xc0110001, + HIDP_STATUS_INVALID_REPORT_TYPE = 0xc0110002, + HIDP_STATUS_INVALID_REPORT_LENGTH = 0xc0110003, + HIDP_STATUS_USAGE_NOT_FOUND = 0xc0110004, + HIDP_STATUS_VALUE_OUT_OF_RANGE = 0xc0110005, + HIDP_STATUS_BAD_LOG_PHY_VALUES = 0xc0110006, + HIDP_STATUS_BUFFER_TOO_SMALL = 0xc0110007, + HIDP_STATUS_INTERNAL_ERROR = 0xc0110008, + HIDP_STATUS_I8042_TRANS_UNKNOWN = 0xc0110009, + HIDP_STATUS_INCOMPATIBLE_REPORT_ID = 0xc011000a, + HIDP_STATUS_NOT_VALUE_ARRAY = 0xc011000b, + HIDP_STATUS_IS_VALUE_ARRAY = 0xc011000c, + HIDP_STATUS_DATA_INDEX_NOT_FOUND = 0xc011000d, + HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE = 0xc011000e, + HIDP_STATUS_BUTTON_NOT_PRESSED = 0xc011000f, + HIDP_STATUS_REPORT_DOES_NOT_EXIST = 0xc0110010, + HIDP_STATUS_NOT_IMPLEMENTED = 0xc0110020, + HIDP_STATUS_I8242_TRANS_UNKNOWN = 0xc0110009 + } + + + [StructLayout(LayoutKind.Sequential)] + public struct USAGE_AND_PAGE + { + public ushort Usage; + public ushort UsagePage; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct HIDD_ATTRIBUTES + { + public uint Size; + public ushort VendorID; + public ushort ProductID; + public ushort VersionNumber; + } + + + [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + public struct HIDP_CAPS + { + /// USAGE->USHORT->unsigned short + public ushort Usage; + + /// USAGE->USHORT->unsigned short + public ushort UsagePage; + + /// USHORT->unsigned short + public ushort InputReportByteLength; + + /// USHORT->unsigned short + public ushort OutputReportByteLength; + + /// USHORT->unsigned short + public ushort FeatureReportByteLength; + + /// USHORT[17] + [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 17, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U2)] + public ushort[] Reserved; + + /// USHORT->unsigned short + public ushort NumberLinkCollectionNodes; + + /// USHORT->unsigned short + public ushort NumberInputButtonCaps; + + /// USHORT->unsigned short + public ushort NumberInputValueCaps; + + /// USHORT->unsigned short + public ushort NumberInputDataIndices; + + /// USHORT->unsigned short + public ushort NumberOutputButtonCaps; + + /// USHORT->unsigned short + public ushort NumberOutputValueCaps; + + /// USHORT->unsigned short + public ushort NumberOutputDataIndices; + + /// USHORT->unsigned short + public ushort NumberFeatureButtonCaps; + + /// USHORT->unsigned short + public ushort NumberFeatureValueCaps; + + /// USHORT->unsigned short + public ushort NumberFeatureDataIndices; + } + + /// + /// Type created in place of an anonymous struct + /// + [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + public struct HIDP_BUTTON_CAPS_RANGE + { + + /// USAGE->USHORT->unsigned short + public ushort UsageMin; + + /// USAGE->USHORT->unsigned short + public ushort UsageMax; + + /// USHORT->unsigned short + public ushort StringMin; + + /// USHORT->unsigned short + public ushort StringMax; + + /// USHORT->unsigned short + public ushort DesignatorMin; + + /// USHORT->unsigned short + public ushort DesignatorMax; + + /// USHORT->unsigned short + public ushort DataIndexMin; + + /// USHORT->unsigned short + public ushort DataIndexMax; + } + + /// + /// Type created in place of an anonymous struct + /// + [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + public struct HIDP_BUTTON_CAPS_NOT_RANGE + { + + /// USAGE->USHORT->unsigned short + public ushort Usage; + + /// USAGE->USHORT->unsigned short + public ushort Reserved1; + + /// USHORT->unsigned short + public ushort StringIndex; + + /// USHORT->unsigned short + public ushort Reserved2; + + /// USHORT->unsigned short + public ushort DesignatorIndex; + + /// USHORT->unsigned short + public ushort Reserved3; + + /// USHORT->unsigned short + public ushort DataIndex; + + /// USHORT->unsigned short + public ushort Reserved4; + } + + /// + /// + /// + [StructLayout(LayoutKind.Explicit, Pack = 1)] + public struct HIDP_BUTTON_CAPS + { + /// USAGE->USHORT->unsigned short + [FieldOffset(0)] + public ushort UsagePage; + + /// UCHAR->unsigned char + [FieldOffset(2)] + public byte ReportID; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(3)] + [MarshalAs(UnmanagedType.U1)] + public bool IsAlias; + + /// USHORT->unsigned short + [FieldOffset(4)] + public ushort BitField; + + /// USHORT->unsigned short + [FieldOffset(6)] + public ushort LinkCollection; + + /// USAGE->USHORT->unsigned short + [FieldOffset(8)] + public ushort LinkUsage; + + /// USAGE->USHORT->unsigned short + [FieldOffset(10)] + public ushort LinkUsagePage; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(12)] + [MarshalAs(UnmanagedType.U1)] + public bool IsRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(13)] + [MarshalAs(UnmanagedType.U1)] + public bool IsStringRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(14)] + [MarshalAs(UnmanagedType.U1)] + public bool IsDesignatorRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(15)] + [MarshalAs(UnmanagedType.U1)] + public bool IsAbsolute; + + /// ULONG[10] + [FieldOffset(16)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10, ArraySubType = UnmanagedType.U4)] + public uint[] Reserved; + + /// Union Range/NotRange + [FieldOffset(56)] + public HIDP_BUTTON_CAPS_RANGE Range; + + [FieldOffset(56)] + public HIDP_BUTTON_CAPS_NOT_RANGE NotRange; + } + + /// + /// Type created in place of an anonymous struct + /// + [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + public struct HIDP_VALUE_CAPS_RANGE + { + + /// USAGE->USHORT->unsigned short + public ushort UsageMin; + + /// USAGE->USHORT->unsigned short + public ushort UsageMax; + + /// USHORT->unsigned short + public ushort StringMin; + + /// USHORT->unsigned short + public ushort StringMax; + + /// USHORT->unsigned short + public ushort DesignatorMin; + + /// USHORT->unsigned short + public ushort DesignatorMax; + + /// USHORT->unsigned short + public ushort DataIndexMin; + + /// USHORT->unsigned short + public ushort DataIndexMax; + } + + /// + /// Type created in place of an anonymous struct + /// + [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] + public struct HIDP_VALUE_CAPS_NOT_RANGE + { + + /// USAGE->USHORT->unsigned short + public ushort Usage; + + /// USAGE->USHORT->unsigned short + public ushort Reserved1; + + /// USHORT->unsigned short + public ushort StringIndex; + + /// USHORT->unsigned short + public ushort Reserved2; + + /// USHORT->unsigned short + public ushort DesignatorIndex; + + /// USHORT->unsigned short + public ushort Reserved3; + + /// USHORT->unsigned short + public ushort DataIndex; + + /// USHORT->unsigned short + public ushort Reserved4; + } + + + /// + /// + /// + [StructLayout(LayoutKind.Explicit, Pack = 1)] + public struct HIDP_VALUE_CAPS + { + + /// USAGE->USHORT->unsigned short + [FieldOffset(0)] + public ushort UsagePage; + + /// UCHAR->unsigned char + [FieldOffset(2)] + public byte ReportID; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(3)] + [MarshalAs(UnmanagedType.U1)] + public bool IsAlias; + + /// USHORT->unsigned short + [FieldOffset(4)] + public ushort BitField; + + /// USHORT->unsigned short + [FieldOffset(6)] + public ushort LinkCollection; + + /// USAGE->USHORT->unsigned short + [FieldOffset(8)] + public ushort LinkUsage; + + /// USAGE->USHORT->unsigned short + [FieldOffset(10)] + public ushort LinkUsagePage; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(12)] + [MarshalAs(UnmanagedType.U1)] + public bool IsRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(13)] + [MarshalAs(UnmanagedType.U1)] + public bool IsStringRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(14)] + [MarshalAs(UnmanagedType.U1)] + public bool IsDesignatorRange; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(15)] + [MarshalAs(UnmanagedType.U1)] + public bool IsAbsolute; + + /// BOOLEAN->BYTE->unsigned char + [FieldOffset(16)] + [MarshalAs(UnmanagedType.U1)] + public bool HasNull; + + /// UCHAR->unsigned char + [FieldOffset(17)] + public byte Reserved; + + /// USHORT->unsigned short + [FieldOffset(18)] + public ushort BitSize; + + /// USHORT->unsigned short + [FieldOffset(20)] + public ushort ReportCount; + + /// USHORT[5] + /// We had to use 5 ushorts instead of an array to avoid alignment exception issues. + [FieldOffset(22)] + public ushort Reserved21; + [FieldOffset(24)] + public ushort Reserved22; + [FieldOffset(26)] + public ushort Reserved23; + [FieldOffset(28)] + public ushort Reserved24; + [FieldOffset(30)] + public ushort Reserved25; + + /// ULONG->unsigned int + [FieldOffset(32)] + public uint UnitsExp; + + /// ULONG->unsigned int + [FieldOffset(36)] + public uint Units; + + /// LONG->int + [FieldOffset(40)] + public int LogicalMin; + + /// LONG->int + [FieldOffset(44)] + public int LogicalMax; + + /// LONG->int + [FieldOffset(48)] + public int PhysicalMin; + + /// LONG->int + [FieldOffset(52)] + public int PhysicalMax; + + /// Union Range/NotRange + [FieldOffset(56)] + public HIDP_VALUE_CAPS_RANGE Range; + + [FieldOffset(56)] + public HIDP_VALUE_CAPS_NOT_RANGE NotRange; + } + +} + + diff -r 72885c950813 -r cdc5f8f1b79e Win32/Win32RawInput.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Win32/Win32RawInput.cs Sun Mar 15 20:25:58 2015 +0100 @@ -0,0 +1,386 @@ +// +// 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; + +namespace SharpLib.Win32 +{ + + static partial class Function + { + [DllImport("User32.dll", SetLastError = true)] + public extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize); + + [DllImport("User32.dll", SetLastError = true)] + public extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader); + + [DllImport("User32.dll", SetLastError=true)] + public extern static int GetRawInputDeviceInfo(IntPtr hDevice, RawInputDeviceInfoType uiCommand, IntPtr pData, ref uint pcbSize); + + [DllImport("user32.dll", SetLastError = true)] + public static extern int GetRawInputDeviceList( + [In, Out] RAWINPUTDEVICELIST[] InputdeviceList, + [In, Out] ref uint puiNumDevices, + [In] uint cbSize); + + } + + + static partial class Macro + { + /// + /// Retrieves the input code from wParam in WM_INPUT. + /// See RIM_INPUT and RIM_INPUTSINK. + /// + /// + /// + public static int GET_RAWINPUT_CODE_WPARAM(IntPtr wParam) + { + return (wParam.ToInt32() & 0xff); + } + + public static int GET_DEVICE_LPARAM(IntPtr lParam) + { + return ((ushort)(HIWORD(lParam.ToInt32()) & Const.FAPPCOMMAND_MASK)); + } + + public static int HIWORD(int val) + { + return ((val >> 16) & 0xffff); + } + + + //#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff)) + //#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) + //#define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff)) + //#define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff)) + + //#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK)) + //#define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK)) + //#define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM + //#define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam)) + //#define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam) + + } + + + + static partial class Const + { + /// + /// Windows Messages + /// + public const int WM_KEYDOWN = 0x0100; + public const int WM_INPUT = 0x00FF; + + + // + public const int RID_INPUT = 0x10000003; + public const int RID_HEADER = 0x10000005; + + /// + /// Possible value taken by wParam for WM_INPUT. + /// + /// Input occurred while the application was in the foreground. The application must call DefWindowProc so the system can perform cleanup. + /// + public const int RIM_INPUT = 0; + /// + /// Possible value taken by wParam for WM_INPUT. + /// + /// Input occurred while the application was not in the foreground. The application must call DefWindowProc so the system can perform the cleanup. + /// + public const int RIM_INPUTSINK = 1; + + /// + /// If set, the application command keys are handled. RIDEV_APPKEYS can be specified only if RIDEV_NOLEGACY is specified for a keyboard device. + /// + public const uint RIDEV_APPKEYS = 0x00000400; + + /// + /// If set, the mouse button click does not activate the other window. + /// + public const uint RIDEV_CAPTUREMOUSE = 0x00000200; + + /// + /// If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal. + /// Windows XP: This flag is not supported until Windows Vista + /// + public const uint RIDEV_DEVNOTIFY = 0x00002000; + + /// + /// If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with RIDEV_PAGEONLY. + /// + public const uint RIDEV_EXCLUDE = 0x00000010; + + /// + /// If set, this enables the caller to receive input in the background only if the foreground application does not process it. In other words, if the foreground application is not registered for raw input, then the background application that is registered will receive the input. + /// Windows XP: This flag is not supported until Windows Vista + /// + public const uint RIDEV_EXINPUTSINK = 0x00001000; + + /// + /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified. + /// + public const uint RIDEV_INPUTSINK = 0x00000100; + + /// + /// If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. RIDEV_NOHOTKEYS can be specified even if RIDEV_NOLEGACY is not specified and hwndTarget is NULL. + /// + public const uint RIDEV_NOHOTKEYS = 0x00000200; + + /// + /// If set, this prevents any devices specified by usUsagePage or usUsage from generating legacy messages. This is only for the mouse and keyboard. See Remarks. + /// + public const uint RIDEV_NOLEGACY = 0x00000030; + + /// + /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that usUsage must be zero. To exclude a particular top level collection, use RIDEV_EXCLUDE. + /// + public const uint RIDEV_PAGEONLY = 0x00000020; + + /// + /// If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection. + /// + public const uint RIDEV_REMOVE = 0x00000001; + + public const int APPCOMMAND_BROWSER_BACKWARD = 1; + public const int APPCOMMAND_VOLUME_MUTE = 8; + public const int APPCOMMAND_VOLUME_DOWN = 9; + public const int APPCOMMAND_VOLUME_UP = 10; + public const int APPCOMMAND_MEDIA_NEXTTRACK = 11; + public const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12; + public const int APPCOMMAND_MEDIA_STOP = 13; + public const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14; + public const int APPCOMMAND_MEDIA_PLAY = 46; + public const int APPCOMMAND_MEDIA_PAUSE = 47; + public const int APPCOMMAND_MEDIA_RECORD = 48; + public const int APPCOMMAND_MEDIA_FAST_FORWARD = 49; + public const int APPCOMMAND_MEDIA_REWIND = 50; + public const int APPCOMMAND_MEDIA_CHANNEL_UP = 51; + public const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52; + + public const int FAPPCOMMAND_MASK = 0xF000; + public const int FAPPCOMMAND_MOUSE = 0x8000; + public const int FAPPCOMMAND_KEY = 0; + public const int FAPPCOMMAND_OEM = 0x1000; + } + + /// + /// Introduced this enum for consistency and easy of use. + /// Naming of the Win32 constants were preserved. + /// + public enum RawInputDeviceType : uint + { + /// + /// Data comes from a mouse. + /// + RIM_TYPEMOUSE = 0, + /// + /// Data comes from a keyboard. + /// + RIM_TYPEKEYBOARD = 1, + /// + /// Data comes from an HID that is not a keyboard or a mouse. + /// + RIM_TYPEHID = 2 + } + + /// + /// Introduced this enum for consistency and easy of use. + /// Naming of the Win32 constants were preserved. + /// + public enum RawInputDeviceInfoType : uint + { + /// + /// GetRawInputDeviceInfo pData points to a string that contains the device name. + /// + RIDI_DEVICENAME = 0x20000007, + /// + /// GetRawInputDeviceInfo For this uiCommand only, the value in pcbSize is the character count (not the byte count). + /// + RIDI_DEVICEINFO = 0x2000000b, + /// + /// GetRawInputDeviceInfo pData points to an RID_DEVICE_INFO structure. + /// + RIDI_PREPARSEDDATA = 0x20000005 + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RAWINPUTDEVICELIST + { + public IntPtr hDevice; + public RawInputDeviceType dwType; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RAWINPUTDEVICE + { + [MarshalAs(UnmanagedType.U2)] + public ushort usUsagePage; + [MarshalAs(UnmanagedType.U2)] + public ushort usUsage; + [MarshalAs(UnmanagedType.U4)] + public uint dwFlags; + public IntPtr hwndTarget; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RAWINPUTHEADER + { + [MarshalAs(UnmanagedType.U4)] + public RawInputDeviceType dwType; + [MarshalAs(UnmanagedType.U4)] + public int dwSize; + public IntPtr hDevice; + [MarshalAs(UnmanagedType.U4)] + public int wParam; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RAWHID + { + [MarshalAs(UnmanagedType.U4)] + public uint dwSizeHid; + [MarshalAs(UnmanagedType.U4)] + public uint dwCount; + // + //BYTE bRawData[1]; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct BUTTONSSTR + { + [MarshalAs(UnmanagedType.U2)] + public ushort usButtonFlags; + [MarshalAs(UnmanagedType.U2)] + public ushort usButtonData; + } + + + [StructLayout(LayoutKind.Explicit, Pack = 1)] + public struct RAWMOUSE + { + [MarshalAs(UnmanagedType.U2)] + [FieldOffset(0)] + public ushort usFlags; + [MarshalAs(UnmanagedType.U4)] + [FieldOffset(4)] + public uint ulButtons; + [FieldOffset(4)] + public BUTTONSSTR buttonsStr; + [MarshalAs(UnmanagedType.U4)] + [FieldOffset(8)] + public uint ulRawButtons; + [MarshalAs(UnmanagedType.U4)] + [FieldOffset(12)] + public int lLastX; + [MarshalAs(UnmanagedType.U4)] + [FieldOffset(16)] + public int lLastY; + [MarshalAs(UnmanagedType.U4)] + [FieldOffset(20)] + public uint ulExtraInformation; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RAWKEYBOARD + { + [MarshalAs(UnmanagedType.U2)] + public ushort MakeCode; + [MarshalAs(UnmanagedType.U2)] + public ushort Flags; + [MarshalAs(UnmanagedType.U2)] + public ushort Reserved; + [MarshalAs(UnmanagedType.U2)] + public ushort VKey; + [MarshalAs(UnmanagedType.U4)] + public uint Message; + [MarshalAs(UnmanagedType.U4)] + public uint ExtraInformation; + } + + + [StructLayout(LayoutKind.Explicit, Pack = 1)] + public struct RAWINPUT + { + [FieldOffset(0)] + public RAWINPUTHEADER header; + [FieldOffset(16)] + public RAWMOUSE mouse; + [FieldOffset(16)] + public RAWKEYBOARD keyboard; + [FieldOffset(16)] + public RAWHID hid; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RID_DEVICE_INFO_MOUSE + { + public uint dwId; + public uint dwNumberOfButtons; + public uint dwSampleRate; + public bool fHasHorizontalWheel; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RID_DEVICE_INFO_KEYBOARD + { + public uint dwType; + public uint dwSubType; + public uint dwKeyboardMode; + public uint dwNumberOfFunctionKeys; + public uint dwNumberOfIndicators; + public uint dwNumberOfKeysTotal; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct RID_DEVICE_INFO_HID + { + public uint dwVendorId; + public uint dwProductId; + public uint dwVersionNumber; + public ushort usUsagePage; + public ushort usUsage; + } + + [StructLayout(LayoutKind.Explicit, Pack = 1)] + public struct RID_DEVICE_INFO + { + [FieldOffset(0)] + public uint cbSize; + [FieldOffset(4)] + [MarshalAs(UnmanagedType.U4)] + public RawInputDeviceType dwType; + [FieldOffset(8)] + public RID_DEVICE_INFO_MOUSE mouse; + [FieldOffset(8)] + public RID_DEVICE_INFO_KEYBOARD keyboard; + [FieldOffset(8)] + public RID_DEVICE_INFO_HID hid; + } + + +} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Win32AppCommand.cs --- a/Win32AppCommand.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -// -// 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; - -namespace SharpLib.Win32 -{ - static public partial class Const - { - public const int WM_APPCOMMAND = 0x0319; - } - - static public partial class Macro - { - public static int GET_APPCOMMAND_LPARAM(IntPtr lParam) - { - return ((short)HIWORD(lParam.ToInt32()) & ~Const.FAPPCOMMAND_MASK); - } - } -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Win32CreateFile.cs --- a/Win32CreateFile.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -// -// 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 Microsoft.Win32.SafeHandles; - -namespace SharpLib.Win32 -{ - - static partial class Function - { - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern SafeFileHandle CreateFile( - [MarshalAs(UnmanagedType.LPTStr)] string lpFileName, - [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, - [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, - IntPtr lpSecurityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero - [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, - [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, - IntPtr hTemplateFile); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)] - public static extern SafeFileHandle CreateFileA( - [MarshalAs(UnmanagedType.LPStr)] string lpFileName, - [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, - [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, - IntPtr lpSecurityAttributes, - [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, - [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, - IntPtr hTemplateFile); - - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern SafeFileHandle CreateFileW( - [MarshalAs(UnmanagedType.LPWStr)] string lpFileName, - [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, - [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, - IntPtr lpSecurityAttributes, - [MarshalAs(UnmanagedType.U4)] CreationDisposition dwCreationDisposition, - [MarshalAs(UnmanagedType.U4)] FileFlagsAttributes dwFlagsAndAttributes, - IntPtr hTemplateFile); - } - - - static partial class Macro - { - - } - - - - static partial class Const - { - - } - - [Flags] - enum FileAccess : uint - { - NONE = 0, - - GENERIC_ALL = 0x10000000, - GENERIC_EXECUTE = 0x20000000, - GENERIC_READ = 0x80000000, - GENERIC_WRITE = 0x40000000, - - FILE_READ_DATA = (0x0001), // file & pipe - FILE_LIST_DIRECTORY = (0x0001), // directory - - FILE_WRITE_DATA = (0x0002), // file & pipe - FILE_ADD_FILE = (0x0002), // directory - - FILE_APPEND_DATA = (0x0004), // file - FILE_ADD_SUBDIRECTORY = (0x0004), // directory - FILE_CREATE_PIPE_INSTANCE = (0x0004), // named pipe - - FILE_READ_EA = (0x0008), // file & directory - - FILE_WRITE_EA = (0x0010), // file & directory - - FILE_EXECUTE = (0x0020), // file - FILE_TRAVERSE = (0x0020), // directory - - FILE_DELETE_CHILD = (0x0040), // directory - - FILE_READ_ATTRIBUTES = (0x0080), // all - - FILE_WRITE_ATTRIBUTES = (0x0100), // all - - FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF), - - FILE_GENERIC_READ = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE), - FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE), - FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE), - - DELETE = (0x00010000), - READ_CONTROL = (0x00020000), - WRITE_DAC = (0x00040000), - WRITE_OWNER = (0x00080000), - SYNCHRONIZE = (0x00100000), - - STANDARD_RIGHTS_REQUIRED = (0x000F0000), - - STANDARD_RIGHTS_READ = (READ_CONTROL), - STANDARD_RIGHTS_WRITE = (READ_CONTROL), - STANDARD_RIGHTS_EXECUTE = (READ_CONTROL), - - STANDARD_RIGHTS_ALL = (0x001F0000), - - SPECIFIC_RIGHTS_ALL = (0x0000FFFF), - - ACCESS_SYSTEM_SECURITY = (0x01000000), - - MAXIMUM_ALLOWED = (0x02000000) - } - - - - [Flags] - public enum FileShare : uint - { - /// - /// Prevents other processes from opening a file or device if they request delete, read, or write access. - /// - FILE_SHARE_NONE = 0x00000000, - /// - /// Enables subsequent open operations on an object to request read access. - /// Otherwise, other processes cannot open the object if they request read access. - /// If this flag is not specified, but the object has been opened for read access, the function fails. - /// - FILE_SHARE_READ = 0x00000001, - /// - /// Enables subsequent open operations on an object to request write access. - /// Otherwise, other processes cannot open the object if they request write access. - /// If this flag is not specified, but the object has been opened for write access, the function fails. - /// - FILE_SHARE_WRITE = 0x00000002, - /// - /// Enables subsequent open operations on an object to request delete access. - /// Otherwise, other processes cannot open the object if they request delete access. - /// If this flag is not specified, but the object has been opened for delete access, the function fails. - /// - FILE_SHARE_DELETE = 0x00000004 - } - - public enum CreationDisposition : uint - { - /// - /// Creates a new file. The function fails if a specified file exists. - /// - CREATE_NEW = 1, - /// - /// Creates a new file, always. - /// If a file exists, the function overwrites the file, clears the existing attributes, combines the specified file attributes, - /// and flags with FILE_ATTRIBUTE_ARCHIVE, but does not set the security descriptor that the SECURITY_ATTRIBUTES structure specifies. - /// - CREATE_ALWAYS = 2, - /// - /// Opens a file. The function fails if the file does not exist. - /// - OPEN_EXISTING = 3, - /// - /// Opens a file, always. - /// If a file does not exist, the function creates a file as if dwCreationDisposition is CREATE_NEW. - /// - OPEN_ALWAYS = 4, - /// - /// Opens a file and truncates it so that its size is 0 (zero) bytes. The function fails if the file does not exist. - /// The calling process must open the file with the GENERIC_WRITE access right. - /// - TRUNCATE_EXISTING = 5 - } - - [Flags] - public enum FileFlagsAttributes : uint - { - FILE_ATTRIBUTE_READONLY = 0x00000001, - FILE_ATTRIBUTE_HIDDEN = 0x00000002, - FILE_ATTRIBUTE_SYSTEM = 0x00000004, - FILE_ATTRIBUTE_DIRECTORY = 0x00000010, - FILE_ATTRIBUTE_ARCHIVE = 0x00000020, - FILE_ATTRIBUTE_DEVICE = 0x00000040, - FILE_ATTRIBUTE_NORMAL = 0x00000080, - FILE_ATTRIBUTE_TEMPORARY = 0x00000100, - FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200, - FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400, - FILE_ATTRIBUTE_COMPRESSED = 0x00000800, - FILE_ATTRIBUTE_OFFLINE = 0x00001000, - FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000, - FILE_ATTRIBUTE_ENCRYPTED = 0x00004000, - FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x00008000, - FILE_ATTRIBUTE_VIRTUAL = 0x00010000, - FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x00020000, - // These are flags supported through CreateFile (W7) and CreateFile2 (W8 and beyond) - FILE_FLAG_WRITE_THROUGH = 0x80000000, - FILE_FLAG_OVERLAPPED = 0x40000000, - FILE_FLAG_NO_BUFFERING = 0x20000000, - FILE_FLAG_RANDOM_ACCESS = 0x10000000, - FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000, - FILE_FLAG_DELETE_ON_CLOSE = 0x04000000, - FILE_FLAG_BACKUP_SEMANTICS = 0x02000000, - FILE_FLAG_POSIX_SEMANTICS = 0x01000000, - FILE_FLAG_SESSION_AWARE = 0x00800000, - FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000, - FILE_FLAG_OPEN_NO_RECALL = 0x00100000, - FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000 - } - - - - -} \ No newline at end of file diff -r 72885c950813 -r cdc5f8f1b79e Win32Hid.cs --- a/Win32Hid.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,515 +0,0 @@ -// -// 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 Microsoft.Win32.SafeHandles; -using System.Text; - -namespace SharpLib.Win32 -{ - - static partial class Function - { - [DllImport("hid.dll", CharSet = CharSet.Unicode)] - public static extern HidStatus HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, ushort LinkCollection, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] USAGE_AND_PAGE[] ButtonList, ref uint UsageLength, IntPtr PreparsedData, [MarshalAs(UnmanagedType.LPArray)] byte[] Report, uint ReportLength); - - [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern Boolean HidD_GetManufacturerString(SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength); - - [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern Boolean HidD_GetProductString(SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength); - - [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes); - - /// Return Type: NTSTATUS->LONG->int - ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* - ///Capabilities: PHIDP_CAPS->_HIDP_CAPS* - [DllImport("hid.dll", EntryPoint = "HidP_GetCaps", CallingConvention = CallingConvention.StdCall)] - public static extern HidStatus HidP_GetCaps(System.IntPtr PreparsedData, ref HIDP_CAPS Capabilities); - - /// Return Type: NTSTATUS->LONG->int - ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE - ///ButtonCaps: PHIDP_BUTTON_CAPS->_HIDP_BUTTON_CAPS* - ///ButtonCapsLength: PUSHORT->USHORT* - ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* - [DllImport("hid.dll", EntryPoint = "HidP_GetButtonCaps", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] - public static extern HidStatus HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] HIDP_BUTTON_CAPS[] ButtonCaps, ref ushort ButtonCapsLength, System.IntPtr PreparsedData); - - /// Return Type: NTSTATUS->LONG->int - ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE - ///ValueCaps: PHIDP_VALUE_CAPS->_HIDP_VALUE_CAPS* - ///ValueCapsLength: PUSHORT->USHORT* - ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* - [DllImport("hid.dll", EntryPoint = "HidP_GetValueCaps", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] - public static extern HidStatus HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] HIDP_VALUE_CAPS[] ValueCaps, ref ushort ValueCapsLength, System.IntPtr PreparsedData); - - /// Return Type: NTSTATUS->LONG->int - ///ReportType: HIDP_REPORT_TYPE->_HIDP_REPORT_TYPE - ///UsagePage: USAGE->USHORT->unsigned short - ///LinkCollection: USHORT->unsigned short - ///Usage: USAGE->USHORT->unsigned short - ///UsageValue: PULONG->ULONG* - ///PreparsedData: PHIDP_PREPARSED_DATA->_HIDP_PREPARSED_DATA* - ///Report: PCHAR->CHAR* - ///ReportLength: ULONG->unsigned int - [DllImport("hid.dll", EntryPoint = "HidP_GetUsageValue", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] - public static extern HidStatus HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, ushort UsagePage, ushort LinkCollection, ushort Usage, ref uint UsageValue, System.IntPtr PreparsedData, [MarshalAs(UnmanagedType.LPArray)] byte[] Report, uint ReportLength); - - - - } - - - static partial class Macro - { - - - } - - - static partial class Const - { - - - } - - - public enum HIDP_REPORT_TYPE : ushort - { - HidP_Input = 0, - HidP_Output, - HidP_Feature - } - - - public enum HidStatus : uint - { - HIDP_STATUS_SUCCESS = 0x110000, - HIDP_STATUS_NULL = 0x80110001, - HIDP_STATUS_INVALID_PREPARSED_DATA = 0xc0110001, - HIDP_STATUS_INVALID_REPORT_TYPE = 0xc0110002, - HIDP_STATUS_INVALID_REPORT_LENGTH = 0xc0110003, - HIDP_STATUS_USAGE_NOT_FOUND = 0xc0110004, - HIDP_STATUS_VALUE_OUT_OF_RANGE = 0xc0110005, - HIDP_STATUS_BAD_LOG_PHY_VALUES = 0xc0110006, - HIDP_STATUS_BUFFER_TOO_SMALL = 0xc0110007, - HIDP_STATUS_INTERNAL_ERROR = 0xc0110008, - HIDP_STATUS_I8042_TRANS_UNKNOWN = 0xc0110009, - HIDP_STATUS_INCOMPATIBLE_REPORT_ID = 0xc011000a, - HIDP_STATUS_NOT_VALUE_ARRAY = 0xc011000b, - HIDP_STATUS_IS_VALUE_ARRAY = 0xc011000c, - HIDP_STATUS_DATA_INDEX_NOT_FOUND = 0xc011000d, - HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE = 0xc011000e, - HIDP_STATUS_BUTTON_NOT_PRESSED = 0xc011000f, - HIDP_STATUS_REPORT_DOES_NOT_EXIST = 0xc0110010, - HIDP_STATUS_NOT_IMPLEMENTED = 0xc0110020, - HIDP_STATUS_I8242_TRANS_UNKNOWN = 0xc0110009 - } - - - [StructLayout(LayoutKind.Sequential)] - public struct USAGE_AND_PAGE - { - public ushort Usage; - public ushort UsagePage; - }; - - [StructLayout(LayoutKind.Sequential)] - public struct HIDD_ATTRIBUTES - { - public uint Size; - public ushort VendorID; - public ushort ProductID; - public ushort VersionNumber; - } - - - [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - public struct HIDP_CAPS - { - /// USAGE->USHORT->unsigned short - public ushort Usage; - - /// USAGE->USHORT->unsigned short - public ushort UsagePage; - - /// USHORT->unsigned short - public ushort InputReportByteLength; - - /// USHORT->unsigned short - public ushort OutputReportByteLength; - - /// USHORT->unsigned short - public ushort FeatureReportByteLength; - - /// USHORT[17] - [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 17, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U2)] - public ushort[] Reserved; - - /// USHORT->unsigned short - public ushort NumberLinkCollectionNodes; - - /// USHORT->unsigned short - public ushort NumberInputButtonCaps; - - /// USHORT->unsigned short - public ushort NumberInputValueCaps; - - /// USHORT->unsigned short - public ushort NumberInputDataIndices; - - /// USHORT->unsigned short - public ushort NumberOutputButtonCaps; - - /// USHORT->unsigned short - public ushort NumberOutputValueCaps; - - /// USHORT->unsigned short - public ushort NumberOutputDataIndices; - - /// USHORT->unsigned short - public ushort NumberFeatureButtonCaps; - - /// USHORT->unsigned short - public ushort NumberFeatureValueCaps; - - /// USHORT->unsigned short - public ushort NumberFeatureDataIndices; - } - - /// - /// Type created in place of an anonymous struct - /// - [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - public struct HIDP_BUTTON_CAPS_RANGE - { - - /// USAGE->USHORT->unsigned short - public ushort UsageMin; - - /// USAGE->USHORT->unsigned short - public ushort UsageMax; - - /// USHORT->unsigned short - public ushort StringMin; - - /// USHORT->unsigned short - public ushort StringMax; - - /// USHORT->unsigned short - public ushort DesignatorMin; - - /// USHORT->unsigned short - public ushort DesignatorMax; - - /// USHORT->unsigned short - public ushort DataIndexMin; - - /// USHORT->unsigned short - public ushort DataIndexMax; - } - - /// - /// Type created in place of an anonymous struct - /// - [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - public struct HIDP_BUTTON_CAPS_NOT_RANGE - { - - /// USAGE->USHORT->unsigned short - public ushort Usage; - - /// USAGE->USHORT->unsigned short - public ushort Reserved1; - - /// USHORT->unsigned short - public ushort StringIndex; - - /// USHORT->unsigned short - public ushort Reserved2; - - /// USHORT->unsigned short - public ushort DesignatorIndex; - - /// USHORT->unsigned short - public ushort Reserved3; - - /// USHORT->unsigned short - public ushort DataIndex; - - /// USHORT->unsigned short - public ushort Reserved4; - } - - /// - /// - /// - [StructLayout(LayoutKind.Explicit, Pack = 1)] - public struct HIDP_BUTTON_CAPS - { - /// USAGE->USHORT->unsigned short - [FieldOffset(0)] - public ushort UsagePage; - - /// UCHAR->unsigned char - [FieldOffset(2)] - public byte ReportID; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(3)] - [MarshalAs(UnmanagedType.U1)] - public bool IsAlias; - - /// USHORT->unsigned short - [FieldOffset(4)] - public ushort BitField; - - /// USHORT->unsigned short - [FieldOffset(6)] - public ushort LinkCollection; - - /// USAGE->USHORT->unsigned short - [FieldOffset(8)] - public ushort LinkUsage; - - /// USAGE->USHORT->unsigned short - [FieldOffset(10)] - public ushort LinkUsagePage; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(12)] - [MarshalAs(UnmanagedType.U1)] - public bool IsRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(13)] - [MarshalAs(UnmanagedType.U1)] - public bool IsStringRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(14)] - [MarshalAs(UnmanagedType.U1)] - public bool IsDesignatorRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(15)] - [MarshalAs(UnmanagedType.U1)] - public bool IsAbsolute; - - /// ULONG[10] - [FieldOffset(16)] - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10, ArraySubType = UnmanagedType.U4)] - public uint[] Reserved; - - /// Union Range/NotRange - [FieldOffset(56)] - public HIDP_BUTTON_CAPS_RANGE Range; - - [FieldOffset(56)] - public HIDP_BUTTON_CAPS_NOT_RANGE NotRange; - } - - /// - /// Type created in place of an anonymous struct - /// - [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - public struct HIDP_VALUE_CAPS_RANGE - { - - /// USAGE->USHORT->unsigned short - public ushort UsageMin; - - /// USAGE->USHORT->unsigned short - public ushort UsageMax; - - /// USHORT->unsigned short - public ushort StringMin; - - /// USHORT->unsigned short - public ushort StringMax; - - /// USHORT->unsigned short - public ushort DesignatorMin; - - /// USHORT->unsigned short - public ushort DesignatorMax; - - /// USHORT->unsigned short - public ushort DataIndexMin; - - /// USHORT->unsigned short - public ushort DataIndexMax; - } - - /// - /// Type created in place of an anonymous struct - /// - [StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - public struct HIDP_VALUE_CAPS_NOT_RANGE - { - - /// USAGE->USHORT->unsigned short - public ushort Usage; - - /// USAGE->USHORT->unsigned short - public ushort Reserved1; - - /// USHORT->unsigned short - public ushort StringIndex; - - /// USHORT->unsigned short - public ushort Reserved2; - - /// USHORT->unsigned short - public ushort DesignatorIndex; - - /// USHORT->unsigned short - public ushort Reserved3; - - /// USHORT->unsigned short - public ushort DataIndex; - - /// USHORT->unsigned short - public ushort Reserved4; - } - - - /// - /// - /// - [StructLayout(LayoutKind.Explicit, Pack = 1)] - public struct HIDP_VALUE_CAPS - { - - /// USAGE->USHORT->unsigned short - [FieldOffset(0)] - public ushort UsagePage; - - /// UCHAR->unsigned char - [FieldOffset(2)] - public byte ReportID; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(3)] - [MarshalAs(UnmanagedType.U1)] - public bool IsAlias; - - /// USHORT->unsigned short - [FieldOffset(4)] - public ushort BitField; - - /// USHORT->unsigned short - [FieldOffset(6)] - public ushort LinkCollection; - - /// USAGE->USHORT->unsigned short - [FieldOffset(8)] - public ushort LinkUsage; - - /// USAGE->USHORT->unsigned short - [FieldOffset(10)] - public ushort LinkUsagePage; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(12)] - [MarshalAs(UnmanagedType.U1)] - public bool IsRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(13)] - [MarshalAs(UnmanagedType.U1)] - public bool IsStringRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(14)] - [MarshalAs(UnmanagedType.U1)] - public bool IsDesignatorRange; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(15)] - [MarshalAs(UnmanagedType.U1)] - public bool IsAbsolute; - - /// BOOLEAN->BYTE->unsigned char - [FieldOffset(16)] - [MarshalAs(UnmanagedType.U1)] - public bool HasNull; - - /// UCHAR->unsigned char - [FieldOffset(17)] - public byte Reserved; - - /// USHORT->unsigned short - [FieldOffset(18)] - public ushort BitSize; - - /// USHORT->unsigned short - [FieldOffset(20)] - public ushort ReportCount; - - /// USHORT[5] - /// We had to use 5 ushorts instead of an array to avoid alignment exception issues. - [FieldOffset(22)] - public ushort Reserved21; - [FieldOffset(24)] - public ushort Reserved22; - [FieldOffset(26)] - public ushort Reserved23; - [FieldOffset(28)] - public ushort Reserved24; - [FieldOffset(30)] - public ushort Reserved25; - - /// ULONG->unsigned int - [FieldOffset(32)] - public uint UnitsExp; - - /// ULONG->unsigned int - [FieldOffset(36)] - public uint Units; - - /// LONG->int - [FieldOffset(40)] - public int LogicalMin; - - /// LONG->int - [FieldOffset(44)] - public int LogicalMax; - - /// LONG->int - [FieldOffset(48)] - public int PhysicalMin; - - /// LONG->int - [FieldOffset(52)] - public int PhysicalMax; - - /// Union Range/NotRange - [FieldOffset(56)] - public HIDP_VALUE_CAPS_RANGE Range; - - [FieldOffset(56)] - public HIDP_VALUE_CAPS_NOT_RANGE NotRange; - } - -} - - diff -r 72885c950813 -r cdc5f8f1b79e Win32RawInput.cs --- a/Win32RawInput.cs Sun Mar 15 16:56:31 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,386 +0,0 @@ -// -// 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; - -namespace SharpLib.Win32 -{ - - static partial class Function - { - [DllImport("User32.dll", SetLastError = true)] - public extern static bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, uint uiNumDevices, uint cbSize); - - [DllImport("User32.dll", SetLastError = true)] - public extern static uint GetRawInputData(IntPtr hRawInput, uint uiCommand, IntPtr pData, ref uint pcbSize, uint cbSizeHeader); - - [DllImport("User32.dll", SetLastError=true)] - public extern static int GetRawInputDeviceInfo(IntPtr hDevice, RawInputDeviceInfoType uiCommand, IntPtr pData, ref uint pcbSize); - - [DllImport("user32.dll", SetLastError = true)] - public static extern int GetRawInputDeviceList( - [In, Out] RAWINPUTDEVICELIST[] InputdeviceList, - [In, Out] ref uint puiNumDevices, - [In] uint cbSize); - - } - - - static partial class Macro - { - /// - /// Retrieves the input code from wParam in WM_INPUT. - /// See RIM_INPUT and RIM_INPUTSINK. - /// - /// - /// - public static int GET_RAWINPUT_CODE_WPARAM(IntPtr wParam) - { - return (wParam.ToInt32() & 0xff); - } - - public static int GET_DEVICE_LPARAM(IntPtr lParam) - { - return ((ushort)(HIWORD(lParam.ToInt32()) & Const.FAPPCOMMAND_MASK)); - } - - public static int HIWORD(int val) - { - return ((val >> 16) & 0xffff); - } - - - //#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff)) - //#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) - //#define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff)) - //#define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff)) - - //#define GET_APPCOMMAND_LPARAM(lParam) ((short)(HIWORD(lParam) & ~FAPPCOMMAND_MASK)) - //#define GET_DEVICE_LPARAM(lParam) ((WORD)(HIWORD(lParam) & FAPPCOMMAND_MASK)) - //#define GET_MOUSEORKEY_LPARAM GET_DEVICE_LPARAM - //#define GET_FLAGS_LPARAM(lParam) (LOWORD(lParam)) - //#define GET_KEYSTATE_LPARAM(lParam) GET_FLAGS_LPARAM(lParam) - - } - - - - static partial class Const - { - /// - /// Windows Messages - /// - public const int WM_KEYDOWN = 0x0100; - public const int WM_INPUT = 0x00FF; - - - // - public const int RID_INPUT = 0x10000003; - public const int RID_HEADER = 0x10000005; - - /// - /// Possible value taken by wParam for WM_INPUT. - /// - /// Input occurred while the application was in the foreground. The application must call DefWindowProc so the system can perform cleanup. - /// - public const int RIM_INPUT = 0; - /// - /// Possible value taken by wParam for WM_INPUT. - /// - /// Input occurred while the application was not in the foreground. The application must call DefWindowProc so the system can perform the cleanup. - /// - public const int RIM_INPUTSINK = 1; - - /// - /// If set, the application command keys are handled. RIDEV_APPKEYS can be specified only if RIDEV_NOLEGACY is specified for a keyboard device. - /// - public const uint RIDEV_APPKEYS = 0x00000400; - - /// - /// If set, the mouse button click does not activate the other window. - /// - public const uint RIDEV_CAPTUREMOUSE = 0x00000200; - - /// - /// If set, this enables the caller to receive WM_INPUT_DEVICE_CHANGE notifications for device arrival and device removal. - /// Windows XP: This flag is not supported until Windows Vista - /// - public const uint RIDEV_DEVNOTIFY = 0x00002000; - - /// - /// If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with RIDEV_PAGEONLY. - /// - public const uint RIDEV_EXCLUDE = 0x00000010; - - /// - /// If set, this enables the caller to receive input in the background only if the foreground application does not process it. In other words, if the foreground application is not registered for raw input, then the background application that is registered will receive the input. - /// Windows XP: This flag is not supported until Windows Vista - /// - public const uint RIDEV_EXINPUTSINK = 0x00001000; - - /// - /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified. - /// - public const uint RIDEV_INPUTSINK = 0x00000100; - - /// - /// If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. RIDEV_NOHOTKEYS can be specified even if RIDEV_NOLEGACY is not specified and hwndTarget is NULL. - /// - public const uint RIDEV_NOHOTKEYS = 0x00000200; - - /// - /// If set, this prevents any devices specified by usUsagePage or usUsage from generating legacy messages. This is only for the mouse and keyboard. See Remarks. - /// - public const uint RIDEV_NOLEGACY = 0x00000030; - - /// - /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that usUsage must be zero. To exclude a particular top level collection, use RIDEV_EXCLUDE. - /// - public const uint RIDEV_PAGEONLY = 0x00000020; - - /// - /// If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection. - /// - public const uint RIDEV_REMOVE = 0x00000001; - - public const int APPCOMMAND_BROWSER_BACKWARD = 1; - public const int APPCOMMAND_VOLUME_MUTE = 8; - public const int APPCOMMAND_VOLUME_DOWN = 9; - public const int APPCOMMAND_VOLUME_UP = 10; - public const int APPCOMMAND_MEDIA_NEXTTRACK = 11; - public const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12; - public const int APPCOMMAND_MEDIA_STOP = 13; - public const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14; - public const int APPCOMMAND_MEDIA_PLAY = 46; - public const int APPCOMMAND_MEDIA_PAUSE = 47; - public const int APPCOMMAND_MEDIA_RECORD = 48; - public const int APPCOMMAND_MEDIA_FAST_FORWARD = 49; - public const int APPCOMMAND_MEDIA_REWIND = 50; - public const int APPCOMMAND_MEDIA_CHANNEL_UP = 51; - public const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52; - - public const int FAPPCOMMAND_MASK = 0xF000; - public const int FAPPCOMMAND_MOUSE = 0x8000; - public const int FAPPCOMMAND_KEY = 0; - public const int FAPPCOMMAND_OEM = 0x1000; - } - - /// - /// Introduced this enum for consistency and easy of use. - /// Naming of the Win32 constants were preserved. - /// - public enum RawInputDeviceType : uint - { - /// - /// Data comes from a mouse. - /// - RIM_TYPEMOUSE = 0, - /// - /// Data comes from a keyboard. - /// - RIM_TYPEKEYBOARD = 1, - /// - /// Data comes from an HID that is not a keyboard or a mouse. - /// - RIM_TYPEHID = 2 - } - - /// - /// Introduced this enum for consistency and easy of use. - /// Naming of the Win32 constants were preserved. - /// - public enum RawInputDeviceInfoType : uint - { - /// - /// GetRawInputDeviceInfo pData points to a string that contains the device name. - /// - RIDI_DEVICENAME = 0x20000007, - /// - /// GetRawInputDeviceInfo For this uiCommand only, the value in pcbSize is the character count (not the byte count). - /// - RIDI_DEVICEINFO = 0x2000000b, - /// - /// GetRawInputDeviceInfo pData points to an RID_DEVICE_INFO structure. - /// - RIDI_PREPARSEDDATA = 0x20000005 - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RAWINPUTDEVICELIST - { - public IntPtr hDevice; - public RawInputDeviceType dwType; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RAWINPUTDEVICE - { - [MarshalAs(UnmanagedType.U2)] - public ushort usUsagePage; - [MarshalAs(UnmanagedType.U2)] - public ushort usUsage; - [MarshalAs(UnmanagedType.U4)] - public uint dwFlags; - public IntPtr hwndTarget; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RAWINPUTHEADER - { - [MarshalAs(UnmanagedType.U4)] - public RawInputDeviceType dwType; - [MarshalAs(UnmanagedType.U4)] - public int dwSize; - public IntPtr hDevice; - [MarshalAs(UnmanagedType.U4)] - public int wParam; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RAWHID - { - [MarshalAs(UnmanagedType.U4)] - public uint dwSizeHid; - [MarshalAs(UnmanagedType.U4)] - public uint dwCount; - // - //BYTE bRawData[1]; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct BUTTONSSTR - { - [MarshalAs(UnmanagedType.U2)] - public ushort usButtonFlags; - [MarshalAs(UnmanagedType.U2)] - public ushort usButtonData; - } - - - [StructLayout(LayoutKind.Explicit, Pack = 1)] - public struct RAWMOUSE - { - [MarshalAs(UnmanagedType.U2)] - [FieldOffset(0)] - public ushort usFlags; - [MarshalAs(UnmanagedType.U4)] - [FieldOffset(4)] - public uint ulButtons; - [FieldOffset(4)] - public BUTTONSSTR buttonsStr; - [MarshalAs(UnmanagedType.U4)] - [FieldOffset(8)] - public uint ulRawButtons; - [MarshalAs(UnmanagedType.U4)] - [FieldOffset(12)] - public int lLastX; - [MarshalAs(UnmanagedType.U4)] - [FieldOffset(16)] - public int lLastY; - [MarshalAs(UnmanagedType.U4)] - [FieldOffset(20)] - public uint ulExtraInformation; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RAWKEYBOARD - { - [MarshalAs(UnmanagedType.U2)] - public ushort MakeCode; - [MarshalAs(UnmanagedType.U2)] - public ushort Flags; - [MarshalAs(UnmanagedType.U2)] - public ushort Reserved; - [MarshalAs(UnmanagedType.U2)] - public ushort VKey; - [MarshalAs(UnmanagedType.U4)] - public uint Message; - [MarshalAs(UnmanagedType.U4)] - public uint ExtraInformation; - } - - - [StructLayout(LayoutKind.Explicit, Pack = 1)] - public struct RAWINPUT - { - [FieldOffset(0)] - public RAWINPUTHEADER header; - [FieldOffset(16)] - public RAWMOUSE mouse; - [FieldOffset(16)] - public RAWKEYBOARD keyboard; - [FieldOffset(16)] - public RAWHID hid; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RID_DEVICE_INFO_MOUSE - { - public uint dwId; - public uint dwNumberOfButtons; - public uint dwSampleRate; - public bool fHasHorizontalWheel; - } - - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RID_DEVICE_INFO_KEYBOARD - { - public uint dwType; - public uint dwSubType; - public uint dwKeyboardMode; - public uint dwNumberOfFunctionKeys; - public uint dwNumberOfIndicators; - public uint dwNumberOfKeysTotal; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct RID_DEVICE_INFO_HID - { - public uint dwVendorId; - public uint dwProductId; - public uint dwVersionNumber; - public ushort usUsagePage; - public ushort usUsage; - } - - [StructLayout(LayoutKind.Explicit, Pack = 1)] - public struct RID_DEVICE_INFO - { - [FieldOffset(0)] - public uint cbSize; - [FieldOffset(4)] - [MarshalAs(UnmanagedType.U4)] - public RawInputDeviceType dwType; - [FieldOffset(8)] - public RID_DEVICE_INFO_MOUSE mouse; - [FieldOffset(8)] - public RID_DEVICE_INFO_KEYBOARD keyboard; - [FieldOffset(8)] - public RID_DEVICE_INFO_HID hid; - } - - -} \ No newline at end of file