Adding button count property to HID device.
Adding device list refresh button.
Better reporting of input value capabilities description.
1.1 --- a/HidDevice.cs Thu Mar 05 10:12:37 2015 +0100
1.2 +++ b/HidDevice.cs Sun Mar 15 09:53:37 2015 +0100
1.3 @@ -47,6 +47,9 @@
1.4 public HIDP_VALUE_CAPS[] InputValueCapabilities { get { return iInputValueCapabilities; } }
1.5 private HIDP_VALUE_CAPS[] iInputValueCapabilities;
1.6
1.7 + //
1.8 + public int ButtonCount { get; private set; }
1.9 +
1.10 /// <summary>
1.11 /// Class constructor will fetch this object properties from HID sub system.
1.12 /// </summary>
1.13 @@ -167,6 +170,8 @@
1.14 {
1.15 throw new Exception("HidDevice: HidP_GetButtonCaps failed: " + status.ToString());
1.16 }
1.17 +
1.18 + ComputeButtonCount();
1.19 }
1.20
1.21 //Get input value caps if needed
1.22 @@ -182,6 +187,23 @@
1.23 }
1.24 }
1.25
1.26 +
1.27 + /// <summary>
1.28 + /// Useful for gamepads.
1.29 + /// </summary>
1.30 + void ComputeButtonCount()
1.31 + {
1.32 + ButtonCount = 0;
1.33 + foreach (HIDP_BUTTON_CAPS bc in iInputButtonCapabilities)
1.34 + {
1.35 + if (bc.IsRange)
1.36 + {
1.37 + ButtonCount += (bc.Range.UsageMax - bc.Range.UsageMin + 1);
1.38 + }
1.39 + }
1.40 + }
1.41 +
1.42 +
1.43 /// <summary>
1.44 ///
1.45 /// </summary>
1.46 @@ -273,7 +295,8 @@
1.47 }
1.48
1.49 /// <summary>
1.50 - ///
1.51 + /// Provide a description for the given capabilities.
1.52 + /// Notably describes axis on a gamepad/joystick.
1.53 /// </summary>
1.54 /// <param name="aCaps"></param>
1.55 /// <returns></returns>
1.56 @@ -281,7 +304,20 @@
1.57 {
1.58 if (!aCaps.IsRange && Enum.IsDefined(typeof(UsagePage), Capabilities.UsagePage))
1.59 {
1.60 - return "Input Value: " + Enum.GetName(Utils.UsageType((UsagePage)Capabilities.UsagePage), aCaps.NotRange.Usage);
1.61 + Type usageType=Utils.UsageType((UsagePage)Capabilities.UsagePage);
1.62 + string name = Enum.GetName(usageType, aCaps.NotRange.Usage);
1.63 + if (name == null)
1.64 + {
1.65 + //Could not find that usage in our enum.
1.66 + //Provide a relevant warning instead.
1.67 + name = "Usage 0x" + aCaps.NotRange.Usage.ToString("X2") + " not defined in " + usageType.Name;
1.68 + }
1.69 + else
1.70 + {
1.71 + //Prepend our usage type name
1.72 + name = usageType.Name + "." + name;
1.73 + }
1.74 + return "Input Value: " + name;
1.75 }
1.76
1.77 return null;
2.1 --- a/HidEvent.cs Thu Mar 05 10:12:37 2015 +0100
2.2 +++ b/HidEvent.cs Sun Mar 15 09:53:37 2015 +0100
2.3 @@ -22,6 +22,9 @@
2.4 public bool IsBackground { get { return !IsForeground; } }
2.5 public bool IsMouse { get; private set; }
2.6 public bool IsKeyboard { get; private set; }
2.7 + /// <summary>
2.8 + /// If this not a mouse or keyboard event then it's a generic HID event.
2.9 + /// </summary>
2.10 public bool IsGeneric { get; private set; }
2.11 public bool IsButtonDown { get { return Usages.Count == 1 && Usages[0] != 0; } }
2.12 public bool IsButtonUp { get { return Usages.Count == 0; } }
2.13 @@ -29,6 +32,8 @@
2.14 public uint RepeatCount { get; private set; }
2.15
2.16 public HidDevice Device { get; private set; }
2.17 + public RAWINPUT RawInput { get {return iRawInput;} }
2.18 + private RAWINPUT iRawInput;
2.19
2.20 public ushort UsagePage { get; private set; }
2.21 public ushort UsageCollection { get; private set; }
2.22 @@ -76,7 +81,6 @@
2.23 IsKeyboard = false;
2.24 IsGeneric = false;
2.25
2.26 -
2.27 Time = DateTime.Now;
2.28 OriginalTime = DateTime.Now;
2.29 Timer = new System.Timers.Timer();
2.30 @@ -105,8 +109,8 @@
2.31 try
2.32 {
2.33 //Fetch raw input
2.34 - RAWINPUT rawInput = new RAWINPUT();
2.35 - if (!Win32.RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
2.36 + iRawInput = new RAWINPUT();
2.37 + if (!Win32.RawInput.GetRawInputData(aMessage.LParam, ref iRawInput, ref rawInputBuffer))
2.38 {
2.39 Debug.WriteLine("GetRawInputData failed!");
2.40 return;
2.41 @@ -114,13 +118,13 @@
2.42
2.43 //Our device can actually be null.
2.44 //This is notably happening for some keyboard events
2.45 - if (rawInput.header.hDevice != IntPtr.Zero)
2.46 + if (RawInput.header.hDevice != IntPtr.Zero)
2.47 {
2.48 //Get various information about this HID device
2.49 - Device = new Hid.HidDevice(rawInput.header.hDevice);
2.50 + Device = new Hid.HidDevice(RawInput.header.hDevice);
2.51 }
2.52
2.53 - if (rawInput.header.dwType == Win32.RawInputDeviceType.RIM_TYPEHID) //Check that our raw input is HID
2.54 + if (RawInput.header.dwType == Win32.RawInputDeviceType.RIM_TYPEHID) //Check that our raw input is HID
2.55 {
2.56 IsGeneric = true;
2.57
2.58 @@ -130,31 +134,31 @@
2.59 UsagePage = Device.Info.hid.usUsagePage;
2.60 UsageCollection = Device.Info.hid.usUsage;
2.61
2.62 - 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
2.63 - && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
2.64 + 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
2.65 + && RawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
2.66 {
2.67 return;
2.68 }
2.69
2.70 //Allocate a buffer for one HID input
2.71 - InputReport = new byte[rawInput.hid.dwSizeHid];
2.72 + InputReport = new byte[RawInput.hid.dwSizeHid];
2.73
2.74 - Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
2.75 + Debug.WriteLine("Raw input contains " + RawInput.hid.dwCount + " HID input report(s)");
2.76
2.77 //For each HID input report in our raw input
2.78 - for (int i = 0; i < rawInput.hid.dwCount; i++)
2.79 + for (int i = 0; i < RawInput.hid.dwCount; i++)
2.80 {
2.81 //Compute the address from which to copy our HID input
2.82 int hidInputOffset = 0;
2.83 unsafe
2.84 {
2.85 byte* source = (byte*)rawInputBuffer;
2.86 - source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
2.87 + source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (RawInput.hid.dwSizeHid * i);
2.88 hidInputOffset = (int)source;
2.89 }
2.90
2.91 //Copy HID input into our buffer
2.92 - Marshal.Copy(new IntPtr(hidInputOffset), InputReport, 0, (int)rawInput.hid.dwSizeHid);
2.93 + Marshal.Copy(new IntPtr(hidInputOffset), InputReport, 0, (int)RawInput.hid.dwSizeHid);
2.94
2.95 //Print HID input report in our debug output
2.96 //string hidDump = "HID input report: " + InputReportString();
2.97 @@ -196,14 +200,14 @@
2.98 }
2.99 }
2.100 }
2.101 - else if (rawInput.header.dwType == RawInputDeviceType.RIM_TYPEMOUSE)
2.102 + else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEMOUSE)
2.103 {
2.104 IsMouse = true;
2.105
2.106 Debug.WriteLine("WM_INPUT source device is Mouse.");
2.107 // do mouse handling...
2.108 }
2.109 - else if (rawInput.header.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD)
2.110 + else if (RawInput.header.dwType == RawInputDeviceType.RIM_TYPEKEYBOARD)
2.111 {
2.112 IsKeyboard = true;
2.113
3.1 --- a/MainForm.Designer.cs Thu Mar 05 10:12:37 2015 +0100
3.2 +++ b/MainForm.Designer.cs Sun Mar 15 09:53:37 2015 +0100
3.3 @@ -29,15 +29,16 @@
3.4 this.buttonTreeViewExpandAll = new System.Windows.Forms.Button();
3.5 this.buttonTreeViewCollapseAll = new System.Windows.Forms.Button();
3.6 this.treeViewDevices = new System.Windows.Forms.TreeView();
3.7 + this.tabPageTests = new System.Windows.Forms.TabPage();
3.8 + this.textBoxTests = new System.Windows.Forms.TextBox();
3.9 this.statusStrip = new System.Windows.Forms.StatusStrip();
3.10 this.toolStripStatusLabelDevice = new System.Windows.Forms.ToolStripStatusLabel();
3.11 - this.tabPageTests = new System.Windows.Forms.TabPage();
3.12 - this.textBoxTests = new System.Windows.Forms.TextBox();
3.13 + this.buttonRefresh = new System.Windows.Forms.Button();
3.14 this.tabControl.SuspendLayout();
3.15 this.tabPageMessages.SuspendLayout();
3.16 this.tabPageDevices.SuspendLayout();
3.17 + this.tabPageTests.SuspendLayout();
3.18 this.statusStrip.SuspendLayout();
3.19 - this.tabPageTests.SuspendLayout();
3.20 this.SuspendLayout();
3.21 //
3.22 // labelButtonName
3.23 @@ -150,6 +151,7 @@
3.24 //
3.25 // tabPageDevices
3.26 //
3.27 + this.tabPageDevices.Controls.Add(this.buttonRefresh);
3.28 this.tabPageDevices.Controls.Add(this.buttonTreeViewExpandAll);
3.29 this.tabPageDevices.Controls.Add(this.buttonTreeViewCollapseAll);
3.30 this.tabPageDevices.Controls.Add(this.treeViewDevices);
3.31 @@ -190,22 +192,6 @@
3.32 this.treeViewDevices.Size = new System.Drawing.Size(713, 492);
3.33 this.treeViewDevices.TabIndex = 0;
3.34 //
3.35 - // statusStrip
3.36 - //
3.37 - this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
3.38 - this.toolStripStatusLabelDevice});
3.39 - this.statusStrip.Location = new System.Drawing.Point(0, 547);
3.40 - this.statusStrip.Name = "statusStrip";
3.41 - this.statusStrip.Size = new System.Drawing.Size(935, 22);
3.42 - this.statusStrip.TabIndex = 5;
3.43 - this.statusStrip.Text = "statusStrip1";
3.44 - //
3.45 - // toolStripStatusLabelDevice
3.46 - //
3.47 - this.toolStripStatusLabelDevice.Name = "toolStripStatusLabelDevice";
3.48 - this.toolStripStatusLabelDevice.Size = new System.Drawing.Size(61, 17);
3.49 - this.toolStripStatusLabelDevice.Text = "No Device";
3.50 - //
3.51 // tabPageTests
3.52 //
3.53 this.tabPageTests.Controls.Add(this.textBoxTests);
3.54 @@ -224,6 +210,32 @@
3.55 this.textBoxTests.Size = new System.Drawing.Size(887, 499);
3.56 this.textBoxTests.TabIndex = 0;
3.57 //
3.58 + // statusStrip
3.59 + //
3.60 + this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
3.61 + this.toolStripStatusLabelDevice});
3.62 + this.statusStrip.Location = new System.Drawing.Point(0, 547);
3.63 + this.statusStrip.Name = "statusStrip";
3.64 + this.statusStrip.Size = new System.Drawing.Size(935, 22);
3.65 + this.statusStrip.TabIndex = 5;
3.66 + this.statusStrip.Text = "statusStrip1";
3.67 + //
3.68 + // toolStripStatusLabelDevice
3.69 + //
3.70 + this.toolStripStatusLabelDevice.Name = "toolStripStatusLabelDevice";
3.71 + this.toolStripStatusLabelDevice.Size = new System.Drawing.Size(61, 17);
3.72 + this.toolStripStatusLabelDevice.Text = "No Device";
3.73 + //
3.74 + // buttonRefresh
3.75 + //
3.76 + this.buttonRefresh.Location = new System.Drawing.Point(813, 64);
3.77 + this.buttonRefresh.Name = "buttonRefresh";
3.78 + this.buttonRefresh.Size = new System.Drawing.Size(75, 23);
3.79 + this.buttonRefresh.TabIndex = 3;
3.80 + this.buttonRefresh.Text = "Refresh";
3.81 + this.buttonRefresh.UseVisualStyleBackColor = true;
3.82 + this.buttonRefresh.Click += new System.EventHandler(this.buttonRefresh_Click);
3.83 + //
3.84 // MainForm
3.85 //
3.86 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
3.87 @@ -238,10 +250,10 @@
3.88 this.tabPageMessages.ResumeLayout(false);
3.89 this.tabPageMessages.PerformLayout();
3.90 this.tabPageDevices.ResumeLayout(false);
3.91 + this.tabPageTests.ResumeLayout(false);
3.92 + this.tabPageTests.PerformLayout();
3.93 this.statusStrip.ResumeLayout(false);
3.94 this.statusStrip.PerformLayout();
3.95 - this.tabPageTests.ResumeLayout(false);
3.96 - this.tabPageTests.PerformLayout();
3.97 this.ResumeLayout(false);
3.98 this.PerformLayout();
3.99
3.100 @@ -254,6 +266,7 @@
3.101 private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelDevice;
3.102 private System.Windows.Forms.TabPage tabPageTests;
3.103 private System.Windows.Forms.TextBox textBoxTests;
3.104 + private System.Windows.Forms.Button buttonRefresh;
3.105
3.106 }
3.107 }
4.1 --- a/MainForm.cs Thu Mar 05 10:12:37 2015 +0100
4.2 +++ b/MainForm.cs Sun Mar 15 09:53:37 2015 +0100
4.3 @@ -177,5 +177,11 @@
4.4 treeViewDevices.ExpandAll();
4.5 }
4.6
4.7 + private void buttonRefresh_Click(object sender, EventArgs e)
4.8 + {
4.9 + treeViewDevices.Nodes.Clear();
4.10 + Win32.RawInput.PopulateDeviceList(treeViewDevices);
4.11 + }
4.12 +
4.13 }
4.14 }
5.1 --- a/RawInput.cs Thu Mar 05 10:12:37 2015 +0100
5.2 +++ b/RawInput.cs Sun Mar 15 09:53:37 2015 +0100
5.3 @@ -207,6 +207,10 @@
5.4 node.Nodes.Add(hidDevice.InputCapabilitiesDescription);
5.5 }
5.6
5.7 + //Add button count
5.8 + node.Nodes.Add("Button Count: " + hidDevice.ButtonCount);
5.9 +
5.10 + //Those can be joystick/gamepad axis
5.11 if (hidDevice.InputValueCapabilities != null)
5.12 {
5.13 foreach (HIDP_VALUE_CAPS caps in hidDevice.InputValueCapabilities)
6.1 --- a/Win32Hid.cs Thu Mar 05 10:12:37 2015 +0100
6.2 +++ b/Win32Hid.cs Sun Mar 15 09:53:37 2015 +0100
6.3 @@ -302,10 +302,10 @@
6.4
6.5 /// Union Range/NotRange
6.6 [FieldOffset(56)]
6.7 - HIDP_BUTTON_CAPS_RANGE Range;
6.8 + public HIDP_BUTTON_CAPS_RANGE Range;
6.9
6.10 [FieldOffset(56)]
6.11 - HIDP_BUTTON_CAPS_NOT_RANGE NotRange;
6.12 + public HIDP_BUTTON_CAPS_NOT_RANGE NotRange;
6.13 }
6.14
6.15 /// <summary>