More cleanup and re-org.
authorsl
Fri, 07 Nov 2014 22:12:22 +0100
changeset 1017f8421146ba
parent 9 94850bfc12b5
child 11 2ff6dbe0d356
More cleanup and re-org.
RawInput.cs
RemoteControlDevice.cs
RemoteControlSample.csproj
Win32RawInput.cs
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/RawInput.cs	Fri Nov 07 22:12:22 2014 +0100
     1.3 @@ -0,0 +1,94 @@
     1.4 +using System;
     1.5 +using System.Runtime.InteropServices;
     1.6 +using System.Diagnostics;
     1.7 +
     1.8 +
     1.9 +namespace Win32
    1.10 +{
    1.11 +    static class RawInput
    1.12 +    {
    1.13 +        /// <summary>
    1.14 +        /// 
    1.15 +        /// </summary>
    1.16 +        /// <param name="aRawInputHandle"></param>
    1.17 +        /// <param name="aRawInput"></param>
    1.18 +        /// <param name="rawInputBuffer">Caller must free up memory on the pointer using Marshal.FreeHGlobal</param>
    1.19 +        /// <returns></returns>
    1.20 +        public static bool GetRawInputData(IntPtr aRawInputHandle, ref RAWINPUT aRawInput, ref IntPtr rawInputBuffer)
    1.21 +        {
    1.22 +            bool success = true;
    1.23 +            rawInputBuffer = IntPtr.Zero;
    1.24 +
    1.25 +            try
    1.26 +            {
    1.27 +                uint dwSize = 0;
    1.28 +                uint sizeOfHeader = (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
    1.29 +
    1.30 +                //Get the size of our raw input data.
    1.31 +                Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, IntPtr.Zero, ref dwSize, sizeOfHeader);
    1.32 +
    1.33 +                //Allocate a large enough buffer
    1.34 +                 rawInputBuffer = Marshal.AllocHGlobal((int)dwSize);
    1.35 +
    1.36 +                //Now read our RAWINPUT data
    1.37 +                if (Win32.Function.GetRawInputData(aRawInputHandle, Const.RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
    1.38 +                {
    1.39 +                    return false;
    1.40 +                }
    1.41 +
    1.42 +                //Cast our buffer
    1.43 +                aRawInput = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
    1.44 +            }
    1.45 +            catch
    1.46 +            {
    1.47 +                Debug.WriteLine("GetRawInputData failed!");
    1.48 +                success = false;
    1.49 +            }
    1.50 +
    1.51 +            return success;
    1.52 +        }
    1.53 +
    1.54 +        /// <summary>
    1.55 +        /// 
    1.56 +        /// </summary>
    1.57 +        /// <param name="aRawInputHandle"></param>
    1.58 +        /// <param name="aUsagePage"></param>
    1.59 +        /// <param name="aUsage"></param>
    1.60 +        /// <returns></returns>
    1.61 +        public static bool GetDeviceInfo(IntPtr hDevice, ref RID_DEVICE_INFO deviceInfo)
    1.62 +        {
    1.63 +            bool success = true;
    1.64 +            IntPtr deviceInfoBuffer = IntPtr.Zero;
    1.65 +            try
    1.66 +            {
    1.67 +                //Get Device Info
    1.68 +                uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
    1.69 +                deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
    1.70 +
    1.71 +                int res = Win32.Function.GetRawInputDeviceInfo(hDevice, Const.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
    1.72 +                if (res <= 0)
    1.73 +                {
    1.74 +                    Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
    1.75 +                    return false;
    1.76 +                }
    1.77 +
    1.78 +                //Cast our buffer
    1.79 +                deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
    1.80 +            }
    1.81 +            catch
    1.82 +            {
    1.83 +                Debug.WriteLine("GetRawInputData failed!");
    1.84 +                success = false;
    1.85 +            }
    1.86 +            finally
    1.87 +            {
    1.88 +                //Always executes, prevents memory leak
    1.89 +                Marshal.FreeHGlobal(deviceInfoBuffer);
    1.90 +            }
    1.91 +
    1.92 +            
    1.93 +            return success;
    1.94 +        }
    1.95 +
    1.96 +    }
    1.97 +}
    1.98 \ No newline at end of file
     2.1 --- a/RemoteControlDevice.cs	Fri Nov 07 20:49:51 2014 +0100
     2.2 +++ b/RemoteControlDevice.cs	Fri Nov 07 22:12:22 2014 +0100
     2.3 @@ -145,9 +145,6 @@
     2.4  		private const int APPCOMMAND_MEDIA_CHANNEL_UP   = 51;
     2.5  		private const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52;
     2.6  
     2.7 -		private const int RID_INPUT						= 0x10000003;
     2.8 -		private const int RID_HEADER					= 0x10000005;
     2.9 -
    2.10  		private const int FAPPCOMMAND_MASK				= 0xF000;
    2.11  		private const int FAPPCOMMAND_MOUSE				= 0x8000;
    2.12  		private const int FAPPCOMMAND_KEY				= 0;
    2.13 @@ -349,42 +346,25 @@
    2.14  		{
    2.15              Debug.WriteLine("================WM_INPUT================");
    2.16  
    2.17 -			uint dwSize = 0;
    2.18  
    2.19 -            uint sizeOfHeader=(uint)Marshal.SizeOf(typeof(RAWINPUTHEADER));
    2.20 +            //Declare a pointer
    2.21 +            IntPtr rawInputBuffer = IntPtr.Zero;
    2.22  
    2.23 -            //Get the size of our raw input data.
    2.24 -			Win32.Function.GetRawInputData(message.LParam,	RID_INPUT, IntPtr.Zero,	ref dwSize,	sizeOfHeader);
    2.25 -
    2.26 -            //Allocate a large enough buffer
    2.27 -			IntPtr rawInputBuffer = Marshal.AllocHGlobal((int) dwSize);
    2.28 -			try
    2.29 -			{
    2.30 -				if(rawInputBuffer == IntPtr.Zero)
    2.31 -					return;
    2.32 -
    2.33 -                //Now read our RAWINPUT data
    2.34 -                if (Win32.Function.GetRawInputData(message.LParam, RID_INPUT, rawInputBuffer, ref dwSize, (uint)Marshal.SizeOf(typeof(RAWINPUTHEADER))) != dwSize)
    2.35 -				{
    2.36 -					return;
    2.37 -				}
    2.38 -
    2.39 -                //Cast our buffer
    2.40 -                RAWINPUT raw = (RAWINPUT)Marshal.PtrToStructure(rawInputBuffer, typeof(RAWINPUT));
    2.41 -
    2.42 -                //Get Device Info
    2.43 -                uint deviceInfoSize = (uint)Marshal.SizeOf(typeof(RID_DEVICE_INFO));
    2.44 -                IntPtr deviceInfoBuffer = Marshal.AllocHGlobal((int)deviceInfoSize);
    2.45 -
    2.46 -                int res = Win32.Function.GetRawInputDeviceInfo(raw.header.hDevice, Const.RIDI_DEVICEINFO, deviceInfoBuffer, ref deviceInfoSize);
    2.47 -                if (res <= 0)
    2.48 +            try
    2.49 +            {
    2.50 +                //Fetch raw input
    2.51 +                RAWINPUT raw = new RAWINPUT();
    2.52 +                if (!RawInput.GetRawInputData(message.LParam, ref raw, ref rawInputBuffer))
    2.53                  {
    2.54 -                    Debug.WriteLine("WM_INPUT could not read device info: " + Marshal.GetLastWin32Error().ToString());
    2.55                      return;
    2.56                  }
    2.57  
    2.58 -                //Cast our buffer
    2.59 -                RID_DEVICE_INFO deviceInfo = (RID_DEVICE_INFO)Marshal.PtrToStructure(deviceInfoBuffer, typeof(RID_DEVICE_INFO));
    2.60 +                //Fetch device info
    2.61 +                RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO();
    2.62 +                if (!RawInput.GetDeviceInfo(raw.header.hDevice, ref deviceInfo))
    2.63 +                {
    2.64 +                    return;
    2.65 +                }
    2.66  
    2.67                  //Check type of input device and quite if we don't like it
    2.68                  switch (deviceInfo.dwType)
    2.69 @@ -406,11 +386,15 @@
    2.70                  //Get Usage Page and Usage
    2.71                  Debug.WriteLine("Usage Page: 0x" + deviceInfo.hid.usUsagePage.ToString("X4") + " Usage: 0x" + deviceInfo.hid.usUsage.ToString("X4"));
    2.72  
    2.73 -                //Check that our raw input is HID
    2.74 -                if (raw.header.dwType == Const.RIM_TYPEHID && raw.hid.dwSizeHid>0)
    2.75 -				{
    2.76 +
    2.77 +                if (raw.header.dwType == Const.RIM_TYPEHID  //Check that our raw input is HID
    2.78 +                    && 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.79 +                    && raw.hid.dwCount > 0)     //Check that we have at least one HID msg
    2.80 +                {
    2.81 +                    //TODO: for each HID message
    2.82 +
    2.83                      //Allocate a buffer for one HID message
    2.84 -					byte[] bRawData = new byte[raw.hid.dwSizeHid];
    2.85 +                    byte[] bRawData = new byte[raw.hid.dwSizeHid];
    2.86  
    2.87                      //Compute the address from which to copy our HID message
    2.88                      int pRawData = 0;
    2.89 @@ -434,6 +418,7 @@
    2.90                      }
    2.91                      Debug.WriteLine(hidDump);
    2.92  
    2.93 +
    2.94                      //Make sure both usage page and usage are matching MCE remote
    2.95                      if (deviceInfo.hid.usUsagePage != (ushort)Hid.UsagePage.MceRemote || deviceInfo.hid.usUsage != (ushort)Hid.UsageId.MceRemoteUsage)
    2.96                      {
    2.97 @@ -441,27 +426,28 @@
    2.98                          return;
    2.99                      }
   2.100  
   2.101 -                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData!=0) //Our button is a known MCE button
   2.102 +                    if (Enum.IsDefined(typeof(MceButton), rawData) && rawData != 0) //Our button is a known MCE button
   2.103                      {
   2.104                          if (this.ButtonPressed != null) //What's that?
   2.105                          {
   2.106                              this.ButtonPressed(this, new RemoteControlEventArgs((MceButton)rawData, GetDevice(message.LParam.ToInt32())));
   2.107                          }
   2.108                      }
   2.109 -				}
   2.110 -				else if(raw.header.dwType == Const.RIM_TYPEMOUSE)
   2.111 -				{
   2.112 -					// do mouse handling...
   2.113 -				}
   2.114 -				else if(raw.header.dwType == Const.RIM_TYPEKEYBOARD)
   2.115 -				{
   2.116 -					// do keyboard handling...
   2.117 -				}
   2.118 -			}
   2.119 -			finally
   2.120 -			{
   2.121 -				Marshal.FreeHGlobal(rawInputBuffer);
   2.122 -			}
   2.123 +                }
   2.124 +                else if (raw.header.dwType == Const.RIM_TYPEMOUSE)
   2.125 +                {
   2.126 +                    // do mouse handling...
   2.127 +                }
   2.128 +                else if (raw.header.dwType == Const.RIM_TYPEKEYBOARD)
   2.129 +                {
   2.130 +                    // do keyboard handling...
   2.131 +                }
   2.132 +            }
   2.133 +            finally
   2.134 +            {
   2.135 +                //Always executed when leaving our try block
   2.136 +                Marshal.FreeHGlobal(rawInputBuffer);
   2.137 +            }
   2.138  		}
   2.139  
   2.140  
     3.1 --- a/RemoteControlSample.csproj	Fri Nov 07 20:49:51 2014 +0100
     3.2 +++ b/RemoteControlSample.csproj	Fri Nov 07 22:12:22 2014 +0100
     3.3 @@ -128,6 +128,7 @@
     3.4        <SubType>Form</SubType>
     3.5      </Compile>
     3.6      <Compile Include="HumanInterfaceDevice.cs" />
     3.7 +    <Compile Include="RawInput.cs" />
     3.8      <Compile Include="RemoteControlDevice.cs">
     3.9        <SubType>Code</SubType>
    3.10      </Compile>
     4.1 --- a/Win32RawInput.cs	Fri Nov 07 20:49:51 2014 +0100
     4.2 +++ b/Win32RawInput.cs	Fri Nov 07 22:12:22 2014 +0100
     4.3 @@ -45,6 +45,10 @@
     4.4          /// </summary>
     4.5          public const uint RIM_TYPEHID = 2;
     4.6  
     4.7 +        public const int RID_INPUT = 0x10000003;
     4.8 +        public const int RID_HEADER = 0x10000005;
     4.9 +
    4.10 +
    4.11      }
    4.12  
    4.13