HID Usage Tables fixes.
2 using System.Windows.Forms;
3 using System.Runtime.InteropServices;
4 using System.Diagnostics;
6 using Microsoft.Win32.SafeHandles;
8 using System.Collections.Generic;
14 /// Represent a HID event.
18 public bool IsValid { get; private set; }
19 public bool IsForeground { get; private set; }
20 public bool IsBackground { get{return !IsForeground;} }
21 public bool IsMouse { get; private set; }
22 public bool IsKeyboard { get; private set; }
23 public bool IsGeneric { get; private set; }
25 public HidDevice Device { get; private set; }
27 public ushort UsagePage { get; private set; }
28 public ushort UsageCollection { get; private set; }
29 public List<ushort> Usages { get; private set; }
33 /// Initialize an HidEvent from a WM_INPUT message
35 /// <param name="hRawInputDevice">Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice</param>
36 public HidEvent(Message aMessage)
42 Usages = new List<ushort>();
44 if (aMessage.Msg != Const.WM_INPUT)
46 //Has to be a WM_INPUT message
50 if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
54 else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
59 //Declare some pointers
60 IntPtr rawInputBuffer = IntPtr.Zero;
61 //My understanding is that this is basically our HID descriptor
62 IntPtr preParsedData = IntPtr.Zero;
67 RAWINPUT rawInput = new RAWINPUT();
68 if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
74 RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
75 if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
80 //Get various information about this HID device
81 Device = new Hid.HidDevice(rawInput.header.hDevice);
83 if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
87 Debug.WriteLine("WM_INPUT source device is HID.");
88 //Get Usage Page and Usage
89 //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
90 UsagePage = deviceInfo.hid.usUsagePage;
91 UsageCollection = deviceInfo.hid.usUsage;
93 preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
95 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
96 && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
101 //Allocate a buffer for one HID input
102 byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
104 Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
106 //For each HID input report in our raw input
107 for (int i = 0; i < rawInput.hid.dwCount; i++)
109 //Compute the address from which to copy our HID input
110 int hidInputOffset = 0;
113 byte* source = (byte*)rawInputBuffer;
114 source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
115 hidInputOffset = (int)source;
118 //Copy HID input into our buffer
119 Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
121 //Print HID input report in our debug output
122 string hidDump = "HID input report: ";
123 foreach (byte b in hidInputReport)
125 hidDump += b.ToString("X2");
127 Debug.WriteLine(hidDump);
130 uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
131 Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
132 Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
133 if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
135 Debug.WriteLine("Could not parse HID data!");
139 //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
140 //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
141 //Add this usage to our list
142 Usages.Add(usages[0].Usage);
147 else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
151 Debug.WriteLine("WM_INPUT source device is Mouse.");
152 // do mouse handling...
154 else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
158 Debug.WriteLine("WM_INPUT source device is Keyboard.");
159 // do keyboard handling...
160 Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
161 Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
162 Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
163 Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
164 Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
165 Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
170 //Always executed when leaving our try block
171 Marshal.FreeHGlobal(rawInputBuffer);
172 Marshal.FreeHGlobal(preParsedData);
179 /// Print information about this device to our debug output.
181 public void DebugWrite()
185 Debug.WriteLine("==== Invalid HidEvent");
189 if (IsGeneric) Debug.WriteLine("==== Generic");
190 if (IsKeyboard) Debug.WriteLine("==== Keyboard");
191 if (IsMouse) Debug.WriteLine("==== Mouse");
192 Debug.WriteLine("==== Foreground: " + IsForeground.ToString());
193 Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4"));
194 Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4"));
195 foreach (ushort usage in Usages)
197 Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4"));