More code consoludation. Supporting multiple HID input per message.
1.1 --- a/HumanInterfaceDevice.cs Fri Nov 07 22:12:22 2014 +0100
1.2 +++ b/HumanInterfaceDevice.cs Sat Nov 08 12:01:19 2014 +0100
1.3 @@ -64,7 +64,7 @@
1.4 /// <summary>
1.5 ///
1.6 /// </summary>
1.7 - public enum MceButton
1.8 + public enum MceButton: ushort
1.9 {
1.10 /// <summary>
1.11 /// Not defined by the Microsoft specs.
1.12 @@ -188,6 +188,9 @@
1.13 VideoSelection = 0x61
1.14 }
1.15
1.16 + /// <summary>
1.17 + /// Those codes come from experimenting with HP remotes.
1.18 + /// </summary>
1.19 public enum HpMceButton: ushort
1.20 {
1.21 /// <summary>
2.1 --- a/RemoteControlDevice.cs Fri Nov 07 22:12:22 2014 +0100
2.2 +++ b/RemoteControlDevice.cs Sat Nov 08 12:01:19 2014 +0100
2.3 @@ -353,94 +353,101 @@
2.4 try
2.5 {
2.6 //Fetch raw input
2.7 - RAWINPUT raw = new RAWINPUT();
2.8 - if (!RawInput.GetRawInputData(message.LParam, ref raw, ref rawInputBuffer))
2.9 + RAWINPUT rawInput = new RAWINPUT();
2.10 + if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
2.11 {
2.12 return;
2.13 }
2.14
2.15 //Fetch device info
2.16 RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
2.17 - if (!RawInput.GetDeviceInfo(raw.header.hDevice, ref deviceInfo))
2.18 + if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
2.19 {
2.20 return;
2.21 }
2.22 +
2.23
2.24 - //Check type of input device and quite if we don't like it
2.25 - switch (deviceInfo.dwType)
2.26 + if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID
2.27 {
2.28 - case Const.RIM_TYPEHID:
2.29 - Debug.WriteLine("WM_INPUT source device is HID.");
2.30 - break;
2.31 - case Const.RIM_TYPEMOUSE:
2.32 - Debug.WriteLine("WM_INPUT source device is Mouse.");
2.33 - return;
2.34 - case Const.RIM_TYPEKEYBOARD:
2.35 - Debug.WriteLine("WM_INPUT source device is Keyboard.");
2.36 - return;
2.37 - default:
2.38 - Debug.WriteLine("WM_INPUT source device is Unknown.");
2.39 - return;
2.40 - }
2.41 -
2.42 - //Get Usage Page and Usage
2.43 - Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
2.44 -
2.45 -
2.46 - if (raw.header.dwType == Const.RIM_TYPEHID //Check that our raw input is HID
2.47 - && raw.hid.dwSizeHid > 1 //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now
2.48 - && raw.hid.dwCount > 0) //Check that we have at least one HID msg
2.49 - {
2.50 - //TODO: for each HID message
2.51 -
2.52 - //Allocate a buffer for one HID message
2.53 - byte[] bRawData = new byte[raw.hid.dwSizeHid];
2.54 -
2.55 - //Compute the address from which to copy our HID message
2.56 - int pRawData = 0;
2.57 - unsafe
2.58 - {
2.59 - byte* source = (byte*)rawInputBuffer;
2.60 - source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID);
2.61 - pRawData = (int)source;
2.62 - }
2.63 -
2.64 - //Copy HID message into our buffer
2.65 - Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid);
2.66 - //bRawData[0] //Not sure what's the meaning of the code at offset 0
2.67 - //TODO: check size before access
2.68 - int rawData = bRawData[1]; //Get button code
2.69 - //Print HID codes in our debug output
2.70 - string hidDump = "HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":";
2.71 - foreach (byte b in bRawData)
2.72 - {
2.73 - hidDump += b.ToString("X2");
2.74 - }
2.75 - Debug.WriteLine(hidDump);
2.76 -
2.77 + Debug.WriteLine("WM_INPUT source device is HID.");
2.78 + //Get Usage Page and Usage
2.79 + Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
2.80
2.81 //Make sure both usage page and usage are matching MCE remote
2.82 + //TODO: handle more that just MCE usage page.
2.83 if (deviceInfo.hid.usUsagePage != (ushort)Hid.UsagePage.MceRemote || deviceInfo.hid.usUsage != (ushort)Hid.UsageId.MceRemoteUsage)
2.84 {
2.85 Debug.WriteLine("Not MCE remote page and usage.");
2.86 return;
2.87 }
2.88
2.89 - if (Enum.IsDefined(typeof(MceButton), rawData) && rawData != 0) //Our button is a known MCE button
2.90 + 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.91 + && rawInput.hid.dwCount > 0)) //Check that we have at least one HID msg
2.92 {
2.93 - if (this.ButtonPressed != null) //What's that?
2.94 + return;
2.95 + }
2.96 +
2.97 +
2.98 + //Allocate a buffer for one HID input
2.99 + byte[] hidInput = new byte[rawInput.hid.dwSizeHid];
2.100 +
2.101 + //For each HID input in our raw input
2.102 + for (int i = 0; i < rawInput.hid.dwCount; i++)
2.103 + {
2.104 + //Compute the address from which to copy our HID input
2.105 + int hidInputOffset = 0;
2.106 + unsafe
2.107 {
2.108 - this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
2.109 + byte* source = (byte*)rawInputBuffer;
2.110 + source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
2.111 + hidInputOffset = (int)source;
2.112 + }
2.113 +
2.114 + //Copy HID input into our buffer
2.115 + Marshal.Copy(new IntPtr(hidInputOffset), hidInput, 0, rawInput.hid.dwSizeHid);
2.116 +
2.117 + //Print HID raw input in our debug output
2.118 + string hidDump = "HID " + rawInput.hid.dwCount + "/" + rawInput.hid.dwSizeHid + ":";
2.119 + foreach (byte b in hidInput)
2.120 + {
2.121 + hidDump += b.ToString("X2");
2.122 + }
2.123 + Debug.WriteLine(hidDump);
2.124 +
2.125 + ushort usage = 0;
2.126 + //hidInput[0] //Not sure what's the meaning of the code at offset 0
2.127 + if (hidInput.Length == 2)
2.128 + {
2.129 + //Single byte code
2.130 + usage = hidInput[1]; //Get button code
2.131 + }
2.132 + else if (hidInput.Length > 2) //Defensive
2.133 + {
2.134 + //Assuming double bytes code
2.135 + usage = (ushort)((hidInput[1] << 2) + hidInput[2]);
2.136 + }
2.137 +
2.138 + //
2.139 + if (Enum.IsDefined(typeof(MceButton), usage) && usage != 0) //Our button is a known MCE button
2.140 + {
2.141 + if (this.ButtonPressed != null) //What's that?
2.142 + {
2.143 + this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)usage, InputDevice.OEM));
2.144 + }
2.145 }
2.146 }
2.147 +
2.148 }
2.149 - else if (raw.header.dwType == Const.RIM_TYPEMOUSE)
2.150 + else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
2.151 {
2.152 + Debug.WriteLine("WM_INPUT source device is Mouse.");
2.153 // do mouse handling...
2.154 }
2.155 - else if (raw.header.dwType == Const.RIM_TYPEKEYBOARD)
2.156 + else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
2.157 {
2.158 + Debug.WriteLine("WM_INPUT source device is Keyboard.");
2.159 // do keyboard handling...
2.160 +
2.161 }
2.162 }
2.163 finally