HidEvent implementation.
authorsl
Sat, 06 Dec 2014 21:52:45 +0100
changeset 27305d2ecd3b1a
parent 26 0166dfab3349
child 28 6af1cbb3beb4
HidEvent implementation.
HidEvent.cs
HidUsageTables.cs
HumanInterfaceDevice.cs
RemoteControlDevice.cs
RemoteControlSample.csproj
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/HidEvent.cs	Sat Dec 06 21:52:45 2014 +0100
     1.3 @@ -0,0 +1,206 @@
     1.4 +using System;
     1.5 +using System.Windows.Forms;
     1.6 +using System.Runtime.InteropServices;
     1.7 +using System.Diagnostics;
     1.8 +using System.Text;
     1.9 +using Microsoft.Win32.SafeHandles;
    1.10 +using Win32;
    1.11 +using System.Collections.Generic;
    1.12 +
    1.13 +
    1.14 +namespace Hid
    1.15 +{
    1.16 +    /// <summary>
    1.17 +    /// Represent a HID event.
    1.18 +    /// </summary>
    1.19 +    class HidEvent
    1.20 +    {
    1.21 +        public bool IsValid { get; private set; }
    1.22 +        public bool IsForeground { get; private set; }
    1.23 +        public bool IsBackground { get{return !IsForeground;} }
    1.24 +        public bool IsMouse { get; private set; }
    1.25 +        public bool IsKeyboard { get; private set; }
    1.26 +        public bool IsGeneric { get; private set; }
    1.27 +
    1.28 +        public HidDevice Device { get; private set; }
    1.29 +
    1.30 +        public ushort UsagePage { get; private set; }
    1.31 +        public ushort UsageCollection { get; private set; }
    1.32 +        public List<ushort> Usages { get; private set; }
    1.33 +
    1.34 +
    1.35 +        /// <summary>
    1.36 +        /// Initialize an HidEvent from a WM_INPUT message
    1.37 +        /// </summary>
    1.38 +        /// <param name="hRawInputDevice">Device Handle as provided by RAWINPUTHEADER.hDevice, typically accessed as rawinput.header.hDevice</param>
    1.39 +        public HidEvent(Message aMessage)
    1.40 +        {
    1.41 +            IsValid = false;
    1.42 +            IsKeyboard = false;
    1.43 +            IsGeneric = false;
    1.44 +
    1.45 +            Usages = new List<ushort>();
    1.46 +
    1.47 +            if (aMessage.Msg != Const.WM_INPUT)
    1.48 +            {
    1.49 +                //Has to be a WM_INPUT message
    1.50 +                return;
    1.51 +            }
    1.52 +
    1.53 +            if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUT)
    1.54 +            {
    1.55 +                IsForeground = true;
    1.56 +            }
    1.57 +            else if (Macro.GET_RAWINPUT_CODE_WPARAM(aMessage.WParam) == Const.RIM_INPUTSINK)
    1.58 +            {
    1.59 +                IsForeground = false;
    1.60 +            }
    1.61 +
    1.62 +            //Declare some pointers
    1.63 +            IntPtr rawInputBuffer = IntPtr.Zero;
    1.64 +            //My understanding is that this is basically our HID descriptor 
    1.65 +            IntPtr preParsedData = IntPtr.Zero;
    1.66 +
    1.67 +            try
    1.68 +            {
    1.69 +                //Fetch raw input
    1.70 +                RAWINPUT rawInput = new RAWINPUT();
    1.71 +                if (!RawInput.GetRawInputData(aMessage.LParam, ref rawInput, ref rawInputBuffer))
    1.72 +                {
    1.73 +                    return;
    1.74 +                }
    1.75 +
    1.76 +                //Fetch device info
    1.77 +                RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
    1.78 +                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
    1.79 +                {
    1.80 +                    return;
    1.81 +                }
    1.82 +
    1.83 +                //Get various information about this HID device
    1.84 +                Device = new Hid.HidDevice(rawInput.header.hDevice);                
    1.85 +
    1.86 +                if (rawInput.header.dwType == Const.RIM_TYPEHID)  //Check that our raw input is HID                        
    1.87 +                {
    1.88 +                    IsGeneric = true;
    1.89 +
    1.90 +                    Debug.WriteLine("WM_INPUT source device is HID.");
    1.91 +                    //Get Usage Page and Usage
    1.92 +                    //Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
    1.93 +                    UsagePage = deviceInfo.hid.usUsagePage;
    1.94 +                    UsageCollection = deviceInfo.hid.usUsage;
    1.95 +
    1.96 +                    preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
    1.97 +
    1.98 +                    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
    1.99 +                        && rawInput.hid.dwCount > 0))    //Check that we have at least one HID msg
   1.100 +                    {
   1.101 +                        return;
   1.102 +                    }
   1.103 +
   1.104 +                    //Allocate a buffer for one HID input
   1.105 +                    byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
   1.106 +
   1.107 +                    Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
   1.108 +
   1.109 +                    //For each HID input report in our raw input
   1.110 +                    for (int i = 0; i < rawInput.hid.dwCount; i++)
   1.111 +                    {
   1.112 +                        //Compute the address from which to copy our HID input
   1.113 +                        int hidInputOffset = 0;
   1.114 +                        unsafe
   1.115 +                        {
   1.116 +                            byte* source = (byte*)rawInputBuffer;
   1.117 +                            source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
   1.118 +                            hidInputOffset = (int)source;
   1.119 +                        }
   1.120 +
   1.121 +                        //Copy HID input into our buffer
   1.122 +                        Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
   1.123 +
   1.124 +                        //Print HID input report in our debug output
   1.125 +                        string hidDump = "HID input report: ";
   1.126 +                        foreach (byte b in hidInputReport)
   1.127 +                        {
   1.128 +                            hidDump += b.ToString("X2");
   1.129 +                        }
   1.130 +                        Debug.WriteLine(hidDump);
   1.131 +
   1.132 +                        //Proper parsing now
   1.133 +                        uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
   1.134 +                        Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
   1.135 +                        Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
   1.136 +                        if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
   1.137 +                        {
   1.138 +                            Debug.WriteLine("Could not parse HID data!");
   1.139 +                        }
   1.140 +                        else
   1.141 +                        {
   1.142 +                            //Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
   1.143 +                            //Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
   1.144 +                            //Add this usage to our list
   1.145 +                            Usages.Add(usages[0].Usage);
   1.146 +                        }
   1.147 +                    }
   1.148 +
   1.149 +                }
   1.150 +                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
   1.151 +                {
   1.152 +                    IsMouse = true;
   1.153 +
   1.154 +                    Debug.WriteLine("WM_INPUT source device is Mouse.");                    
   1.155 +                    // do mouse handling...
   1.156 +                }
   1.157 +                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
   1.158 +                {
   1.159 +                    IsKeyboard = true;
   1.160 +
   1.161 +                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
   1.162 +                    // do keyboard handling...
   1.163 +                    Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
   1.164 +                    Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
   1.165 +                    Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
   1.166 +                    Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
   1.167 +                    Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
   1.168 +                    Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
   1.169 +                }
   1.170 +            }
   1.171 +            finally
   1.172 +            {
   1.173 +                //Always executed when leaving our try block
   1.174 +                Marshal.FreeHGlobal(rawInputBuffer);
   1.175 +                Marshal.FreeHGlobal(preParsedData);
   1.176 +            }
   1.177 +
   1.178 +            IsValid = true;
   1.179 +        }
   1.180 +
   1.181 +        /// <summary>
   1.182 +        /// Print information about this device to our debug output.
   1.183 +        /// </summary>
   1.184 +        public void DebugWrite()
   1.185 +        {
   1.186 +            if (!IsValid)
   1.187 +            {
   1.188 +                Debug.WriteLine("==== Invalid HidEvent");
   1.189 +                return;
   1.190 +            }
   1.191 +            Device.DebugWrite();
   1.192 +            if (IsGeneric) Debug.WriteLine("==== Generic");
   1.193 +            if (IsKeyboard) Debug.WriteLine("==== Keyboard");
   1.194 +            if (IsMouse) Debug.WriteLine("==== Mouse");
   1.195 +            Debug.WriteLine("==== Foreground: " + IsForeground.ToString());
   1.196 +            Debug.WriteLine("==== UsagePage: 0x" + UsagePage.ToString("X4"));
   1.197 +            Debug.WriteLine("==== UsageCollection: 0x" + UsageCollection.ToString("X4"));
   1.198 +            foreach (ushort usage in Usages)
   1.199 +            {
   1.200 +                Debug.WriteLine("==== Usage: 0x" + usage.ToString("X4"));
   1.201 +            }
   1.202 +        }
   1.203 +
   1.204 +
   1.205 +
   1.206 +
   1.207 +    }
   1.208 +
   1.209 +}
   1.210 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/HidUsageTables.cs	Sat Dec 06 21:52:45 2014 +0100
     2.3 @@ -0,0 +1,394 @@
     2.4 +//
     2.5 +//
     2.6 +//
     2.7 +
     2.8 +namespace Hid
     2.9 +{
    2.10 +    /// <summary>
    2.11 +    /// From USB HID usage tables.
    2.12 +    /// http://www.usb.org/developers/hidpage#HID_Usage
    2.13 +    /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
    2.14 +    /// </summary>
    2.15 +    public enum UsagePage : ushort
    2.16 +    {
    2.17 +        Undefined = 0,
    2.18 +        GenericDesktopControl,
    2.19 +        SimulationControl,
    2.20 +        VirtualRealityControl,
    2.21 +        SportControl,
    2.22 +        GameControl,
    2.23 +        GenericDeviceControl,
    2.24 +        Keyboard,
    2.25 +        LightEmittingDiode,
    2.26 +        Button,
    2.27 +        Ordinal,
    2.28 +        Telephony,
    2.29 +        Consumer,
    2.30 +        Digitiser,
    2.31 +        PhysicalInterfaceDevice = 0x0f,
    2.32 +        Unicode = 0x10,
    2.33 +        AlphaNumericDisplay = 0x14,
    2.34 +        MedicalInstruments = 0x40,
    2.35 +        MonitorPage0 = 0x80,
    2.36 +        MonitorPage1,
    2.37 +        MonitorPage2,
    2.38 +        MonitorPage3,
    2.39 +        PowerPage0,
    2.40 +        PowerPage1,
    2.41 +        PowerPage2,
    2.42 +        PowerPage3,
    2.43 +        BarCodeScanner = 0x8c,
    2.44 +        Scale,
    2.45 +        MagneticStripeReader,
    2.46 +        ReservedPointOfSale,
    2.47 +        CameraControl,
    2.48 +        Arcade,
    2.49 +        // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx
    2.50 +        MceRemote = 0xffbc,
    2.51 +        TerraTecRemote = 0xffcc
    2.52 +    }
    2.53 +
    2.54 +    public enum UsageIdGenericDesktop : ushort
    2.55 +    {      
    2.56 +        Pointer = 0x01,
    2.57 +        Mouse = 0x02,
    2.58 +        Joystick = 0x04,
    2.59 +        GamePad = 0x05,
    2.60 +        Keyboard = 0x06,
    2.61 +        KeyPad = 0x07,
    2.62 +        MultiAxisController = 0x08,
    2.63 +        TabletPCSystemControls = 0x09,
    2.64 +        SystemControl = 0x80
    2.65 +    }
    2.66 +
    2.67 +    public enum UsageIdConsumer : ushort
    2.68 +    {
    2.69 +        ConsumerControl = 0x01,
    2.70 +        NumericKeyPad = 0x02,
    2.71 +        ProgrammableButtons = 0x03,
    2.72 +        Microphone = 0x04,
    2.73 +        Headphone = 0x05,
    2.74 +        GraphicEqualizer = 0x06,
    2.75 +        Selection = 0x80,
    2.76 +    }
    2.77 +
    2.78 +    
    2.79 +    public enum UsageIdMce: ushort
    2.80 +    {
    2.81 +        MceRemote = 0x88        
    2.82 +    }
    2.83 +
    2.84 +
    2.85 +
    2.86 +    namespace UsageTables
    2.87 +    {
    2.88 +        /// <summary>
    2.89 +        ///
    2.90 +        /// </summary>
    2.91 +        public enum MceButton: ushort
    2.92 +        {
    2.93 +            /// <summary>
    2.94 +            /// Not defined by the Microsoft specs.
    2.95 +            /// </summary>
    2.96 +            Null                    =   0x00,
    2.97 +            GreenStart              =   0x0D,
    2.98 +            ClosedCaptioning        =   0x2B,
    2.99 +            Teletext                =   0x5A,
   2.100 +            TeletextRed             =   0x5B,
   2.101 +            TeletextGreen           =   0x5C,
   2.102 +            TeletextYellow          =   0x5D,
   2.103 +            TeletextBlue            =   0x5E,
   2.104 +            LiveTv                  =   0x25,
   2.105 +            Music                   =   0x47,
   2.106 +            RecordedTv              =   0x48,
   2.107 +            Pictures                =   0x49,
   2.108 +            Videos                  =   0x4A,
   2.109 +            FmRadio                 =   0x50,
   2.110 +            Extras                  =   0x3C,
   2.111 +            ExtrasApp               =   0x3D,
   2.112 +            DvdMenu                 =   0x24,
   2.113 +            DvdAngle                =   0x4B,
   2.114 +            DvdAudio                =   0x4C,
   2.115 +            DvdSubtitle             =   0x4D,
   2.116 +            /// <summary>
   2.117 +            /// First press action: Ejects a DVD drive.
   2.118 +            /// <para />
   2.119 +            /// Second press action: Repeats first press action.
   2.120 +            /// <para />
   2.121 +            /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
   2.122 +            /// </summary>
   2.123 +            Eject                   =   0x28,
   2.124 +            DvdTopMenu              =   0x43,
   2.125 +            /// <summary>
   2.126 +            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   2.127 +            /// Collection (page 0xFFBC, usage 0x88).
   2.128 +            /// <para />
   2.129 +            /// Second press action: Repeats message.
   2.130 +            /// <para />
   2.131 +            /// Auto-repeat: No
   2.132 +            /// <para />
   2.133 +            /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
   2.134 +            /// <para />
   2.135 +            /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
   2.136 +            /// </summary>
   2.137 +            Ext0                    =   0x32,
   2.138 +            /// <summary>
   2.139 +            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   2.140 +            /// Collection (page 0xFFBC, usage 0x88).
   2.141 +            /// <para />
   2.142 +            /// Second press action: Repeats message.
   2.143 +            /// <para />
   2.144 +            /// Auto-repeat: No
   2.145 +            /// <para />
   2.146 +            /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
   2.147 +            /// <para />
   2.148 +            /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
   2.149 +            /// </summary>
   2.150 +            Ext1                    =   0x33,
   2.151 +            /// <summary>
   2.152 +            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   2.153 +            /// Collection (page 0xFFBC, usage 0x88).
   2.154 +            /// <para />
   2.155 +            /// Second press action: Repeats message.
   2.156 +            /// <para />
   2.157 +            /// Auto-repeat: No
   2.158 +            /// <para />
   2.159 +            /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
   2.160 +            /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
   2.161 +            /// </summary>
   2.162 +            Ext2                    =   0x34,
   2.163 +            /// <summary>
   2.164 +            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   2.165 +            /// Collection (page 0xFFBC, usage 0x88).
   2.166 +            /// <para />
   2.167 +            /// Second press action: Repeats message.
   2.168 +            /// <para />
   2.169 +            /// Auto-repeat: No
   2.170 +            /// <para />
   2.171 +            /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
   2.172 +            /// </summary>
   2.173 +            Ext3                    =   0x35,
   2.174 +            Ext4                    =   0x36,
   2.175 +            Ext5                    =   0x37,
   2.176 +            Ext6                    =   0x38,
   2.177 +            Ext7                    =   0x39,
   2.178 +            Ext8                    =   0x3A,
   2.179 +            Ext9                    =   0x80,
   2.180 +            Ext10                   =   0x81,
   2.181 +            Ext11                   =   0x6F,
   2.182 +            Zoom                    =   0x27,
   2.183 +            ChannelInput            =   0x42,
   2.184 +            SubAudio                =   0x2D,
   2.185 +            Channel10               =   0x3E,
   2.186 +            Channel11               =   0x3F,
   2.187 +            Channel12               =   0x40,
   2.188 +            /// <summary>
   2.189 +            /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific
   2.190 +            /// Collection. This button is intended to control the front panel display of home entertainment
   2.191 +            /// computers. When this button is pressed, the display could be turned on or off, or the display
   2.192 +            /// mode could change.
   2.193 +            /// <para />
   2.194 +            /// Second press action: Repeats message.
   2.195 +            /// <para />
   2.196 +            /// Auto-repeat: No
   2.197 +            /// <para />
   2.198 +            /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
   2.199 +            /// </summary>
   2.200 +            Display                 =   0x4F,
   2.201 +            /// <summary>
   2.202 +            /// First press action: To be determined.
   2.203 +            /// <para />
   2.204 +            /// Second press action: Repeats message.
   2.205 +            /// <para />
   2.206 +            /// Auto-repeat: No
   2.207 +            /// </summary>
   2.208 +            Kiosk                   =   0x6A,
   2.209 +            NetworkSelection        =   0x2C,
   2.210 +            BlueRayTool             =   0x78,
   2.211 +            ChannelInfo             =   0x41,
   2.212 +            VideoSelection          =   0x61
   2.213 +        }
   2.214 +
   2.215 +        /// <summary>
   2.216 +        /// Those codes come from experimenting with HP remotes.
   2.217 +        /// </summary>
   2.218 +        public enum HpMceButton: ushort
   2.219 +        {
   2.220 +            /// <summary>
   2.221 +            /// Displays visual imagery that is synchronized to the sound of your music tracks.
   2.222 +            /// <para />
   2.223 +            /// Second press action: Repeats message.
   2.224 +            /// <para />
   2.225 +            /// Auto-repeat: No
   2.226 +            /// <para />
   2.227 +            /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
   2.228 +            /// <para />
   2.229 +            /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
   2.230 +            /// </summary>
   2.231 +            Visualization = MceButton.Ext0,
   2.232 +            /// <summary>
   2.233 +            /// Plays a slide show of all the pictures on your hard disk drive.
   2.234 +            /// <para />
   2.235 +            /// Second press action: Repeats message.
   2.236 +            /// <para />
   2.237 +            /// Auto-repeat: No
   2.238 +            /// <para />
   2.239 +            /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
   2.240 +            /// <para />
   2.241 +            /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
   2.242 +            /// </summary>
   2.243 +            SlideShow = MceButton.Ext1,
   2.244 +            /// <summary>
   2.245 +            /// Eject optical drive.
   2.246 +            /// <para />
   2.247 +            /// Second press action: Repeats message.
   2.248 +            /// <para />
   2.249 +            /// Auto-repeat: No
   2.250 +            /// <para />
   2.251 +            /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
   2.252 +            /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
   2.253 +            /// </summary>
   2.254 +            Eject = MceButton.Ext2,
   2.255 +            /// <summary>
   2.256 +            /// Not sure what this should do.
   2.257 +            /// <para />
   2.258 +            /// Second press action: Repeats message.
   2.259 +            /// <para />
   2.260 +            /// Auto-repeat: No
   2.261 +            /// <para />
   2.262 +            /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
   2.263 +            /// </summary>
   2.264 +            InputSelection = MceButton.Ext3,
   2.265 +        }
   2.266 +
   2.267 +        /// <summary>
   2.268 +        /// Usage Table for Consumer Controls
   2.269 +        /// 0x0C 0X01
   2.270 +        /// </summary>
   2.271 +        public enum ConsumerControl: ushort
   2.272 +        {
   2.273 +            Null = 0x0000,           
   2.274 +            //           
   2.275 +            Channel = 0x0086,
   2.276 +            MediaSelection = 0x0087,
   2.277 +            MediaSelectComputer = 0x0088,
   2.278 +            MediaSelectTV = 0x0089,
   2.279 +            MediaSelectWWW = 0x008A,
   2.280 +            MediaSelectDVD = 0x008B,
   2.281 +            MediaSelectTelephone = 0x008C,
   2.282 +            MediaSelectProgramGuide = 0x008D,
   2.283 +            MediaSelectVideoPhone = 0x008E,
   2.284 +            MediaSelectGames = 0x008F,
   2.285 +            MediaSelectMessages = 0x0090,
   2.286 +            MediaSelectCD = 0x0091,
   2.287 +            MediaSelectVCR = 0x0092,
   2.288 +            MediaSelectTuner = 0x0093,
   2.289 +            Quit = 0x0094,
   2.290 +            Help = 0x0095,
   2.291 +            MediaSelectTape = 0x0096,
   2.292 +            MediaSelectCable = 0x0097,
   2.293 +            MediaSelectSatellite = 0x0098,
   2.294 +            MediaSelectSecurity = 0x0099,
   2.295 +            MediaSelectHome = 0x009A,
   2.296 +            MediaSelectCall = 0x009B,
   2.297 +            ChannelIncrement = 0x009C,
   2.298 +            ChannelDecrement = 0x009D,
   2.299 +            MediaSelectSAP = 0x009E,
   2.300 +            //
   2.301 +            Play = 0x00B0,
   2.302 +            Pause = 0x00B1,
   2.303 +            Record = 0x00B2,
   2.304 +            FastForward = 0x00B3,
   2.305 +            Rewind = 0x00B4,
   2.306 +            ScanNextTrack = 0x00B5,
   2.307 +            ScanPreviousTrack = 0x00B6,
   2.308 +            Stop = 0x00B7,
   2.309 +            Eject = 0x00B8,
   2.310 +            RandomPlay = 0x00B9,
   2.311 +            SelectDisc = 0x00BA,
   2.312 +            EnterDisc = 0x00BB,
   2.313 +            Repeat = 0x00BC,
   2.314 +            Tracking = 0x00BD,
   2.315 +            TrackNormal = 0x00BE,
   2.316 +            SlowTracking = 0x00BF,
   2.317 +            FrameForward = 0x00C0,
   2.318 +            FrameBack = 0x00C1,
   2.319 +            Mark = 0x00C2,
   2.320 +            ClearMark = 0x00C3,
   2.321 +            RepeatFromMark = 0x00C4,
   2.322 +            ReturnToMark = 0x00C5,
   2.323 +            SearchMarkForward = 0x00C6,
   2.324 +            SearchMarkBackwards = 0x00C7,
   2.325 +            CounterReset = 0x00C8,
   2.326 +            ShowCounter = 0x00C9,
   2.327 +            TrackingIncrement = 0x00CA,
   2.328 +            TrackingDecrement = 0x00CB,
   2.329 +            StopEject = 0x00CC,
   2.330 +            PlayPause = 0x00CD,
   2.331 +            PlaySkip = 0x00CE,
   2.332 +
   2.333 +            /// <summary>
   2.334 +            /// Audio controls
   2.335 +            /// </summary>
   2.336 +            Volume = 0x00E0,
   2.337 +            Balance = 0x00E1,
   2.338 +            Mute = 0x00E2,
   2.339 +            Bass = 0x00E3,
   2.340 +            Treble = 0x00E4,
   2.341 +            BassBoost = 0x00E5,
   2.342 +            SurroundMode = 0x00E6,
   2.343 +            Loudness = 0x00E7,
   2.344 +            MPX = 0x00E8,
   2.345 +            VolumeIncrement = 0x00E9,
   2.346 +            VolumeDecrement = 0x00EA,
   2.347 +
   2.348 +            //Generic GUI Application Controls
   2.349 +            GenericGUIApplicationControls = 0x0200,
   2.350 +            AppCtrlNew = 0x0201,
   2.351 +            AppCtrlOpen = 0x0202,
   2.352 +            AppCtrlClose = 0x0203,
   2.353 +            AppCtrlExit = 0x0204,
   2.354 +            AppCtrlMaximize = 0x0205,
   2.355 +            AppCtrlMinimize = 0x0206,
   2.356 +            AppCtrlSave = 0x0207,
   2.357 +            AppCtrlPrint = 0x0208,
   2.358 +            AppCtrlProperties = 0x0209,
   2.359 +            AppCtrlUndo = 0x021A,
   2.360 +            AppCtrlCopy = 0x021B,
   2.361 +            AppCtrlCut = 0x021C,
   2.362 +            AppCtrlPaste = 0x021D,
   2.363 +            AppCtrlSelectAll = 0x021E,
   2.364 +            AppCtrlFind = 0x021F,
   2.365 +            AppCtrlFindAndReplace = 0x0220,
   2.366 +            AppCtrlSearch = 0x0221,
   2.367 +            AppCtrlGoTo = 0x0222,
   2.368 +            AppCtrlHome = 0x0223,
   2.369 +            AppCtrlBack = 0x0224,
   2.370 +            AppCtrlForward = 0x0225,
   2.371 +            AppCtrlStop = 0x0226,
   2.372 +            AppCtrlRefresh = 0x0227,
   2.373 +            AppCtrlPreviousLink = 0x0228,
   2.374 +            AppCtrlNextLink = 0x0229,
   2.375 +            AppCtrlBookmarks = 0x022A,
   2.376 +            AppCtrlHistory = 0x022B,
   2.377 +            AppCtrlSubscriptions = 0x022C,
   2.378 +            AppCtrlZoomIn = 0x022D,
   2.379 +            AppCtrlZoomOut = 0x022E,
   2.380 +            AppCtrlZoom = 0x022F,
   2.381 +            AppCtrlFullScreenView = 0x0230,
   2.382 +            AppCtrlNormalView = 0x0231,
   2.383 +            AppCtrlViewToggle = 0x0232,
   2.384 +            AppCtrlScrollUp = 0x0233,
   2.385 +            AppCtrlScrollDown = 0x0234,
   2.386 +            AppCtrlScroll = 0x0235,
   2.387 +            AppCtrlPanLeft = 0x0236,
   2.388 +            AppCtrlPanRight = 0x0237,
   2.389 +            AppCtrlPan = 0x0238,
   2.390 +            AppCtrlNewWindow = 0x0239,
   2.391 +            AppCtrlTileHorizontally = 0x023A,
   2.392 +            AppCtrlTileVertically = 0x023B,
   2.393 +            AppCtrlFormat = 0x023C,
   2.394 +            AppCtrlEdit = 0x023D,
   2.395 +        }
   2.396 +    }
   2.397 +}
   2.398 \ No newline at end of file
     3.1 --- a/HumanInterfaceDevice.cs	Sat Dec 06 13:14:16 2014 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,394 +0,0 @@
     3.4 -//
     3.5 -//
     3.6 -//
     3.7 -
     3.8 -namespace Hid
     3.9 -{
    3.10 -    /// <summary>
    3.11 -    /// From USB HID usage tables.
    3.12 -    /// http://www.usb.org/developers/hidpage#HID_Usage
    3.13 -    /// http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
    3.14 -    /// </summary>
    3.15 -    public enum UsagePage : ushort
    3.16 -    {
    3.17 -        Undefined = 0,
    3.18 -        GenericDesktopControl,
    3.19 -        SimulationControl,
    3.20 -        VirtualRealityControl,
    3.21 -        SportControl,
    3.22 -        GameControl,
    3.23 -        GenericDeviceControl,
    3.24 -        Keyboard,
    3.25 -        LightEmittingDiode,
    3.26 -        Button,
    3.27 -        Ordinal,
    3.28 -        Telephony,
    3.29 -        Consumer,
    3.30 -        Digitiser,
    3.31 -        PhysicalInterfaceDevice = 0x0f,
    3.32 -        Unicode = 0x10,
    3.33 -        AlphaNumericDisplay = 0x14,
    3.34 -        MedicalInstruments = 0x40,
    3.35 -        MonitorPage0 = 0x80,
    3.36 -        MonitorPage1,
    3.37 -        MonitorPage2,
    3.38 -        MonitorPage3,
    3.39 -        PowerPage0,
    3.40 -        PowerPage1,
    3.41 -        PowerPage2,
    3.42 -        PowerPage3,
    3.43 -        BarCodeScanner = 0x8c,
    3.44 -        Scale,
    3.45 -        MagneticStripeReader,
    3.46 -        ReservedPointOfSale,
    3.47 -        CameraControl,
    3.48 -        Arcade,
    3.49 -        // http://msdn.microsoft.com/en-us/library/windows/desktop/bb417079.aspx
    3.50 -        MceRemote = 0xffbc,
    3.51 -        TerraTecRemote = 0xffcc
    3.52 -    }
    3.53 -
    3.54 -    public enum UsageIdGenericDesktop : ushort
    3.55 -    {      
    3.56 -        Pointer = 0x01,
    3.57 -        Mouse = 0x02,
    3.58 -        Joystick = 0x04,
    3.59 -        GamePad = 0x05,
    3.60 -        Keyboard = 0x06,
    3.61 -        KeyPad = 0x07,
    3.62 -        MultiAxisController = 0x08,
    3.63 -        TabletPCSystemControls = 0x09,
    3.64 -        SystemControl = 0x80
    3.65 -    }
    3.66 -
    3.67 -    public enum UsageIdConsumer : ushort
    3.68 -    {
    3.69 -        ConsumerControl = 0x01,
    3.70 -        NumericKeyPad = 0x02,
    3.71 -        ProgrammableButtons = 0x03,
    3.72 -        Microphone = 0x04,
    3.73 -        Headphone = 0x05,
    3.74 -        GraphicEqualizer = 0x06,
    3.75 -        Selection = 0x80,
    3.76 -    }
    3.77 -
    3.78 -    
    3.79 -    public enum UsageIdMce: ushort
    3.80 -    {
    3.81 -        MceRemote = 0x88        
    3.82 -    }
    3.83 -
    3.84 -
    3.85 -
    3.86 -    namespace UsageTables
    3.87 -    {
    3.88 -        /// <summary>
    3.89 -        ///
    3.90 -        /// </summary>
    3.91 -        public enum MceButton: ushort
    3.92 -        {
    3.93 -            /// <summary>
    3.94 -            /// Not defined by the Microsoft specs.
    3.95 -            /// </summary>
    3.96 -            Null                    =   0x00,
    3.97 -            GreenStart              =   0x0D,
    3.98 -            ClosedCaptioning        =   0x2B,
    3.99 -            Teletext                =   0x5A,
   3.100 -            TeletextRed             =   0x5B,
   3.101 -            TeletextGreen           =   0x5C,
   3.102 -            TeletextYellow          =   0x5D,
   3.103 -            TeletextBlue            =   0x5E,
   3.104 -            LiveTv                  =   0x25,
   3.105 -            Music                   =   0x47,
   3.106 -            RecordedTv              =   0x48,
   3.107 -            Pictures                =   0x49,
   3.108 -            Videos                  =   0x4A,
   3.109 -            FmRadio                 =   0x50,
   3.110 -            Extras                  =   0x3C,
   3.111 -            ExtrasApp               =   0x3D,
   3.112 -            DvdMenu                 =   0x24,
   3.113 -            DvdAngle                =   0x4B,
   3.114 -            DvdAudio                =   0x4C,
   3.115 -            DvdSubtitle             =   0x4D,
   3.116 -            /// <summary>
   3.117 -            /// First press action: Ejects a DVD drive.
   3.118 -            /// <para />
   3.119 -            /// Second press action: Repeats first press action.
   3.120 -            /// <para />
   3.121 -            /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
   3.122 -            /// </summary>
   3.123 -            Eject                   =   0x28,
   3.124 -            DvdTopMenu              =   0x43,
   3.125 -            /// <summary>
   3.126 -            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   3.127 -            /// Collection (page 0xFFBC, usage 0x88).
   3.128 -            /// <para />
   3.129 -            /// Second press action: Repeats message.
   3.130 -            /// <para />
   3.131 -            /// Auto-repeat: No
   3.132 -            /// <para />
   3.133 -            /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
   3.134 -            /// <para />
   3.135 -            /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
   3.136 -            /// </summary>
   3.137 -            Ext0                    =   0x32,
   3.138 -            /// <summary>
   3.139 -            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   3.140 -            /// Collection (page 0xFFBC, usage 0x88).
   3.141 -            /// <para />
   3.142 -            /// Second press action: Repeats message.
   3.143 -            /// <para />
   3.144 -            /// Auto-repeat: No
   3.145 -            /// <para />
   3.146 -            /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
   3.147 -            /// <para />
   3.148 -            /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
   3.149 -            /// </summary>
   3.150 -            Ext1                    =   0x33,
   3.151 -            /// <summary>
   3.152 -            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   3.153 -            /// Collection (page 0xFFBC, usage 0x88).
   3.154 -            /// <para />
   3.155 -            /// Second press action: Repeats message.
   3.156 -            /// <para />
   3.157 -            /// Auto-repeat: No
   3.158 -            /// <para />
   3.159 -            /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
   3.160 -            /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
   3.161 -            /// </summary>
   3.162 -            Ext2                    =   0x34,
   3.163 -            /// <summary>
   3.164 -            /// First press action: Generates EXTn HID message in the Media Center Vendor Specific
   3.165 -            /// Collection (page 0xFFBC, usage 0x88).
   3.166 -            /// <para />
   3.167 -            /// Second press action: Repeats message.
   3.168 -            /// <para />
   3.169 -            /// Auto-repeat: No
   3.170 -            /// <para />
   3.171 -            /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
   3.172 -            /// </summary>
   3.173 -            Ext3                    =   0x35,
   3.174 -            Ext4                    =   0x36,
   3.175 -            Ext5                    =   0x37,
   3.176 -            Ext6                    =   0x38,
   3.177 -            Ext7                    =   0x39,
   3.178 -            Ext8                    =   0x3A,
   3.179 -            Ext9                    =   0x80,
   3.180 -            Ext10                   =   0x81,
   3.181 -            Ext11                   =   0x6F,
   3.182 -            Zoom                    =   0x27,
   3.183 -            ChannelInput            =   0x42,
   3.184 -            SubAudio                =   0x2D,
   3.185 -            Channel10               =   0x3E,
   3.186 -            Channel11               =   0x3F,
   3.187 -            Channel12               =   0x40,
   3.188 -            /// <summary>
   3.189 -            /// First press action: Generates OEM2 HID message in the Media Center Vendor Specific
   3.190 -            /// Collection. This button is intended to control the front panel display of home entertainment
   3.191 -            /// computers. When this button is pressed, the display could be turned on or off, or the display
   3.192 -            /// mode could change.
   3.193 -            /// <para />
   3.194 -            /// Second press action: Repeats message.
   3.195 -            /// <para />
   3.196 -            /// Auto-repeat: No
   3.197 -            /// <para />
   3.198 -            /// Notably issued by XBOX360 remote as defined in irplus - Remote Control - Android application.
   3.199 -            /// </summary>
   3.200 -            Display                 =   0x4F,
   3.201 -            /// <summary>
   3.202 -            /// First press action: To be determined.
   3.203 -            /// <para />
   3.204 -            /// Second press action: Repeats message.
   3.205 -            /// <para />
   3.206 -            /// Auto-repeat: No
   3.207 -            /// </summary>
   3.208 -            Kiosk                   =   0x6A,
   3.209 -            NetworkSelection        =   0x2C,
   3.210 -            BlueRayTool             =   0x78,
   3.211 -            ChannelInfo             =   0x41,
   3.212 -            VideoSelection          =   0x61
   3.213 -        }
   3.214 -
   3.215 -        /// <summary>
   3.216 -        /// Those codes come from experimenting with HP remotes.
   3.217 -        /// </summary>
   3.218 -        public enum HpMceButton: ushort
   3.219 -        {
   3.220 -            /// <summary>
   3.221 -            /// Displays visual imagery that is synchronized to the sound of your music tracks.
   3.222 -            /// <para />
   3.223 -            /// Second press action: Repeats message.
   3.224 -            /// <para />
   3.225 -            /// Auto-repeat: No
   3.226 -            /// <para />
   3.227 -            /// Notably sent by the 'Visualization' button of HP Windows Media Center Remote (TSGH-IR08).
   3.228 -            /// <para />
   3.229 -            /// According to HP specs it displays visual imagery that is synchronized to the sound of your music tracks.
   3.230 -            /// </summary>
   3.231 -            Visualization = MceButton.Ext0,
   3.232 -            /// <summary>
   3.233 -            /// Plays a slide show of all the pictures on your hard disk drive.
   3.234 -            /// <para />
   3.235 -            /// Second press action: Repeats message.
   3.236 -            /// <para />
   3.237 -            /// Auto-repeat: No
   3.238 -            /// <para />
   3.239 -            /// Notably sent by the 'Slide Show' button of HP Windows Media Center Remote (TSGH-IR08).
   3.240 -            /// <para />
   3.241 -            /// According to HP specs it plays a slide show of all the pictures on your hard disk drive.
   3.242 -            /// </summary>
   3.243 -            SlideShow = MceButton.Ext1,
   3.244 -            /// <summary>
   3.245 -            /// Eject optical drive.
   3.246 -            /// <para />
   3.247 -            /// Second press action: Repeats message.
   3.248 -            /// <para />
   3.249 -            /// Auto-repeat: No
   3.250 -            /// <para />
   3.251 -            /// Notably sent by the 'Eject' button of HP Windows Media Center Remote (TSGH-IR08).
   3.252 -            /// Also interpreted as 'Eject' action by SoundGraph iMON Manager in MCE mode (OrigenAE VF310).
   3.253 -            /// </summary>
   3.254 -            Eject = MceButton.Ext2,
   3.255 -            /// <summary>
   3.256 -            /// Not sure what this should do.
   3.257 -            /// <para />
   3.258 -            /// Second press action: Repeats message.
   3.259 -            /// <para />
   3.260 -            /// Auto-repeat: No
   3.261 -            /// <para />
   3.262 -            /// Notably sent by the 'Input selection' button of HP Windows Media Center Remote (TSGH-IR08).
   3.263 -            /// </summary>
   3.264 -            InputSelection = MceButton.Ext3,
   3.265 -        }
   3.266 -
   3.267 -        /// <summary>
   3.268 -        /// Usage Table for Consumer Controls
   3.269 -        /// 0x0C 0X01
   3.270 -        /// </summary>
   3.271 -        public enum ConsumerControl: ushort
   3.272 -        {
   3.273 -            Null = 0x0000,           
   3.274 -            //           
   3.275 -            Channel = 0x0086,
   3.276 -            MediaSelection = 0x0087,
   3.277 -            MediaSelectComputer = 0x0088,
   3.278 -            MediaSelectTV = 0x0089,
   3.279 -            MediaSelectWWW = 0x008A,
   3.280 -            MediaSelectDVD = 0x008B,
   3.281 -            MediaSelectTelephone = 0x008C,
   3.282 -            MediaSelectProgramGuide = 0x008D,
   3.283 -            MediaSelectVideoPhone = 0x008E,
   3.284 -            MediaSelectGames = 0x008F,
   3.285 -            MediaSelectMessages = 0x0090,
   3.286 -            MediaSelectCD = 0x0091,
   3.287 -            MediaSelectVCR = 0x0092,
   3.288 -            MediaSelectTuner = 0x0093,
   3.289 -            Quit = 0x0094,
   3.290 -            Help = 0x0095,
   3.291 -            MediaSelectTape = 0x0096,
   3.292 -            MediaSelectCable = 0x0097,
   3.293 -            MediaSelectSatellite = 0x0098,
   3.294 -            MediaSelectSecurity = 0x0099,
   3.295 -            MediaSelectHome = 0x009A,
   3.296 -            MediaSelectCall = 0x009B,
   3.297 -            ChannelIncrement = 0x009C,
   3.298 -            ChannelDecrement = 0x009D,
   3.299 -            MediaSelectSAP = 0x009E,
   3.300 -            //
   3.301 -            Play = 0x00B0,
   3.302 -            Pause = 0x00B1,
   3.303 -            Record = 0x00B2,
   3.304 -            FastForward = 0x00B3,
   3.305 -            Rewind = 0x00B4,
   3.306 -            ScanNextTrack = 0x00B5,
   3.307 -            ScanPreviousTrack = 0x00B6,
   3.308 -            Stop = 0x00B7,
   3.309 -            Eject = 0x00B8,
   3.310 -            RandomPlay = 0x00B9,
   3.311 -            SelectDisc = 0x00BA,
   3.312 -            EnterDisc = 0x00BB,
   3.313 -            Repeat = 0x00BC,
   3.314 -            Tracking = 0x00BD,
   3.315 -            TrackNormal = 0x00BE,
   3.316 -            SlowTracking = 0x00BF,
   3.317 -            FrameForward = 0x00C0,
   3.318 -            FrameBack = 0x00C1,
   3.319 -            Mark = 0x00C2,
   3.320 -            ClearMark = 0x00C3,
   3.321 -            RepeatFromMark = 0x00C4,
   3.322 -            ReturnToMark = 0x00C5,
   3.323 -            SearchMarkForward = 0x00C6,
   3.324 -            SearchMarkBackwards = 0x00C7,
   3.325 -            CounterReset = 0x00C8,
   3.326 -            ShowCounter = 0x00C9,
   3.327 -            TrackingIncrement = 0x00CA,
   3.328 -            TrackingDecrement = 0x00CB,
   3.329 -            StopEject = 0x00CC,
   3.330 -            PlayPause = 0x00CD,
   3.331 -            PlaySkip = 0x00CE,
   3.332 -
   3.333 -            /// <summary>
   3.334 -            /// Audio controls
   3.335 -            /// </summary>
   3.336 -            Volume = 0x00E0,
   3.337 -            Balance = 0x00E1,
   3.338 -            Mute = 0x00E2,
   3.339 -            Bass = 0x00E3,
   3.340 -            Treble = 0x00E4,
   3.341 -            BassBoost = 0x00E5,
   3.342 -            SurroundMode = 0x00E6,
   3.343 -            Loudness = 0x00E7,
   3.344 -            MPX = 0x00E8,
   3.345 -            VolumeIncrement = 0x00E9,
   3.346 -            VolumeDecrement = 0x00EA,
   3.347 -
   3.348 -            //Generic GUI Application Controls
   3.349 -            GenericGUIApplicationControls = 0x0200,
   3.350 -            AppCtrlNew = 0x0201,
   3.351 -            AppCtrlOpen = 0x0202,
   3.352 -            AppCtrlClose = 0x0203,
   3.353 -            AppCtrlExit = 0x0204,
   3.354 -            AppCtrlMaximize = 0x0205,
   3.355 -            AppCtrlMinimize = 0x0206,
   3.356 -            AppCtrlSave = 0x0207,
   3.357 -            AppCtrlPrint = 0x0208,
   3.358 -            AppCtrlProperties = 0x0209,
   3.359 -            AppCtrlUndo = 0x021A,
   3.360 -            AppCtrlCopy = 0x021B,
   3.361 -            AppCtrlCut = 0x021C,
   3.362 -            AppCtrlPaste = 0x021D,
   3.363 -            AppCtrlSelectAll = 0x021E,
   3.364 -            AppCtrlFind = 0x021F,
   3.365 -            AppCtrlFindAndReplace = 0x0220,
   3.366 -            AppCtrlSearch = 0x0221,
   3.367 -            AppCtrlGoTo = 0x0222,
   3.368 -            AppCtrlHome = 0x0223,
   3.369 -            AppCtrlBack = 0x0224,
   3.370 -            AppCtrlForward = 0x0225,
   3.371 -            AppCtrlStop = 0x0226,
   3.372 -            AppCtrlRefresh = 0x0227,
   3.373 -            AppCtrlPreviousLink = 0x0228,
   3.374 -            AppCtrlNextLink = 0x0229,
   3.375 -            AppCtrlBookmarks = 0x022A,
   3.376 -            AppCtrlHistory = 0x022B,
   3.377 -            AppCtrlSubscriptions = 0x022C,
   3.378 -            AppCtrlZoomIn = 0x022D,
   3.379 -            AppCtrlZoomOut = 0x022E,
   3.380 -            AppCtrlZoom = 0x022F,
   3.381 -            AppCtrlFullScreenView = 0x0230,
   3.382 -            AppCtrlNormalView = 0x0231,
   3.383 -            AppCtrlViewToggle = 0x0232,
   3.384 -            AppCtrlScrollUp = 0x0233,
   3.385 -            AppCtrlScrollDown = 0x0234,
   3.386 -            AppCtrlScroll = 0x0235,
   3.387 -            AppCtrlPanLeft = 0x0236,
   3.388 -            AppCtrlPanRight = 0x0237,
   3.389 -            AppCtrlPan = 0x0238,
   3.390 -            AppCtrlNewWindow = 0x0239,
   3.391 -            AppCtrlTileHorizontally = 0x023A,
   3.392 -            AppCtrlTileVertically = 0x023B,
   3.393 -            AppCtrlFormat = 0x023C,
   3.394 -            AppCtrlEdit = 0x023D,
   3.395 -        }
   3.396 -    }
   3.397 -}
   3.398 \ No newline at end of file
     4.1 --- a/RemoteControlDevice.cs	Sat Dec 06 13:14:16 2014 +0100
     4.2 +++ b/RemoteControlDevice.cs	Sat Dec 06 21:52:45 2014 +0100
     4.3 @@ -13,93 +13,93 @@
     4.4  namespace Devices.RemoteControl
     4.5  {
     4.6  
     4.7 -	public enum InputDevice
     4.8 -	{
     4.9 -		Key,
    4.10 -		Mouse,
    4.11 -		OEM
    4.12 -	}
    4.13 +    public enum InputDevice
    4.14 +    {
    4.15 +        Key,
    4.16 +        Mouse,
    4.17 +        OEM
    4.18 +    }
    4.19  
    4.20  
    4.21 -	public enum RemoteControlButton
    4.22 -	{
    4.23 -		Clear,
    4.24 -		Down,
    4.25 -		Left,
    4.26 -		Digit0,
    4.27 -		Digit1,
    4.28 -		Digit2,
    4.29 -		Digit3,
    4.30 -		Digit4,
    4.31 -		Digit5,
    4.32 -		Digit6,
    4.33 -		Digit7,
    4.34 -		Digit8,
    4.35 -		Digit9,
    4.36 -		Enter,
    4.37 -		Right,
    4.38 -		Up,
    4.39 +    public enum RemoteControlButton
    4.40 +    {
    4.41 +        Clear,
    4.42 +        Down,
    4.43 +        Left,
    4.44 +        Digit0,
    4.45 +        Digit1,
    4.46 +        Digit2,
    4.47 +        Digit3,
    4.48 +        Digit4,
    4.49 +        Digit5,
    4.50 +        Digit6,
    4.51 +        Digit7,
    4.52 +        Digit8,
    4.53 +        Digit9,
    4.54 +        Enter,
    4.55 +        Right,
    4.56 +        Up,
    4.57  
    4.58 -		Back,
    4.59 -		ChannelDown,
    4.60 -		ChannelUp,
    4.61 -		FastForward,
    4.62 -		VolumeMute,
    4.63 -		Pause,
    4.64 -		Play,
    4.65 +        Back,
    4.66 +        ChannelDown,
    4.67 +        ChannelUp,
    4.68 +        FastForward,
    4.69 +        VolumeMute,
    4.70 +        Pause,
    4.71 +        Play,
    4.72          PlayPause,
    4.73 -		Record,
    4.74 -		PreviousTrack,
    4.75 -		Rewind,
    4.76 -		NextTrack,
    4.77 -		Stop,
    4.78 -		VolumeDown,
    4.79 -		VolumeUp,
    4.80 +        Record,
    4.81 +        PreviousTrack,
    4.82 +        Rewind,
    4.83 +        NextTrack,
    4.84 +        Stop,
    4.85 +        VolumeDown,
    4.86 +        VolumeUp,
    4.87  
    4.88 -		RecordedTV,
    4.89 -		Guide,
    4.90 -		LiveTV,
    4.91 -		MoreInfo,
    4.92 +        RecordedTV,
    4.93 +        Guide,
    4.94 +        LiveTV,
    4.95 +        MoreInfo,
    4.96          Print,
    4.97 -		DVDMenu,
    4.98 -		DVDAngle,
    4.99 -		DVDAudio,
   4.100 -		DVDSubtitle,
   4.101 -		MyMusic,
   4.102 -		MyPictures,
   4.103 -		MyVideos,
   4.104 -		MyTV,
   4.105 -		OEM1,
   4.106 -		OEM2,
   4.107 -		StandBy,
   4.108 -		TVJump,
   4.109 +        DVDMenu,
   4.110 +        DVDAngle,
   4.111 +        DVDAudio,
   4.112 +        DVDSubtitle,
   4.113 +        MyMusic,
   4.114 +        MyPictures,
   4.115 +        MyVideos,
   4.116 +        MyTV,
   4.117 +        OEM1,
   4.118 +        OEM2,
   4.119 +        StandBy,
   4.120 +        TVJump,
   4.121  
   4.122 -		Unknown
   4.123 -	}
   4.124 +        Unknown
   4.125 +    }
   4.126  
   4.127  
   4.128 -	#region RemoteControlEventArgs
   4.129 +    #region RemoteControlEventArgs
   4.130  
   4.131 -	public class RemoteControlEventArgs : EventArgs
   4.132 -	{
   4.133 +    public class RemoteControlEventArgs : EventArgs
   4.134 +    {
   4.135          RemoteControlButton _rcb;
   4.136 -		InputDevice _device;
   4.137 +        InputDevice _device;
   4.138          MceButton iMceButton;
   4.139          ConsumerControl iConsumerControl;
   4.140  
   4.141          public RemoteControlEventArgs(RemoteControlButton rcb, InputDevice device)
   4.142 -		{
   4.143 +        {
   4.144              SetNullButtons();
   4.145              //
   4.146 -			_rcb = rcb;
   4.147 -			_device = device;            
   4.148 -		}
   4.149 +            _rcb = rcb;
   4.150 +            _device = device;
   4.151 +        }
   4.152  
   4.153          public RemoteControlEventArgs(ConsumerControl aConsumerControl, InputDevice device)
   4.154          {
   4.155              SetNullButtons();
   4.156              //
   4.157 -            iConsumerControl = aConsumerControl;            
   4.158 +            iConsumerControl = aConsumerControl;
   4.159              _device = device;
   4.160          }
   4.161  
   4.162 @@ -108,7 +108,7 @@
   4.163          {
   4.164              SetNullButtons();
   4.165              //
   4.166 -            iMceButton = mce;            
   4.167 +            iMceButton = mce;
   4.168              _device = device;
   4.169          }
   4.170  
   4.171 @@ -119,18 +119,18 @@
   4.172              _rcb = RemoteControlButton.Unknown;
   4.173          }
   4.174  
   4.175 -		public RemoteControlEventArgs()
   4.176 -		{
   4.177 +        public RemoteControlEventArgs()
   4.178 +        {
   4.179              iMceButton = MceButton.Null;
   4.180 -			_rcb = RemoteControlButton.Unknown;
   4.181 -			_device = InputDevice.Key;
   4.182 -		}
   4.183 +            _rcb = RemoteControlButton.Unknown;
   4.184 +            _device = InputDevice.Key;
   4.185 +        }
   4.186  
   4.187 -		public RemoteControlButton Button
   4.188 -		{
   4.189 -			get { return _rcb;  }
   4.190 -			set { _rcb = value; }
   4.191 -		}
   4.192 +        public RemoteControlButton Button
   4.193 +        {
   4.194 +            get { return _rcb; }
   4.195 +            set { _rcb = value; }
   4.196 +        }
   4.197  
   4.198          public MceButton MceButton
   4.199          {
   4.200 @@ -144,20 +144,20 @@
   4.201              set { iConsumerControl = value; }
   4.202          }
   4.203  
   4.204 -		public InputDevice Device
   4.205 -		{
   4.206 -			get { return _device;  }
   4.207 -			set { _device = value; }
   4.208 -		}
   4.209 -	}
   4.210 +        public InputDevice Device
   4.211 +        {
   4.212 +            get { return _device; }
   4.213 +            set { _device = value; }
   4.214 +        }
   4.215 +    }
   4.216  
   4.217 -	#endregion RemoteControlEventArgs
   4.218 +    #endregion RemoteControlEventArgs
   4.219  
   4.220  
   4.221 -	public sealed class RemoteControlDevice
   4.222 -	{
   4.223 -		public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
   4.224 -		public event RemoteControlDeviceEventHandler ButtonPressed;
   4.225 +    public sealed class RemoteControlDevice
   4.226 +    {
   4.227 +        public delegate bool RemoteControlDeviceEventHandler(object sender, RemoteControlEventArgs e);
   4.228 +        public event RemoteControlDeviceEventHandler ButtonPressed;
   4.229  
   4.230          /// <summary>
   4.231          /// Return true if the usage was processed.
   4.232 @@ -165,22 +165,22 @@
   4.233          /// <param name="aUsage"></param>
   4.234          /// <returns></returns>
   4.235          public delegate bool HidUsageHandler(ushort aUsage);
   4.236 -        
   4.237  
   4.238 -		//-------------------------------------------------------------
   4.239 -		// constructors
   4.240 -		//-------------------------------------------------------------
   4.241  
   4.242 -		public RemoteControlDevice(IntPtr aHWND)
   4.243 -		{
   4.244 -			// Register the input device to receive the commands from the
   4.245 -			// remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
   4.246 -			// for the vendor defined usage page.
   4.247 +        //-------------------------------------------------------------
   4.248 +        // constructors
   4.249 +        //-------------------------------------------------------------
   4.250  
   4.251 -			RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[5];
   4.252 +        public RemoteControlDevice(IntPtr aHWND)
   4.253 +        {
   4.254 +            // Register the input device to receive the commands from the
   4.255 +            // remote device. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/remote_control.asp
   4.256 +            // for the vendor defined usage page.
   4.257 +
   4.258 +            RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[4];
   4.259  
   4.260              int i = 0;
   4.261 -			rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
   4.262 +            rid[i].usUsagePage = (ushort)Hid.UsagePage.MceRemote;
   4.263              rid[i].usUsage = (ushort)Hid.UsageIdMce.MceRemote;
   4.264              rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   4.265              rid[i].hwndTarget = aHWND;
   4.266 @@ -203,11 +203,11 @@
   4.267              rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   4.268              rid[i].hwndTarget = aHWND;
   4.269  
   4.270 -            i++;
   4.271 -            rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
   4.272 -            rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
   4.273 -            rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   4.274 -            rid[i].hwndTarget = aHWND;
   4.275 +            //i++;
   4.276 +            //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
   4.277 +            //rid[i].usUsage = (ushort)Hid.UsageIdGenericDesktop.Keyboard;
   4.278 +            //rid[i].dwFlags = Const.RIDEV_EXINPUTSINK;
   4.279 +            //rid[i].hwndTarget = aHWND;
   4.280  
   4.281              //i++;
   4.282              //rid[i].usUsagePage = (ushort)Hid.UsagePage.GenericDesktopControl;
   4.283 @@ -216,55 +216,55 @@
   4.284              //rid[i].hwndTarget = aHWND;
   4.285  
   4.286  
   4.287 -			if (!Function.RegisterRawInputDevices(rid,(uint) rid.Length,(uint) Marshal.SizeOf(rid[0])))
   4.288 -			{
   4.289 +            if (!Function.RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])))
   4.290 +            {
   4.291                  throw new ApplicationException("Failed to register raw input devices: " + Marshal.GetLastWin32Error().ToString());
   4.292 -			}
   4.293 -		}
   4.294 +            }
   4.295 +        }
   4.296  
   4.297  
   4.298 -		//-------------------------------------------------------------
   4.299 -		// methods
   4.300 -		//-------------------------------------------------------------
   4.301 +        //-------------------------------------------------------------
   4.302 +        // methods
   4.303 +        //-------------------------------------------------------------
   4.304  
   4.305 -		public void ProcessMessage(Message message)
   4.306 -		{
   4.307 -			switch (message.Msg)
   4.308 -			{
   4.309 -				case Const.WM_KEYDOWN:
   4.310 +        public void ProcessMessage(Message message)
   4.311 +        {
   4.312 +            switch (message.Msg)
   4.313 +            {
   4.314 +                case Const.WM_KEYDOWN:
   4.315                      ProcessKeyDown(message.WParam);
   4.316 -					break;
   4.317 +                    break;
   4.318                  case Const.WM_INPUT:
   4.319                      //Returning zero means we processed that message.
   4.320                      message.Result = new IntPtr(0);
   4.321 -					ProcessInputCommand(ref message);
   4.322 -					break;
   4.323 -			}
   4.324 +                    ProcessInputCommand(ref message);
   4.325 +                    break;
   4.326 +            }
   4.327  
   4.328 -		}
   4.329 +        }
   4.330  
   4.331  
   4.332 -		//-------------------------------------------------------------
   4.333 -		// methods (helpers)
   4.334 -		//-------------------------------------------------------------
   4.335 +        //-------------------------------------------------------------
   4.336 +        // methods (helpers)
   4.337 +        //-------------------------------------------------------------
   4.338  
   4.339 -		private void ProcessKeyDown(IntPtr wParam)
   4.340 -		{
   4.341 -			RemoteControlButton rcb = RemoteControlButton.Unknown;
   4.342 +        private void ProcessKeyDown(IntPtr wParam)
   4.343 +        {
   4.344 +            RemoteControlButton rcb = RemoteControlButton.Unknown;
   4.345  
   4.346              switch (wParam.ToInt32())
   4.347 -			{
   4.348 -				case (int) Keys.Escape:
   4.349 -					rcb = RemoteControlButton.Clear;
   4.350 +            {
   4.351 +                case (int)Keys.Escape:
   4.352 +                    rcb = RemoteControlButton.Clear;
   4.353                      break;
   4.354                  case (int)Keys.Up:
   4.355                      rcb = RemoteControlButton.Up;
   4.356                      break;
   4.357 -				case (int) Keys.Down:
   4.358 -					rcb = RemoteControlButton.Down;
   4.359 -					break;
   4.360 -				case (int) Keys.Left:
   4.361 -					rcb = RemoteControlButton.Left;
   4.362 +                case (int)Keys.Down:
   4.363 +                    rcb = RemoteControlButton.Down;
   4.364 +                    break;
   4.365 +                case (int)Keys.Left:
   4.366 +                    rcb = RemoteControlButton.Left;
   4.367                      break;
   4.368                  case (int)Keys.Right:
   4.369                      rcb = RemoteControlButton.Right;
   4.370 @@ -272,44 +272,44 @@
   4.371                  case (int)Keys.Enter:
   4.372                      rcb = RemoteControlButton.Enter;
   4.373                      break;
   4.374 -				case (int) Keys.D0:
   4.375 -					rcb = RemoteControlButton.Digit0;
   4.376 -					break;
   4.377 -				case (int) Keys.D1:
   4.378 -					rcb = RemoteControlButton.Digit1;
   4.379 -					break;
   4.380 -				case (int) Keys.D2:
   4.381 -					rcb = RemoteControlButton.Digit2;
   4.382 -					break;
   4.383 -				case (int) Keys.D3:
   4.384 -					rcb = RemoteControlButton.Digit3;
   4.385 -					break;
   4.386 -				case (int) Keys.D4:
   4.387 -					rcb = RemoteControlButton.Digit4;
   4.388 -					break;
   4.389 -				case (int) Keys.D5:
   4.390 -					rcb = RemoteControlButton.Digit5;
   4.391 -					break;
   4.392 -				case (int) Keys.D6:
   4.393 -					rcb = RemoteControlButton.Digit6;
   4.394 -					break;
   4.395 -				case (int) Keys.D7:
   4.396 -					rcb = RemoteControlButton.Digit7;
   4.397 -					break;
   4.398 -				case (int) Keys.D8:
   4.399 -					rcb = RemoteControlButton.Digit8;
   4.400 -					break;
   4.401 -				case (int) Keys.D9:
   4.402 -					rcb = RemoteControlButton.Digit9;
   4.403 +                case (int)Keys.D0:
   4.404 +                    rcb = RemoteControlButton.Digit0;
   4.405                      break;
   4.406 -			}
   4.407 +                case (int)Keys.D1:
   4.408 +                    rcb = RemoteControlButton.Digit1;
   4.409 +                    break;
   4.410 +                case (int)Keys.D2:
   4.411 +                    rcb = RemoteControlButton.Digit2;
   4.412 +                    break;
   4.413 +                case (int)Keys.D3:
   4.414 +                    rcb = RemoteControlButton.Digit3;
   4.415 +                    break;
   4.416 +                case (int)Keys.D4:
   4.417 +                    rcb = RemoteControlButton.Digit4;
   4.418 +                    break;
   4.419 +                case (int)Keys.D5:
   4.420 +                    rcb = RemoteControlButton.Digit5;
   4.421 +                    break;
   4.422 +                case (int)Keys.D6:
   4.423 +                    rcb = RemoteControlButton.Digit6;
   4.424 +                    break;
   4.425 +                case (int)Keys.D7:
   4.426 +                    rcb = RemoteControlButton.Digit7;
   4.427 +                    break;
   4.428 +                case (int)Keys.D8:
   4.429 +                    rcb = RemoteControlButton.Digit8;
   4.430 +                    break;
   4.431 +                case (int)Keys.D9:
   4.432 +                    rcb = RemoteControlButton.Digit9;
   4.433 +                    break;
   4.434 +            }
   4.435  
   4.436              if (this.ButtonPressed != null && rcb != RemoteControlButton.Unknown)
   4.437              {
   4.438                  Debug.WriteLine("KeyDown: " + rcb.ToString());
   4.439                  this.ButtonPressed(this, new RemoteControlEventArgs(rcb, InputDevice.Key));
   4.440              }
   4.441 -		}
   4.442 +        }
   4.443  
   4.444  
   4.445          /// <summary>
   4.446 @@ -356,7 +356,7 @@
   4.447              {
   4.448                  if (this.ButtonPressed != null)
   4.449                  {
   4.450 -                    return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));                    
   4.451 +                    return this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)aUsage, InputDevice.OEM));
   4.452                  }
   4.453                  return false;
   4.454              }
   4.455 @@ -368,156 +368,45 @@
   4.456          }
   4.457  
   4.458  
   4.459 -		private void ProcessInputCommand(ref Message message)
   4.460 -		{
   4.461 +        private void ProcessInputCommand(ref Message message)
   4.462 +        {
   4.463              //We received a WM_INPUT message
   4.464              Debug.WriteLine("================WM_INPUT================");
   4.465  
   4.466 -            //Check if we received this message while in background or foreground
   4.467 -            if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUT)
   4.468 +            Hid.HidEvent hidEvent = new Hid.HidEvent(message);
   4.469 +            hidEvent.DebugWrite();
   4.470 +
   4.471 +            if (!hidEvent.IsValid || !hidEvent.IsGeneric)
   4.472              {
   4.473 -                Debug.WriteLine("================FOREGROUND");
   4.474 -            }
   4.475 -            else if (Macro.GET_RAWINPUT_CODE_WPARAM(message.WParam) == Const.RIM_INPUTSINK)
   4.476 -            {
   4.477 -                Debug.WriteLine("================BACKGROUND");
   4.478 +                Debug.WriteLine("Skipping HID message.");
   4.479 +                return;
   4.480              }
   4.481  
   4.482 -            //Declare some pointers
   4.483 -            IntPtr rawInputBuffer = IntPtr.Zero;
   4.484 -            //My understanding is that this is basically our HID descriptor 
   4.485 -            IntPtr preParsedData = IntPtr.Zero;
   4.486  
   4.487 -            try
   4.488 +            HidUsageHandler usagePageHandler = null;
   4.489 +
   4.490 +            //Check if this an MCE remote HID message
   4.491 +            if (hidEvent.UsagePage == (ushort)Hid.UsagePage.MceRemote && hidEvent.UsageCollection == (ushort)Hid.UsageIdMce.MceRemote)
   4.492              {
   4.493 -                //Fetch raw input
   4.494 -                RAWINPUT rawInput = new RAWINPUT();
   4.495 -                if (!RawInput.GetRawInputData(message.LParam, ref rawInput, ref rawInputBuffer))
   4.496 -                {
   4.497 -                    return;
   4.498 -                }
   4.499 +                usagePageHandler = HidMceRemoteHandler;
   4.500 +            }
   4.501 +            //Check if this is a consumer control HID message
   4.502 +            else if (hidEvent.UsagePage == (ushort)Hid.UsagePage.Consumer && hidEvent.UsageCollection == (ushort)Hid.UsageIdConsumer.ConsumerControl)
   4.503 +            {
   4.504 +                usagePageHandler = HidConsumerDeviceHandler;
   4.505 +            }
   4.506 +            //Unknown HID message
   4.507 +            else
   4.508 +            {
   4.509 +                Debug.WriteLine("Unknown HID message.");
   4.510 +                return;
   4.511 +            }
   4.512  
   4.513 +            foreach (ushort usage in hidEvent.Usages)
   4.514 +            {
   4.515 +                usagePageHandler(usage);
   4.516 +            }
   4.517 +        }
   4.518 +    }
   4.519 +}
   4.520  
   4.521 -
   4.522 -                //Fetch device info
   4.523 -                RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
   4.524 -                if (!RawInput.GetDeviceInfo(rawInput.header.hDevice, ref deviceInfo))
   4.525 -                {
   4.526 -                    return;
   4.527 -                }
   4.528 -
   4.529 -                //Get various information about this HID device
   4.530 -                Hid.HidDevice device = new Hid.HidDevice(rawInput.header.hDevice);
   4.531 -                device.DebugWrite();
   4.532 -                
   4.533 -               
   4.534 -
   4.535 -
   4.536 -                if (rawInput.header.dwType == Const.RIM_TYPEHID)  //Check that our raw input is HID                        
   4.537 -                {
   4.538 -                    Debug.WriteLine("WM_INPUT source device is HID.");
   4.539 -                    //Get Usage Page and Usage
   4.540 -                    Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage ID: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
   4.541 -
   4.542 -
   4.543 -                    preParsedData = RawInput.GetPreParsedData(rawInput.header.hDevice);
   4.544 -
   4.545 -                    //
   4.546 -                    HidUsageHandler usagePageHandler=null;
   4.547 -
   4.548 -                    //Check if this an MCE remote HID message
   4.549 -                    if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.MceRemote && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdMce.MceRemote)
   4.550 -                    {                        
   4.551 -                        usagePageHandler = HidMceRemoteHandler;
   4.552 -                    }
   4.553 -                    //Check if this is a consumer control HID message
   4.554 -                    else if (deviceInfo.hid.usUsagePage == (ushort)Hid.UsagePage.Consumer && deviceInfo.hid.usUsage == (ushort)Hid.UsageIdConsumer.ConsumerControl)
   4.555 -                    {
   4.556 -                        usagePageHandler = HidConsumerDeviceHandler;
   4.557 -                    }
   4.558 -                    //Unknown HID message
   4.559 -                    else
   4.560 -                    {
   4.561 -                        Debug.WriteLine("Unknown HID message.");
   4.562 -                        return;
   4.563 -                    }
   4.564 -
   4.565 -                    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
   4.566 -                        && rawInput.hid.dwCount > 0))    //Check that we have at least one HID msg
   4.567 -                    {
   4.568 -                        return;
   4.569 -                    }
   4.570 -
   4.571 -
   4.572 -                    //Allocate a buffer for one HID input
   4.573 -                    byte[] hidInputReport = new byte[rawInput.hid.dwSizeHid];
   4.574 -
   4.575 -                    Debug.WriteLine("Raw input contains " + rawInput.hid.dwCount + " HID input report(s)");
   4.576 -
   4.577 -                    //For each HID input report in our raw input
   4.578 -                    for (int i = 0; i < rawInput.hid.dwCount; i++)
   4.579 -                    {
   4.580 -                        //Compute the address from which to copy our HID input
   4.581 -                        int hidInputOffset = 0;
   4.582 -                        unsafe
   4.583 -                        {
   4.584 -                            byte* source = (byte*)rawInputBuffer;
   4.585 -                            source += sizeof(RAWINPUTHEADER) + sizeof(RAWHID) + (rawInput.hid.dwSizeHid * i);
   4.586 -                            hidInputOffset = (int)source;
   4.587 -                        }
   4.588 -
   4.589 -                        //Copy HID input into our buffer
   4.590 -                        Marshal.Copy(new IntPtr(hidInputOffset), hidInputReport, 0, (int)rawInput.hid.dwSizeHid);
   4.591 -
   4.592 -                        //Print HID input report in our debug output
   4.593 -                        string hidDump = "HID input report: ";
   4.594 -                        foreach (byte b in hidInputReport)
   4.595 -                        {
   4.596 -                            hidDump += b.ToString("X2");
   4.597 -                        }
   4.598 -                        Debug.WriteLine(hidDump);
   4.599 -                        
   4.600 -                        //Proper parsing now
   4.601 -                        uint usageCount = 1; //Assuming a single usage per input report. Is that correct?
   4.602 -                        Win32.USAGE_AND_PAGE[] usages = new Win32.USAGE_AND_PAGE[usageCount];
   4.603 -                        Win32.HidStatus status = Win32.Function.HidP_GetUsagesEx(Win32.HIDP_REPORT_TYPE.HidP_Input, 0, usages, ref usageCount, preParsedData, hidInputReport, (uint)hidInputReport.Length);
   4.604 -                        if (status != Win32.HidStatus.HIDP_STATUS_SUCCESS)
   4.605 -                        {
   4.606 -                            Debug.WriteLine("Could not parse HID data!");
   4.607 -                        }
   4.608 -                        else
   4.609 -                        {
   4.610 -                            Debug.WriteLine("UsagePage: 0x" + usages[0].UsagePage.ToString("X4"));
   4.611 -                            Debug.WriteLine("Usage: 0x" + usages[0].Usage.ToString("X4"));
   4.612 -                            //Call on our Usage Page handler
   4.613 -                            usagePageHandler(usages[0].Usage);
   4.614 -                        }
   4.615 -                    }
   4.616 -
   4.617 -                }
   4.618 -                else if (rawInput.header.dwType == Const.RIM_TYPEMOUSE)
   4.619 -                {
   4.620 -                    Debug.WriteLine("WM_INPUT source device is Mouse.");
   4.621 -                    // do mouse handling...
   4.622 -                }
   4.623 -                else if (rawInput.header.dwType == Const.RIM_TYPEKEYBOARD)
   4.624 -                {
   4.625 -                    Debug.WriteLine("WM_INPUT source device is Keyboard.");
   4.626 -                    // do keyboard handling...
   4.627 -                    Debug.WriteLine("Type: " + deviceInfo.keyboard.dwType.ToString());
   4.628 -                    Debug.WriteLine("SubType: " + deviceInfo.keyboard.dwSubType.ToString());
   4.629 -                    Debug.WriteLine("Mode: " + deviceInfo.keyboard.dwKeyboardMode.ToString());
   4.630 -                    Debug.WriteLine("Number of function keys: " + deviceInfo.keyboard.dwNumberOfFunctionKeys.ToString());
   4.631 -                    Debug.WriteLine("Number of indicators: " + deviceInfo.keyboard.dwNumberOfIndicators.ToString());
   4.632 -                    Debug.WriteLine("Number of keys total: " + deviceInfo.keyboard.dwNumberOfKeysTotal.ToString());
   4.633 -                }
   4.634 -            }
   4.635 -            finally
   4.636 -            {
   4.637 -                //Always executed when leaving our try block
   4.638 -                Marshal.FreeHGlobal(rawInputBuffer);
   4.639 -                Marshal.FreeHGlobal(preParsedData);
   4.640 -            }
   4.641 -		}
   4.642 -	}
   4.643 -}
     5.1 --- a/RemoteControlSample.csproj	Sat Dec 06 13:14:16 2014 +0100
     5.2 +++ b/RemoteControlSample.csproj	Sat Dec 06 21:52:45 2014 +0100
     5.3 @@ -127,8 +127,9 @@
     5.4      <Compile Include="Form1.cs">
     5.5        <SubType>Form</SubType>
     5.6      </Compile>
     5.7 +    <Compile Include="HidEvent.cs" />
     5.8 +    <Compile Include="HidUsageTables.cs" />
     5.9      <Compile Include="HidUtil.cs" />
    5.10 -    <Compile Include="HumanInterfaceDevice.cs" />
    5.11      <Compile Include="RawInput.cs" />
    5.12      <Compile Include="RemoteControlDevice.cs">
    5.13        <SubType>Code</SubType>