# HG changeset patch # User sl # Date 1415444479 -3600 # Node ID 2ff6dbe0d356d50f6554b012434c0c553ffeb9df # Parent 17f8421146ba193c8c0484f4ea6adb82cbcc59e1 More code consoludation. Supporting multiple HID input per message. diff -r 17f8421146ba -r 2ff6dbe0d356 HumanInterfaceDevice.cs --- a/HumanInterfaceDevice.cs Fri Nov 07 22:12:22 2014 +0100 +++ b/HumanInterfaceDevice.cs Sat Nov 08 12:01:19 2014 +0100 @@ -64,7 +64,7 @@ /// /// /// - public enum MceButton + public enum MceButton: ushort { /// /// Not defined by the Microsoft specs. @@ -188,6 +188,9 @@ VideoSelection = 0x61 } + /// + /// Those codes come from experimenting with HP remotes. + /// public enum HpMceButton: ushort { /// diff -r 17f8421146ba -r 2ff6dbe0d356 RemoteControlDevice.cs --- a/RemoteControlDevice.cs Fri Nov 07 22:12:22 2014 +0100 +++ b/RemoteControlDevice.cs Sat Nov 08 12:01:19 2014 +0100 @@ -353,94 +353,101 @@ try { //Fetch raw input - RAWINPUT raw = new RAWINPUT(); - if (!RawInput.GetRawInputData(message.LParam, ref raw, ref rawInputBuffer)) + RAWINPUT rawInput = new RAWINPUT(); + if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer)) { return; } //Fetch device info RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO(); - if (!RawInput.GetDeviceInfo(raw.header.hDevice, ref deviceInfo)) + if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo)) { return; } + - //Check type of input device and quite if we don't like it - switch (deviceInfo.dwType) + if (rawInput.header.dwType == Const.RIM_TYPEHID) //Check that our raw input is HID { - case Const.RIM_TYPEHID: - Debug.WriteLine("WM_INPUT source device is HID."); - break; - case Const.RIM_TYPEMOUSE: - Debug.WriteLine("WM_INPUT source device is Mouse."); - return; - case Const.RIM_TYPEKEYBOARD: - Debug.WriteLine("WM_INPUT source device is Keyboard."); - return; - default: - Debug.WriteLine("WM_INPUT source device is Unknown."); - return; - } - - //Get Usage Page and Usage - Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4")); - - - if (raw.header.dwType == Const.RIM_TYPEHID //Check that our raw input is HID - && raw.hid.dwSizeHid > 1 //Make sure our HID msg size more than 1. In fact the first ushort is irrelevant to us for now - && raw.hid.dwCount > 0) //Check that we have at least one HID msg - { - //TODO: for each HID message - - //Allocate a buffer for one HID message - byte[] bRawData = new byte[raw.hid.dwSizeHid]; - - //Compute the address from which to copy our HID message - int pRawData = 0; - unsafe - { - byte* source = (byte*)rawInputBuffer; - source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID); - pRawData = (int)source; - } - - //Copy HID message into our buffer - Marshal.Copy(new IntPtr(pRawData), bRawData, 0, raw.hid.dwSizeHid); - //bRawData[0] //Not sure what's the meaning of the code at offset 0 - //TODO: check size before access - int rawData = bRawData[1]; //Get button code - //Print HID codes in our debug output - string hidDump = "HID " + raw.hid.dwCount + "/" + raw.hid.dwSizeHid + ":"; - foreach (byte b in bRawData) - { - hidDump += b.ToString("X2"); - } - Debug.WriteLine(hidDump); - + Debug.WriteLine("WM_INPUT source device is HID."); + //Get Usage Page and Usage + Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4")); //Make sure both usage page and usage are matching MCE remote + //TODO: handle more that just MCE usage page. if (deviceInfo.hid.usUsagePage != (ushort)Hid.UsagePage.MceRemote || deviceInfo.hid.usUsage != (ushort)Hid.UsageId.MceRemoteUsage) { Debug.WriteLine("Not MCE remote page and usage."); return; } - if (Enum.IsDefined(typeof(MceButton), rawData) && rawData != 0) //Our button is a known MCE button + 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 { - if (this.ButtonPressed != null) //What's that? + return; + } + + + //Allocate a buffer for one HID input + byte[] hidInput = new byte[rawInput.hid.dwSizeHid]; + + //For each HID input 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 { - this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32()))); + 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), hidInput, 0, rawInput.hid.dwSizeHid); + + //Print HID raw input in our debug output + string hidDump = "HID " + rawInput.hid.dwCount + "/" + rawInput.hid.dwSizeHid + ":"; + foreach (byte b in hidInput) + { + hidDump += b.ToString("X2"); + } + Debug.WriteLine(hidDump); + + ushort usage = 0; + //hidInput[0] //Not sure what's the meaning of the code at offset 0 + if (hidInput.Length == 2) + { + //Single byte code + usage = hidInput[1]; //Get button code + } + else if (hidInput.Length > 2) //Defensive + { + //Assuming double bytes code + usage = (ushort)((hidInput[1] << 2) + hidInput[2]); + } + + // + if (Enum.IsDefined(typeof(MceButton), usage) && usage != 0) //Our button is a known MCE button + { + if (this.ButtonPressed != null) //What's that? + { + this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)usage, InputDevice.OEM)); + } } } + } - else if (raw.header.dwType == Const.RIM_TYPEMOUSE) + else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE) { + Debug.WriteLine("WM_INPUT source device is Mouse."); // do mouse handling... } - else if (raw.header.dwType == Const.RIM_TYPEKEYBOARD) + else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD) { + Debug.WriteLine("WM_INPUT source device is Keyboard."); // do keyboard handling... + } } finally